1

back with another question towards solidity Guru's. I am trying to call a method which takes bytes array as an input, but either I am encoding this parameter wrongly or decoding it wrongly. Solidity docs on the matter is fairly vague, so I implemented as I saw was written in the example. The function callback receives the said parameter, but than fails as reverted whenever I call it in a testnet. What am I missing regarding bytes abi.decode() function, or have just encoded my data wrongly? Any help would be greatly appreciated, thank you!

Here's the relevant kovan testnet transaction: https://kovan.etherscan.io/tx/0xc4a158d99f78dcf68ad8a3e9e26e4b8bad8b8a631dd09661ea09fdac23a0729a

The intended packed structure of the data passed in was as follows:

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

And from what I could see in the transaction linked above the parameters where received in the precise order and in the expected sequence.

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, "");
    }
}

P.S. A total noob question: how is it possible to read require() error message after it has occurred on the blockchain? This parts eludes me a bit.

1 Answer 1

2

Your input is not ABI encoded. The correct ABI encoding of those values is as follows:

0xff00000000000000000000000000000000000000000000000000000000000000ffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000006bc84f6a0fabbd7102be338c048fe0ae54948c2e0000000000000000000000006bc84f6a0fabbd7102be338c048fe0ae54948c2e

In ABI encoding, pretty much everything is encoded to length 32 bytes. Fixed-length byte sequences (like byte and bytes5) are right-padded with zeros, and numeric types (like address) are left-padded with zeros. Array types are a bit more complicated, but you don't have any of those in this example.

2
  • Thank you for cleaning up the confusion, I just was under the impression that bytes was encoded without those zero padding on the left (since as per solidity docs it's tightly packed array, I suppose if wanted to use it in this manner I would have to attempt decode manually?). I will test this today, hopefully will workout.
    – Kristaps
    Apr 16, 2019 at 6:27
  • 1
    ABI encoding is documented here: solidity.readthedocs.io/en/v0.5.7/abi-spec.html.
    – user19510
    Apr 16, 2019 at 6:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.