ERC-721 可暂停
具有可暂停的 token 转移、铸造和销毁的 ERC721 token。
适用于诸如在评估期结束之前阻止交易,或者具有用于冻结所有 token 转移的紧急开关等场景,例如由错误引起的。
用法
为了使您的 ERC721 token pausable
,您需要使用 Pausable
合约,并将它的机制应用到 ERC721 token 函数,如下所示:
use openzeppelin_stylus::{
token::erc721::{self, Erc721, IErc721},
utils::{introspection::erc165::IErc165, pausable, IPausable, Pausable},
};
#[derive(SolidityError, Debug)]
enum Error {
InvalidOwner(erc721::ERC721InvalidOwner),
NonexistentToken(erc721::ERC721NonexistentToken),
IncorrectOwner(erc721::ERC721IncorrectOwner),
InvalidSender(erc721::ERC721InvalidSender),
InvalidReceiver(erc721::ERC721InvalidReceiver),
InvalidReceiverWithReason(erc721::InvalidReceiverWithReason),
InsufficientApproval(erc721::ERC721InsufficientApproval),
InvalidApprover(erc721::ERC721InvalidApprover),
InvalidOperator(erc721::ERC721InvalidOperator),
EnforcedPause(pausable::EnforcedPause),
ExpectedPause(pausable::ExpectedPause),
}
impl From<erc721::Error> for Error {
fn from(value: erc721::Error) -> Self {
match value {
erc721::Error::InvalidOwner(e) => Error::InvalidOwner(e),
erc721::Error::NonexistentToken(e) => Error::NonexistentToken(e),
erc721::Error::IncorrectOwner(e) => Error::IncorrectOwner(e),
erc721::Error::InvalidSender(e) => Error::InvalidSender(e),
erc721::Error::InvalidReceiver(e) => Error::InvalidReceiver(e),
erc721::Error::InvalidReceiverWithReason(e) => {
Error::InvalidReceiverWithReason(e)
}
erc721::Error::InsufficientApproval(e) => {
Error::InsufficientApproval(e)
}
erc721::Error::InvalidApprover(e) => Error::InvalidApprover(e),
erc721::Error::InvalidOperator(e) => Error::InvalidOperator(e),
}
}
}
impl From<pausable::Error> for Error {
fn from(value: pausable::Error) -> Self {
match value {
pausable::Error::EnforcedPause(e) => Error::EnforcedPause(e),
pausable::Error::ExpectedPause(e) => Error::ExpectedPause(e),
}
}
}
#[entrypoint]
#[storage]
struct Erc721Example {
erc721: Erc721,
pausable: Pausable,
}
#[public]
#[implements(IErc721<Error = Error>, IPausable, IErc165)]
impl Erc721Example {
fn mint(&mut self, to: Address, token_id: U256) -> Result<(), Error> {
// ...
self.pausable.when_not_paused()?;
// ...
self.erc721._mint(to, token_id)?;
Ok(())
}
}
#[public]
impl IErc721 for Erc721Example {
type Error = Error;
fn balance_of(&self, owner: Address) -> Result<U256, Self::Error> {
Ok(self.erc721.balance_of(owner)?)
}
fn owner_of(&self, token_id: U256) -> Result<Address, Self::Error> {
Ok(self.erc721.owner_of(token_id)?)
}
fn safe_transfer_from(
&mut self,
from: Address,
to: Address,
token_id: U256,
) -> Result<(), Error> {
// ...
self.pausable.when_not_paused()?;
// ...
self.erc721.safe_transfer_from(from, to, token_id)?;
Ok(())
}
#[selector(name = "safeTransferFrom")]
fn safe_transfer_from_with_data(
&mut self,
from: Address,
to: Address,
token_id: U256,
data: Bytes,
) -> Result<(), Error> {
// ...
self.pausable.when_not_paused()?;
// ...
self.erc721.safe_transfer_from_with_data(from, to, token_id, data)?;
Ok(())
}
fn transfer_from(
&mut self,
from: Address,
to: Address,
token_id: U256,
) -> Result<(), Error> {
// ...
self.pausable.when_not_paused()?;
// ...
self.erc721.transfer_from(from, to, token_id)?;
Ok(())
}
fn approve(
&mut self,
to: Address,
token_id: U256,
) -> Result<(), Self::Error> {
Ok(self.erc721.approve(to, token_id)?)
}
fn set_approval_for_all(
&mut self,
to: Address,
approved: bool,
) -> Result<(), Self::Error> {
Ok(self.erc721.set_approval_for_all(to, approved)?)
}
fn get_approved(&self, token_id: U256) -> Result<Address, Self::Error> {
Ok(self.erc721.get_approved(token_id)?)
}
fn is_approved_for_all(&self, owner: Address, operator: Address) -> bool {
self.erc721.is_approved_for_all(owner, operator)
}
}
#[public]
impl IPausable for Erc721Example {
fn paused(&self) -> bool {
self.pausable.paused()
}
}
#[public]
impl IErc165 for Erc721Example {
fn supports_interface(&self, interface_id: B32) -> bool {
self.erc721.supports_interface(interface_id)
}
}