ERC-20 许可
添加了 permit
方法,该方法可用于更改帐户的 ERC20 授权额度(参见 IErc20::allowance
),方法是出示由帐户签名的消息。通过不依赖于 IErc20::approve
,token 持有者帐户不需要发送交易,因此根本不需要持有 Ether 。
用法
为了拥有 ERC-20 Permit
token,您只需要使用此合约,而无需使用 ERC-20,如下所示:
use openzeppelin_stylus::{
token::erc20::{
extensions::{permit, Erc20Permit, IErc20Permit},
Erc20, IErc20,
},
utils::{
cryptography::eip712::IEip712,
nonces::{INonces, Nonces},
},
};
#[entrypoint]
#[storage]
struct Erc20PermitExample {
erc20: Erc20,
nonces: Nonces,
erc20_permit: Erc20Permit<Eip712>,
}
#[storage]
struct Eip712;
impl IEip712 for Eip712 {
const NAME: &'static str = "ERC-20 Permit Example";
const VERSION: &'static str = "1";
}
#[public]
#[implements(IErc20<Error = permit::Error>, INonces, IErc20Permit<Error = permit::Error>)]
impl Erc20PermitExample {
// 添加 token 铸造功能。
fn mint(
&mut self,
account: Address,
value: U256,
) -> Result<(), permit::Error> {
Ok(self.erc20._mint(account, value)?)
}
}
#[public]
impl INonces for Erc20PermitExample {
fn nonces(&self, owner: Address) -> U256 {
self.nonces.nonces(owner)
}
}
#[public]
impl IErc20Permit for Erc20PermitExample {
type Error = permit::Error;
#[selector(name = "DOMAIN_SEPARATOR")]
fn domain_separator(&self) -> B256 {
self.erc20_permit.domain_separator()
}
fn permit(
&mut self,
owner: Address,
spender: Address,
value: U256,
deadline: U256,
v: u8,
r: B256,
s: B256,
) -> Result<(), Self::Error> {
self.erc20_permit.permit(
owner,
spender,
value,
deadline,
v,
r,
s,
&mut self.erc20,
&mut self.nonces,
)
}
}
#[public]
impl IErc20 for Erc20PermitExample {
type Error = permit::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)?)
}
}