ERC-20 Permit

Adds the permit method, which can be used to change an account’s ERC20 allowance (see IErc20::allowance) by presenting a message signed by the account. By not relying on IErc20::approve, the token holder account doesn’t need to send a transaction, and thus is not required to hold Ether at all.

Usage

In order to have ERC-20 Permit token, you need to use only this contract without ERC-20 as follows:

use openzeppelin_stylus::{
    token::erc20::{
        extensions::{permit, Erc20Permit},
        Erc20,
    },
    utils::{cryptography::eip712::IEip712, nonces::Nonces},
};

#[entrypoint]
#[storage]
struct Erc20PermitExample {
    #[borrow]
    erc20: Erc20,
    #[borrow]
    nonces: Nonces,
    #[borrow]
    erc20_permit: Erc20Permit<Eip712>,
}

#[storage]
struct Eip712;

// Define `NAME` and `VERSION` for your contract.
impl IEip712 for Eip712 {
    const NAME: &'static str = "ERC-20 Permit Example";
    const VERSION: &'static str = "1";
}

#[public]
#[inherit(Erc20, Nonces, Erc20Permit<Eip712>)]
impl Erc20PermitExample {
    // Add token minting feature.
    fn mint(
        &mut self,
        account: Address,
        value: U256,
    ) -> Result<(), permit::Error> {
        Ok(self.erc20._mint(account, value)?)
    }

    #[allow(clippy::too_many_arguments)]
    fn permit(
        &mut self,
        owner: Address,
        spender: Address,
        value: U256,
        deadline: U256,
        v: u8,
        r: B256,
        s: B256,
    ) -> Result<(), permit::Error> {
        self.erc20_permit.permit(
            owner,
            spender,
            value,
            deadline,
            v,
            r,
            s,
            &mut self.erc20,
            &mut self.nonces,
        )
    }
}