Solidity
代理模式委託呼叫的奇怪還原
在使用 zeppelin 的可升級合約模式之前,我使用過可升級合約。但是,我發現如果我嘗試通過合約呼叫來獲取實現合約地址,我會得到意外的還原。
pragma solidity >=0.6.0; contract Proxy { address registry = 0xc5c97AAd92a962396229cbC8392e62585B04DfB3; // assume this is registry address function implementation() public view returns(address) { return Registry(registry).getImplementationAddress(); } fallback() external payable { address implementationAddress = implementation(); assembly { let ptr := mload(0x40) calldatacopy(ptr, returndatasize(), calldatasize()) let result := delegatecall(gas(), implementationAddress, ptr, calldatasize(), returndatasize(), returndatasize()) returndatacopy(ptr, 0, returndatasize()) switch result case 0 {revert(ptr, returndatasize())} default {return(ptr, returndatasize())} } } } contract Registry { address public implementationAddress = 0x8750c1719E32294260e596c80a04818533e2C643; // assume this is impl address function getImplementationAddress() public view returns(address) { return implementationAddress; } } contract Foo { // assume this is implementation contract uint256 public a; uint256 public b; function setA(uint256 val) external { a = val; } function setB(uint256 val) external { b = val; } function getA() external view returns(uint256) { return a; } function getB() external view returns(uint256) { return b; } }
在
Foo
. 但是,如果我使該行address registry = 0xc5c97AAd92a962396229cbC8392e62585B04DfB3
保持不變,它將不再恢復。有沒有人對導致還原的原因有任何見解?在 Solc 版本 0.6.13、0.7.4 上複製。
想通了,在更改返回數據大小之前呼叫另一個合約。