My understanding is that in a transaction's input data, the first 4 bytes, i.e. 8 characters, is reserved for a function signature. The rest of the data, after processed by the API, will be fitted to 32-byte slots. However, I've encountered transaction inputs that do not fit the above understanding. For example, in this transaction, after the first 4 bytes, there are 158 characters which is not a multiple of 64 (equivalent to 32 bytes and 1 slot). How is this possible or is there any shortcoming in my understanding of EVM storage slot?
1 Answer
In EVM, calldata is an arbitrary length array with the meaning is interpreted using your bytecode parsing it. In Solidity, due to their implementation, they have a special way of interpreting calldata following ABI specification (this is what you mean).
You can write your smartcontract with bytecode and override all logic in ABI specification. In this case you type your bytecode directly if you know what they mean and to implement your logic for example: 0x602a60005260206000f3 return value 42 when called, as can be seen in this ethernaut challenge with explanation
But even in ABI specification for normal function, the data can be in arbitrary length greater than a certain value. For example
test(bytes)will accept any appropriate formatted calldata with greater than 68 bytes: 4 bytes(function sig) + 32 bytes(array location) + 32 bytes(array size) + x bytes array content)In another way, you can also craft your contract to accept arbitrary length call data (or what ever size) in your sample tx by this code:
pragma solidity ^0.8.0; contract Test{ bytes public call_data_; fallback(bytes calldata data) external payable returns (bytes memory) { call_data_ = data; // do other logic etc... } } Sample smart contract interaction with 2 bytes 0x1234 on remix : 
Your give smart contract is obfuscated with custom logic to handle call data via further implementing the //do other logic in the above sample code. Decompilation attempt here
Read more about ABI specification here
- Thanks for the answer. 2 questions: 1. how do specify in our smart contract to override ABI specification? 2. without overriding, can you please briefly tell me how to achieve the data input like the one my example transaction above?Khanh– Khanh2023-10-25 07:49:16 +00:00Commented Oct 25, 2023 at 7:49
- In your test(bytes), if I understand it correctly, the data input will still be 4 bytes + n * 32 bytes?Khanh– Khanh2023-10-25 07:55:01 +00:00Commented Oct 25, 2023 at 7:55
- It's 4byte function signature + array location (32 byte) + array size (32 byte) + array content (which mean whatever number of bytes). You can try it here: abi.hashex.orgminhhn2910– minhhn29102023-10-25 08:20:34 +00:00Commented Oct 25, 2023 at 8:20
- Thanks again. I suppose when you said "whatever number of bytes", it can be 1 or 2 bytes as well? I just used abi.hashex.org to try your function, it still has padding 0s at the end (right-padding) of data content to make 32 bytes. Moreover, I see that the first 2 slots are reserved for array location and array size. How do we eliminate these 2 slots completely to save data storage? If complete elimination is not possible, how do remove any padding 0s? In the example transaction, I see there's no padding zeros and all the data are packed tightly together.Khanh– Khanh2023-10-25 09:12:07 +00:00Commented Oct 25, 2023 at 9:12
- Hi, I added sample interaction with that contract i gave, you can use 0x1234 (your 2bytes as you want). For the rest, up to you to read more on the documentation :Dminhhn2910– minhhn29102023-10-26 01:57:41 +00:00Commented Oct 26, 2023 at 1:57