Assembly
從裝配轉換為 Solidity
我正在嘗試將彙編程式碼轉換為連結中給出的 Solidity: 什麼是函式選擇器 程式碼試圖呼叫下面給出的 Contract1 的函式 func(…):
contract Contract1 { function func(uint256 x, uint8 y) public returns (uint32, uint32) {...} } contract Contract2{ /* ....... */ assembly { let success := call( gas, // pass the remaining gas to the function dest, // the address of the contract1 instance 0, // pass 0 wei to the function add(data, 32), // the actual data starts after the length of 'data' mload(data), // the length of 'data' appears at the first 32 bytes ret, // the address of the output 8 // the size of the output ) if iszero(success) { revert(0, 0) } } /*....*/ }
以下陳述是否正確?
(success, errCode, arg1, arg2) =dest.func.value()( uint256(789), uint8(123));
arg1 和 arg2 將保存 Contract1 的 func() 返回的兩個值。有人請指導我。
祖爾菲。
您需要編寫以下內容:
(bool success, ) = dest.call(data);
正如文件所說:
為了與不遵守 ABI 的合約進行互動,或者為了更直接地控制編碼,提供了
call
和delegatecall
功能staticcall
。它們都採用單個bytes memory
參數並返回成功條件(作為 abool
)和返回的數據(bytes memory
)。函式abi.encode
、abi.encodePacked
和可用於對結構化數據進行編碼abi.encodeWithSelector
。abi.encodeWithSignature
假設下一個實現
func()
ofContract1
。function func(uint256 x, uint8 y) public returns (uint32, uint32) { return(uint32(x), uint32(y)); }
的程式碼
Contract2
。contract Contract2 { Contract1 public contract1 = new Contract1(); function func() public returns (uint32, uint32) { uint32[2] memory ret; address dest = address(contract1); bytes4 selector = contract1.func.selector; //bytes4 selector = bytes4(keccak256("func(uint256,uint8)")); bytes memory data = abi.encodeWithSelector(selector, uint256(789), uint8(123)); (bool success, ) = dest.call(data); require(success); assembly { let size := returndatasize returndatacopy(ret, 0, size) } return (ret[0], ret[1]); } }
這裡使用的彙編是管理函式返回的數據
call
。如果您使用元組(bool success, bytes memory returnData)
,您將獲得返回的數據bytes memory
,您需要將其轉換為作為兩個uint32
值返回。