ERC-20 带有上限
ERC-20 的扩展,为token的供应量增加了一个上限。
用法
为了让 ERC-20 Capped
方法监督token的供应,您需要像下面这样为您最终的合约添加它们:
use openzeppelin_stylus::token::erc20::{
self,
extensions::{capped, Capped, ICapped},
Erc20, IErc20,
};
#[derive(SolidityError, Debug)]
enum Error {
ExceededCap(capped::ERC20ExceededCap),
InvalidCap(capped::ERC20InvalidCap),
InsufficientBalance(erc20::ERC20InsufficientBalance),
InvalidSender(erc20::ERC20InvalidSender),
InvalidReceiver(erc20::ERC20InvalidReceiver),
InsufficientAllowance(erc20::ERC20InsufficientAllowance),
InvalidSpender(erc20::ERC20InvalidSpender),
InvalidApprover(erc20::ERC20InvalidApprover),
}
impl From<capped::Error> for Error {
fn from(value: capped::Error) -> Self {
match value {
capped::Error::ExceededCap(e) => Error::ExceededCap(e),
capped::Error::InvalidCap(e) => Error::InvalidCap(e),
}
}
}
impl From<erc20::Error> for Error {
fn from(value: erc20::Error) -> Self {
match value {
erc20::Error::InsufficientBalance(e) => {
Error::InsufficientBalance(e)
}
erc20::Error::InvalidSender(e) => Error::InvalidSender(e),
erc20::Error::InvalidReceiver(e) => Error::InvalidReceiver(e),
erc20::Error::InsufficientAllowance(e) => {
Error::InsufficientAllowance(e)
}
erc20::Error::InvalidSpender(e) => Error::InvalidSpender(e),
erc20::Error::InvalidApprover(e) => Error::InvalidApprover(e),
}
}
}
#[entrypoint]
#[storage]
struct Erc20Example {
erc20: Erc20,
capped: Capped,
}
#[public]
#[implements(IErc20<Error = Error>, ICapped)]
impl Erc20Example {
#[constructor]
fn constructor(&mut self, cap: U256) -> Result<(), Error> {
Ok(self.capped.constructor(cap)?)
}
// Add token minting feature.
// 添加token铸造功能。
//
// Make sure to handle `Capped` properly. You should not call
// 确保正确处理`Capped`。您不应该调用
// [`Erc20::_update`] to mint tokens -- it will break the `Capped`
// [`Erc20::_update`] 来铸造token -- 它会破坏 `Capped`
// mechanism.
// 机制。
fn mint(
&mut self,
account: Address,
value: U256,
) -> Result<(), Error> {
let max_supply = self.capped.cap();
// Overflow check required.
// 需要溢出检查。
let supply = self
.erc20
.total_supply()
.checked_add(value)
.expect("new supply should not exceed `U256::MAX`");
if supply > max_supply {
return Err(capped::Error::ExceededCap(
capped::ERC20ExceededCap {
increased_supply: supply,
cap: max_supply,
},
))?;
}
self.erc20._mint(account, value)?;
Ok(())
}
}
#[public]
impl ICapped for Erc20Example {
fn cap(&self) -> U256 {
self.capped.cap()
}
}
#[public]
impl IErc20 for Erc20Example {
type Error = Error;
fn total_supply(&self) -> U256 {
self.erc20.total_supply()
}
fn balance_of(&self, account: Address) -> U256 {
self.erc20.balance_of(account)
}
fn transfer(
&mut self,
to: Address,
value: U256,
) -> Result<bool, Self::Error> {
Ok(self.erc20.transfer(to, value)?)
}
fn allowance(&self, owner: Address, spender: Address) -> U256 {
self.erc20.allowance(owner, spender)
}
fn approve(
&mut self,
spender: Address,
value: U256,
) -> Result<bool, Self::Error> {
Ok(self.erc20.approve(spender, value)?)
}
fn transfer_from(
&mut self,
from: Address,
to: Address,
value: U256,
) -> Result<bool, Self::Error> {
Ok(self.erc20.transfer_from(from, to, value)?)
}
}