Solidity

Solidity,字節解碼問題

  • April 15, 2019

回到關於solidity Guru的另一個問題。我正在嘗試呼叫一個將字節數組作為輸入的方法,但要麼我錯誤地編碼了這個參數,要麼錯誤地解碼了它。關於此事的 Solidity 文件相當模糊,因此我按照範例中所寫的方式實現了。函式回調接收到所述參數,但是每當我在測試網中呼叫它時都會失敗。關於字節函式,我缺少什麼abi.decode(),或者只是錯誤地編碼了我的數據?任何幫助將不勝感激,謝謝!

這是相關的 kovan 測試網交易: https ://kovan.etherscan.io/tx/0xc4a158d99f78dcf68ad8a3e9e26e4b8bad8b8a631dd09661ea09fdac23a0729a

傳入的數據的預期打包結構如下:

ff - operId
ffffffffff - txId
6bc84f6a0fabbd7102be338c048fe0ae54948c2e - forwardAddress
6bc84f6a0fabbd7102be338c048fe0ae54948c2e - refundAddress

從我在上面連結的交易中可以看到,以精確順序和預期順序接收的參數。

contract StoForwarder is Controllable {

   constructor(address _controller, address _controllerAgent) public Controllable(_controller, _controllerAgent) {}

   event NewTask(bytes5 txId, address forwardAddress, address refundAddress, address tokenContract,
       bytes32 partition, uint256 amount);

   struct Task {
       bytes5 txId;
       address forwardAddress;
       address refundAddress;
       IERC1410 tokenContract;
       bytes32 partition;
       uint256 amount;
   }

   mapping (bytes5 => Task) public pendingTasks;

   function callback(IERC1410 _stoContract, bytes32 _partition, uint256 _amount, bytes calldata _data) external {
       require(_data.length >= 46, "Insufficient data provided");
       byte operCode;
       bytes5 txId;
       address forwardAddress;
       address refundAddress;
       (operCode, txId, forwardAddress, refundAddress) = abi.decode(_data, (byte, bytes5, address, address));

       require(txId != "", "TransactionId not specified");
       require(_partition != "", "Bad Partition");
       require(forwardAddress != address(0), "Bad Forward Address");
       require(refundAddress != address(0), "Bad refund Address");

       pendingTasks[txId].txId = txId;
       pendingTasks[txId].forwardAddress = forwardAddress;
       pendingTasks[txId].refundAddress = refundAddress;
       pendingTasks[txId].tokenContract = _stoContract;
       pendingTasks[txId].partition = _partition;
       pendingTasks[txId].amount = _amount;

       emit NewTask(txId, forwardAddress, refundAddress, address(_stoContract), _partition, _amount);
   }

   function controllerTransfer(bytes5 txId, bool forward) onlyController external {
       require(pendingTasks[txId].txId != "");
       Task storage task = pendingTasks[txId];
       address targetAddress;

       if (forward) {
           targetAddress = task.forwardAddress;
       } else {
           targetAddress = task.refundAddress;
       }

       task.tokenContract.transferByPartition(task.partition, targetAddress, task.amount, "");
   }
}

PS 一個完全的菜鳥問題:如何require()在區塊鏈上發生錯誤消息後讀取它?這部分讓我有點難以理解。

您的輸入不是 ABI 編碼的。這些值的正確 ABI 編碼如下:

0xff00000000000000000000000000000000000000000000000000000000000000ffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000006bc84f6a0fabbd7102be338c048fe0ae54948c2e0000000000000000000000006bc84f6a0fabbd7102be338c048fe0ae54948c2e

在 ABI 編碼中,幾乎所有內容都被編碼為 32 個字節的長度。固定長度的字節序列(如bytebytes5)右填充零,數字類型(如address)左填充零。數組類型有點複雜,但在這個例子中你沒有這些類型。

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