ERC-20 Pausable

ERC20 token with pausable token transfers, minting, and burning.

Useful for scenarios such as preventing trades until the end of an evaluation period, or having an emergency switch for freezing all token transfers in the event of a large bug.

Usage

In order to make your ERC20 token pausable, you need to use the Pausable contract and apply its mechanisms to ERC20 token functions as follows:

use openzeppelin_stylus::
    token::erc20::{self, Erc20, IErc20,
    utils::pausable, IPausable, Pausable,
};

#[derive(SolidityError, Debug)]
enum Error 
    InsufficientBalance(erc20::ERC20InsufficientBalance),
    InvalidSender(erc20::ERC20InvalidSender),
    InvalidReceiver(erc20::ERC20InvalidReceiver),
    InsufficientAllowance(erc20::ERC20InsufficientAllowance),
    InvalidSpender(erc20::ERC20InvalidSpender),
    InvalidApprover(erc20::ERC20InvalidApprover),
    EnforcedPause(pausable::EnforcedPause),
    ExpectedPause(pausable::ExpectedPause),


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),
        }
    }
}

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 Erc20Example 
    erc20: Erc20,
    pausable: Pausable,


#[public]
#[implements(IErc20<Error = Error>, IPausable)]
impl Erc20Example 
    fn mint(&mut self, account: Address, value: U256) -> Result<(), Error> {
        // ...
        self.pausable.when_not_paused()?;
        // ...
        self.erc20._mint(account, value)?;
        Ok(())
    
}

#[public]
impl IErc20 for Erc20Example 
    type Error = Error;

    fn transfer(&mut self, to: Address, value: U256) -> Result<bool, Error> {
        // ...
        self.pausable.when_not_paused()?;
        // ...
        let result = self.erc20.transfer(to, value)?;
        // ...
        Ok(result)
    

    fn transfer_from(
        &mut self,
        from: Address,
        to: Address,
        value: U256,
    ) -> Result<bool, Error> 
        // ...
        self.pausable.when_not_paused()?;
        // ...
        let result = self.erc20.transfer_from(from, to, value)?;
        // ...
        Ok(result)
    

    fn total_supply(&self) -> U256 
        self.erc20.total_supply()
    

    fn balance_of(&self, account: Address) -> U256 
        self.erc20.balance_of(account)
    

    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)?)
    
}

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

On this page