ERC-20 Capped

Extension of ERC-20 that adds a cap to the supply of tokens.

Usage

In order to make ERC-20 Capped methods supervising the supply of tokens, you need to add them by yourself for your final contract as follows:

use openzeppelin_stylus::{
    token::erc20::{
        extensions::{capped, Capped},
        Erc20, IErc20,
    }
};

sol_storage! {
    #[entrypoint]
    struct Erc20Example {
        #[borrow]
        Erc20 erc20;
        #[borrow]
        Capped capped;
    }
}

#[external]
#[inherit(Erc20, Capped)]
impl Erc20Example {
    // Add token minting feature.
    //
    // Make sure to handle `Capped` properly. You should not call
    // [`Erc20::_update`] to mint tokens -- it will the break `Capped`
    // mechanism.
    pub fn mint(
        &mut self,
        account: Address,
        value: U256,
    ) -> Result<(), Vec<u8>> {
        self.pausable.when_not_paused()?;
        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(())
    }
}

Additionally, you need to ensure proper initialization during contract deployment. Make sure to include the following code in your Solidity Constructor:

contract Erc20Example {
    // ...

    uint256 private _cap;

    error ERC20InvalidCap(uint256 cap);

    constructor(uint256 cap_) {
        // ...
        if (cap_ == 0) {
            revert ERC20InvalidCap(0);
        }

        _cap = cap_;

        // ...
    }
}