Skip to main content

Move example

example

ERC20

在 Move 语言中实现一个 ERC20 代币标准并添加详细的代码注释可以帮助理解每个部分的功能和目的。以下是一个简单的 Move ERC20 代币实现的示例,包括注释来解释各部分代码的作用:

address 0x1 {
module Token {
// 定义一个资源类型`Token`,包含总供应量
struct Token has store {
total_supply: u128,
}

// 定义一个资源类型`Balance`,用于追踪每个账户的代币余额
struct Balance has key, store {
value: u128,
}

// 初始化代币,设置初始供应量,并将全部代币分配给初始账户
public fun initialize(sender: &signer, initial_supply: u128) {
// 将`Token`和初始供应量绑定到调用者账户
move_to(sender, Token { total_supply: initial_supply });
// 将初始代币余额绑定到调用者账户
move_to(sender, Balance { value: initial_supply });
}

// 查询指定账户的代币余额
public fun balance_of(account: &signer): u128 {
// 从指定账户获取`Balance`资源,并返回余额
borrow_global<Balance>(Signer::address_of(account)).value
}

// 从调用者账户向另一个账户转移代币
public fun transfer(sender: &signer, recipient: address, amount: u128) acquires Balance {
let sender_balance = borrow_global_mut<Balance>(Signer::address_of(sender));
let recipient_balance = borrow_global_mut<Balance>(recipient);

// 检查发送者余额是否足够
assert(sender_balance.value >= amount, 42);

// 执行代币转移
sender_balance.value = sender_balance.value - amount;
recipient_balance.value = recipient_balance.value + amount;
}

// 创建新代币并增加到总供应量
public fun mint(account: &signer, amount: u128) acquires Token, Balance {
let token = borrow_global_mut<Token>(Signer::address_of(account));
let balance = borrow_global_mut<Balance>(Signer::address_of(account));

// 增加总供应量和账户余额
token.total_supply = token.total_supply + amount;
balance.value = balance.value + amount;
}

// 销毁代币并从总供应量中扣除
public fun burn(account: &signer, amount: u128) acquires Token, Balance {
let token = borrow_global_mut<Token>(Signer::address_of(account));
let balance = borrow_global_mut<Balance>(Signer::address_of(account));

// 检查账户余额是否足够
assert(balance.value >= amount, 42);

// 减少总供应量和账户余额
token.total_supply = token.total_supply - amount;
balance.value = balance.value - amount;
}
}
}

代码解释

  1. Token 结构体:定义了一个包含 total_supply 的资源,代表代币的总供应量。
  2. Balance 结构体:为每个账户定义了一个 Balance 资源,用于追踪其代币余额。
  3. initialize 函数:用于初始化代币,设置初始供应量,并将所有代币分配给初始账户(通常是合约部署者)。
  4. balance_of 函数:允许查询任何账户的代币余额。
  5. transfer 函数:实现了代币的转账功能,从一个账户向另一个账户转移指定数量的代币。
  6. mint 函数:用于增发新的代币,同时增加总供应量和指定账户的余额。
  7. burn 函数:用于销毁代币,减少总供应量和指定账户的余额。

这个简单的 ERC20 实现提供了基本的代币功能,包括初始化、余额查询、转账、增发和销毁。在实际部署之前,应进行彻底的测试和审查以确保安全性和正确性。

这个 burn 与 结构体上的 drop 冲突吗?

在 Move 语言中,drop 是一个内置的函数,用于销毁一个资源类型的实例。这个操作是不可逆的,一旦执行,就会彻底移除资源实例,并且无法恢复。这与 burn 函数的概念相似,因为 burn 也是用来永久地移除代币,减少总供应量。

然而,drop 通常用于整个资源实例,而不是资源的一部分。在 Move 中,代币通常被建模为一种资源,其数量是该资源的一个字段。当你想要 "燃烧" 一定数量的代币时,你实际上是在更新该资源的一个字段,而不是销毁整个资源实例。

因此,burn 函数和 drop 操作在概念上不冲突,因为它们用于不同的目的:

  • burn 函数:用于更新代币资源的状态,减少代币数量,但不销毁整个资源。
  • drop 操作:用于销毁整个资源实例,这在 Move 中通常发生在资源不再需要时,比如一个账户被关闭,或者一个合约被废弃。

在你的代币合约中,burn 函数应该只减少代币的数量,而不是销毁整个代币资源实例。你的 burn 函数应该调整代币资源内部的 total_supplybalances 字段,而不是直接使用 drop。这样,你就可以精确地控制燃烧的数量,而不是完全移除代币资源。