Solidity, problem with bytes decoding

by Kristaps   Last Updated April 15, 2019 20:28 PM

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.



Related Questions


Updated August 12, 2017 15:28 PM

Updated January 05, 2018 03:28 AM

Updated March 30, 2019 05:28 AM

Updated January 25, 2019 17:28 PM

Updated June 19, 2018 10:28 AM