I am looking at EIP-2612..

Permit mostly will be written as the following:

function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external {
        require(deadline >= block.timestamp, "token: auth expired");

        bytes32 encodeData = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline));
        _validateSignedData(owner, encodeData, v, r, s);

        _approve(owner, spender, value);

So this is good in a case where user signs a message, dapp then calls its own contract, that has the code like this:

function testFunction() {
       token.permit(owner, spender, value, deadline, v, r, s);

       token.transferFrom(spender, to/address(this), value);

Question: I was wondering what if we directly put _transfer instead of _approve in the permit function ? this way testFunction doesn't have to do transferFrom at all. Mainly I am curious why not the creators didn't come up with _transfer at the end of permit function.

  • 1
    I think permit was added as feature on top of ERC20 to make more user friendly integrations with Dex like contracts. If permit called _transfer then developers should have to change dex to permit+transfer, from the approve+transferFrom. It should work but there will be extra work for the auditors, updating contracts, frontends, look for non compliant tokens, etc. Unfortunately ERC20 is so popular that moving to a better standard is too complicated.
    – Ismael
    Jun 7, 2022 at 23:44

1 Answer 1


This is a very interesting question, and I've been pondering it for a while now.

Reading the EIP (https://eips.ethereum.org/EIPS/eip-2612), it talks about "paying gas fee with tokens" and "a relayer submit a Permit". So my (next) best guess is that this is meant to be used by some sort of relayer or service, which executes the permit.

In fact, if the permit function transfers the tokens directly with _transfer, it would break a lot of integrations. Consider for example Uniswap: Uniswap expects there to be allowance in place before a trade. It doesn't know how to handle direct token transfers.

Furthermore, if we want to interact with Uniswap but don't want to pay gas fee ourselves (or want to pay it in some other assets), the chain could go something like this:

  1. Owner signs a permit and sends it to service X. The permit gives Uniswap allowance to token Y

  2. Service X executes the permit and takes some fees from the owner, in some fashion

  3. Service X calls Uniswap to execute the trade, sending the resulting token to the owner

TLDR: allowances work with existing integrations. Most on-chain services don't understand how to use tokens if they are transferred to them directly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.