Delegatecall

delegatecall 批准 ERC20 合約

  • February 2, 2022

我嘗試從另一個 ERC20 合約的合約中呼叫批准:

委託人來電:

// 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));
   }
}

ERC20 合約:

// 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);
   }
}

我呼叫函式delegate,事務成功結束

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

然而,檢查 ERC20 合約 0x70CcB2c7E3809f1e91B8273beC4c8186b4F897a4 (Arbitrum Rinkeby) 沒有交易的痕跡。

有誰知道出了什麼問題?

同時,我在 Ethereum Rinkeby L1 上觸發了相同的交易。內部交易,delegatecall因為approve是成功的,但是,狀態似乎沒有改變,津貼仍然是 0(零):

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

當 Delegate 執行 MyERC20.delegetecall 時,它會在 Delegate 的上下文中執行 MyERC20 的程式碼。因此,所有更改的變數,以及其他一切都僅在 Delegate 上完成。這就是為什麼您在 Delegate 上看到交易但在 MyERC20 上看不到的原因。您不能使用委託呼叫更改另一個合約的狀態。

如果您檢查success_approve 是否為真,您可能會看到呼叫實際上失敗了(因為您在Delegate 上沒有執行.approve 命令所需的變數)。

引用自:https://ethereum.stackexchange.com/questions/120551