Bit operations in Solidity
I would keep this article short and divide it in 2 sections. Section 1 being the problem statement and section 2 being the solution
The problem statement :
I wanted to read msg.data and get its first parameter, msg.data is in bytes and the composition of msg.data (in simple terms) is : function name + input parameters.
With 0–4 byte being the function signature
4–36 bytes being the first parameter
36–72 being the second parameter
and so on.
So to get the first parameter it is evident that bit operations is a must.
I present to you the Solution
Use inline assembly! What is inline assembly you ask?
In simple terms it is a language which can be used within solidity. It is harder to write but the EVM can understand it more easily, same story as C. Hard to write but better with computers.
It is called Yul. How do you write in inline assembly you ask?
Well it is very simple
function getFirstParameter() external view{assembly {}}
Within the assembly brackets you will write the Yul.
The only main thing to remember in Yul, = is written as :=
Rest everything is very easy.
So now let’s get going with how Yul will look.
function getFirstParameter(address _address, uint a) external view returns (address){bytes20 _add;assembly {calldatacopy(0x0, 16, 36)_address := mload(0x0)}address _address = address(_add);return _address;}
Now what is calldatacopy and mload?
Calldatacopy takes 3 input parameters
- address (this address refers the the address in the memory)
- Start(this is regarding from which byte to start)
- End (this is regarding at which byte to stop)
Now what calldatacopy(0x0, x, y) does is, it copies the calldata from byte x to y and stores it at 0x0 of the memory. In our case we needed the first parameter so we stored it from byte 4 to byte 36 at 0x0.
Note : calldata is the same as msg.data
mload is nothing. As the name suggests it loads something.
So basically mload(0x0) will load and give the data stored at 0x0 of the memory.
The significance of what we did right now!
Even though the example we performed right now was very trivial as, over here we are only giving and reading the same input parameter.
But this feature of reading and storing calldata will come very much in handy when we will work with fallback functions.
I am specifically using this while I am creating a one of a kind dynamic upgradeable smart contract right now.
You can have a look at Proxy.sol in the contracts folder https://github.com/dakshjoshi/upgradeable-contracts
If you have any doubts about the code in the Github, you are very welcomed to reach out to me on my linkedIn.
I hope this article was of use to you
Thank you
Cheers
Live Long and Prosper
Daksh Joshi