1

Any idea to compress the input data to erase the much zeros

From: 0x8f2b7a67000000000000000000000000a19a81a38bf2238a695629fa7b4a909a2390ddb40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052fea3caafaaf3f95ec536b30714bff78dbac5b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000013247aacf600000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000c17b109e146934d36c33e55fade9cbda791b03660000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c17b109e146934d36c33e55fade9cbda791b03660000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270

To: 0x8f2b7a67a19a81a38bf2238a695629fa7b4a909a2390ddb4052fea3caafaaf3f95ec536b30714bff78dbac5b01e1400013247aacf6002d500b1d8e8ef31e21c99d1db9a6444d3adf127c17b109e146934d36c33e55fade9cbda791b036602c17b109e146934d36c33e55fade9cbda791b0366d500b1d8e8ef31e21c99d1db9a6444d3adf1270

4
  • Is there any reason u want to erase the padding zeros ? the input data is designed to encode with padding 0 for 32 bytes.
    – Jiaming Li
    Mar 23, 2022 at 13:38
  • I want to compressed the input to save the gas
    – khennati
    Mar 23, 2022 at 20:15
  • in your code you should use abi.encodePacked(var1,var2,etc.)
    – Adam Boudj
    Mar 24, 2022 at 7:16
  • Thank you @AdamBoudjemaa could you please tell me any example.
    – khennati
    Mar 24, 2022 at 7:54

2 Answers 2

1

You can use abi.encodePacked, here is a quick example:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Demo {
     
    function encode(uint8 a, uint16 b, bool c, string calldata d) external pure returns(bytes memory) {
      return abi.encode(a,b,c,d);
    }

        function encodePacked(uint8 a, uint16 b, bool c, string calldata d) external pure returns(bytes memory) {
      return abi.encodePacked(a,b,c,d);
    }
}

encode function returns bytes: 0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000000

while encodePacked returns bytes: 0x0100010131

1
  • Thank you very much for your time, I really appreciate this. now how can I back from 0x0100010131 to a,b,c,d, to put them in another function
    – khennati
    Mar 24, 2022 at 10:50
0

Calldata

when submitting a transaction, the calldata is structured like so: the first 4 bytes contain the function signature and for each function argument you get 32 bytes padded with zeroes. In your example:

0x8f2b7a67000000000000000000000000a19a81a38bf2238a695629fa7b4a909a2390ddb40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052fea3caafaaf3f95ec536b30714bff78dbac5b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000013247aacf600000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000c17b109e146934d36c33e55fade9cbda791b03660000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c17b109e146934d36c33e55fade9cbda791b03660000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270

0x8f2b7a67 is the function signature and it's followed by 13 arguments (each struct key or array element counts as an argument)

000000000000000000000000a19a81a38bf2238a695629fa7b4a909a2390ddb4 (probably an address)

0000000000000000000000000000000000000000000000000000000000000000 (0)

000000000000000000000000052fea3caafaaf3f95ec536b30714bff78dbac5b (looks like an address)

0000000000000000000000000000000000000000000000000000000000000001 (1)

00000000000000000000000000000000000000000000000000000000000000e0 (224)

0000000000000000000000000000000000000000000000000000000000000140 (320)

00000000000000000000000000000000000000000000000013247aacf6000000 (1379362269162373120)

0000000000000000000000000000000000000000000000000000000000000002 (2)

0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270 (another address)

000000000000000000000000c17b109e146934d36c33e55fade9cbda791b0366 (address again)

0000000000000000000000000000000000000000000000000000000000000002 (2)

000000000000000000000000c17b109e146934d36c33e55fade9cbda791b0366 (same address)

0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270 (and an address again)

Calldata in solidity is pretty cheap: 4 gas per 0x00 byte and 16 gas per byte with a non-zero value.

Tight-Packing

You could tight-pack these arguments together (see Tight Packing) but you would have to

  • Find smaller types for each argument that will be consistent with their maximum value. For example for your argument #4 (1) maybe it's a uint8 (max 255), or a uint16 (max 65535), ...
  • Change your method so that it accepts packed uint256 or bytes32 variables
  • Extract each variable through bitwise operations

It's very likely that doing this will result in a higher gas cost.

If you post your function params and the code you use to call that function, I can propose some code implementing this solution

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.