Delegatecall
delegatecall 批准 ERC20 合約
我嘗試從另一個 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 命令所需的變數)。