创建 ERC20 供应量
在 Starknet 上构建的代币所实现的标准接口来自 Ethereum 上流行的代币标准,称为 ERC20。 EIP20,ERC20 合约由此派生,但未指定如何创建代币。 本指南将介绍创建固定和动态代币供应量的策略。
固定供应量
假设我们要创建一个名为 MyToken
的代币,它具有固定的代币供应量。
我们可以通过在构造函数中设置代币供应量来实现这一点,构造函数将在部署时执行。
#[starknet::contract]
mod MyToken {
use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
use starknet::ContractAddress;
component!(path: ERC20Component, storage: erc20, event: ERC20Event);
// ERC20 Mixin
#[abi(embed_v0)]
impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
#[storage]
struct Storage {
#[substorage(v0)]
erc20: ERC20Component::Storage
}
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC20Event: ERC20Component::Event
}
#[constructor]
fn constructor(
ref self: ContractState,
fixed_supply: u256,
recipient: ContractAddress
) {
let name = "MyToken";
let symbol = "MTK";
self.erc20.initializer(name, symbol);
self.erc20.mint(recipient, fixed_supply);
}
}
在构造函数中,我们首先调用 ERC20 初始化器来设置代币名称和符号。
接下来,我们调用内部 mint
函数,该函数创建 fixed_supply
的代币并将它们分配给 recipient
。
由于内部 mint
未在我们的合约中公开,因此不可能创建更多代币。
换句话说,我们已经实现了一个固定的代币供应量!
动态供应量
具有动态供应量的 ERC20 合约包括创建或销毁代币的机制。
让我们对强大的 MyToken
合约进行一些更改,并创建一个铸币机制。
#[starknet::contract]
mod MyToken {
use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
use starknet::ContractAddress;
component!(path: ERC20Component, storage: erc20, event: ERC20Event);
// ERC20 Mixin
#[abi(embed_v0)]
impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
#[storage]
struct Storage {
#[substorage(v0)]
erc20: ERC20Component::Storage
}
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC20Event: ERC20Component::Event
}
#[constructor]
fn constructor(ref self: ContractState) {
let name = "MyToken";
let symbol = "MTK";
self.erc20.initializer(name, symbol);
}
#[external(v0)]
fn mint(
ref self: ContractState,
recipient: ContractAddress,
amount: u256
) {
// 此函数未受保护,这意味着
// 任何人都可以铸造代币
self.erc20.mint(recipient, amount);
}
}
上面公开的 mint
将创建 amount
个代币并将它们分配给 recipient
。
我们现在有了铸币机制!
但是,存在一个大问题。
mint
不包括对谁可以调用此函数的任何限制。
为了良好实践,让我们使用 Ownable
实现一个简单的权限机制。
#[starknet::contract]
mod MyToken {
(...)
// 集成 Ownable
#[external(v0)]
fn mint(
ref self: ContractState,
recipient: ContractAddress,
amount: u256
) {
// 使用 Ownable 设置权限
self.ownable.assert_only_owner();
// 如果由合约所有者调用,则铸造代币
self.erc20.mint(recipient, amount);
}
}
在构造函数中,我们传递所有者地址以设置 MyToken
合约的所有者。
mint
函数包含 assert_only_owner
,这将确保只有合约所有者可以调用此函数。
现在,我们有了一个受保护的 ERC20 铸币机制来创建动态代币供应量。
有关权限机制的更详尽解释,请参见 访问控制。 |