ERC-1155 可暂停的

具有可暂停的 token 转移、铸造和燃烧的 ERC-1155 token。

适用于诸如在评估期结束前阻止交易,或者在发生大型错误时使用紧急开关来冻结所有 token 转移等情况。

用法

为了使你的 ERC-1155 token pausable,你需要使用 Pausable 合约并将它的机制应用于 ERC1155 token 函数,如下所示:

use openzeppelin_stylus::{
    token::erc1155::{self, Erc1155, IErc1155},
    utils::{introspection::erc165::IErc165, pausable, IPausable, Pausable},
};

#[derive(SolidityError, Debug)]
enum Error {
    InsufficientBalance(erc1155::ERC1155InsufficientBalance),
    InvalidSender(erc1155::ERC1155InvalidSender),
    InvalidReceiver(erc1155::ERC1155InvalidReceiver),
    InvalidReceiverWithReason(erc1155::InvalidReceiverWithReason),
    MissingApprovalForAll(erc1155::ERC1155MissingApprovalForAll),
    InvalidApprover(erc1155::ERC1155InvalidApprover),
    InvalidOperator(erc1155::ERC1155InvalidOperator),
    InvalidArrayLength(erc1155::ERC1155InvalidArrayLength),
    EnforcedPause(pausable::EnforcedPause),
    ExpectedPause(pausable::ExpectedPause),
}

impl From<erc1155::Error> for Error {
    fn from(value: erc1155::Error) -> Self {
        match value {
            erc1155::Error::InsufficientBalance(e) => {
                Error::InsufficientBalance(e)
            }
            erc1155::Error::InvalidSender(e) => Error::InvalidSender(e),
            erc1155::Error::InvalidReceiver(e) => Error::InvalidReceiver(e),
            erc1155::Error::InvalidReceiverWithReason(e) => {
                Error::InvalidReceiverWithReason(e)
            }
            erc1155::Error::MissingApprovalForAll(e) => {
                Error::MissingApprovalForAll(e)
            }
            erc1155::Error::InvalidApprover(e) => Error::InvalidApprover(e),
            erc1155::Error::InvalidOperator(e) => Error::InvalidOperator(e),
            erc1155::Error::InvalidArrayLength(e) => {
                Error::InvalidArrayLength(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 Erc1155Example {
    erc1155: Erc1155,
    pausable: Pausable,
}

#[public]
#[implements(IErc1155<Error = Error>, IPausable)]
impl Erc1155Example {
    fn mint(
        &mut self,
        to: Address,
        token_id: U256,
        amount: U256,
        data: Bytes,
    ) -> Result<(), Error> {
        // ...
        self.pausable.when_not_paused()?;
        // ...
        self.erc1155._mint(to, token_id, amount, &data)?;
        Ok(())
    }

    fn mint_batch(
        &mut self,
        to: Address,
        token_ids: Vec<U256>,
        amounts: Vec<U256>,
        data: Bytes,
    ) -> Result<(), Error> {
        // ...
        self.pausable.when_not_paused()?;
        // ...
        self.erc1155._mint_batch(to, token_ids, amounts, &data)?;
        Ok(())
    }
}

#[public]
impl IPausable for Erc1155Example {
    fn paused(&self) -> bool {
        self.pausable.paused()
    }
}

#[public]
impl IErc1155 for Erc1155Example {
    type Error = Error;

    fn safe_transfer_from(
        &mut self,
        from: Address,
        to: Address,
        id: U256,
        value: U256,
        data: Bytes,
    ) -> Result<(), Self::Error> {
        // ...
        self.pausable.when_not_paused()?;
        // ...
        self.erc1155.safe_transfer_from(from, to, id, value, data)?;
        Ok(())
    }

    fn safe_batch_transfer_from(
        &mut self,
        from: Address,
        to: Address,
        ids: Vec<U256>,
        values: Vec<U256>,
        data: Bytes,
    ) -> Result<(), Self::Error> {
        // ...
        self.pausable.when_not_paused()?;
        // ...
        self.erc1155.safe_batch_transfer_from(from, to, ids, values, data)?;
        Ok(())
    }

    fn balance_of(&self, account: Address, id: U256) -> U256 {
        self.erc1155.balance_of(account, id)
    }

    fn balance_of_batch(
        &self,
        accounts: Vec<Address>,
        ids: Vec<U256>,
    ) -> Result<Vec<U256>, Self::Error> {
        Ok(self.erc1155.balance_of_batch(accounts, ids)?)
    }

    fn set_approval_for_all(
        &mut self,
        operator: Address,
        approved: bool,
    ) -> Result<(), Self::Error> {
        Ok(self.erc1155.set_approval_for_all(operator, approved)?)
    }

    fn is_approved_for_all(&self, account: Address, operator: Address) -> bool {
        self.erc1155.is_approved_for_all(account, operator)
    }
}

#[public]
impl IErc165 for Erc1155Example {
    fn supports_interface(&self, interface_id: B32) -> bool {
        self.erc1155.supports_interface(interface_id)
    }
}