1

I try to call approve from a contract of another ERC20 contract:

The delegate call:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Delegate {
    address public constant f24 = 0x70CcB2c7E3809f1e91B8273beC4c8186b4F897a4;

    function delegate(address account, uint256 price) external {
        (bool success_approve,) = f24.delegatecall(abi.encodeWithSignature('approve(address,uint256)',account,price));
    }
}

The ERC20 contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract MyERC20 is ERC20, ERC20Permit, ERC20Votes, ERC20Pausable, ERC20Burnable, AccessControl {
    using SafeMath for uint256;
    bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");

    mapping(uint256 => uint256) public claim;

    constructor() ERC20("MyERC", "MRC") ERC20Permit("MyERC") {
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _setupRole(OPERATOR_ROLE, msg.sender);

    }

    function decimals() public view virtual override returns (uint8) {
        return 2;
    }

    function _mint(address account, uint256 amount) internal virtual override(ERC20, ERC20Votes) {
        super._mint(account, amount);
    }

    function _burn(address account, uint256 amount) internal virtual override(ERC20, ERC20Votes) {
        super._burn(account, amount);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override(ERC20, ERC20Pausable) {
       super._beforeTokenTransfer(from, to, amount);

    }

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override(ERC20, ERC20Votes) {
        super._afterTokenTransfer(from, to, amount);
    }
}

I call the function delegateand the transaction ends successfully

https://testnet.arbiscan.io/tx/0xd048a1e312c240696bf58c22c89267bd6afebaf38e11d6e37d2c719004e4e115

However, checking the ERC20 contract 0x70CcB2c7E3809f1e91B8273beC4c8186b4F897a4 (Arbitrum Rinkeby) there is no trace of a transaction.

Has anyone an idea what's going wrong?

Meanwhile, I triggered the same transaction on Ethereum Rinkeby L1. The internal transaction, delegatecall for the approve is successful, however, the state seems not to have changed, the allowance is still 0 (zero):

https://rinkeby.etherscan.io/tx/0xde431622bd04556dc4c9ee0eb1f76c367d09194ce6b2b1febd7b35ad8990ae4d

1 Answer 1

1

When Delegate runs MyERC20.delegetecall, it executes MyERC20's code in Delegate's context. So all the variables that are changed, and everything else is being done on Delegate only. This is why you see the transaction on Delegate but not on MyERC20. You can't change another contract's state using delegatecall.

If you would check whether success_approve is true, you would probably see that actually the call failed (as you don't have the necessary variables on Delegate to execute the .approve command).

2
  • 1
    Thank you very much for your answer @Kenzo Agada. I added a require(success_approve, "Delegate call failed");, however, the function still succeeds and I even get the log/event require(success_approve, "Delegate call failed"); rinkeby.etherscan.io/tx/… If the delegate call cannot change the state, delegate calls makes no sense, right?
    – user66732
    Commented Feb 2, 2022 at 12:46
  • 1
    Okay, I've read into this topic. A delegatecall only passes the call context, however, does not change the status of the callee.
    – user66732
    Commented Feb 2, 2022 at 13:16

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.