Why would we get function selector like this and why do we use that bytes variable functionCallData do many times? Thanks in advance!
function getSelectorTwo() public view returns (bytes4 selector) {
bytes memory functionCallData = abi.encodeWithSignature(
"transfer(address,uint256)",
address(this),
123
);
selector = bytes4(
bytes.concat(
functionCallData[0],
functionCallData[1],
functionCallData[2],
functionCallData[3]
)
);
}
Best Answer
The
bytes
type is like an array, where each element in the array is 1 byte.The
getSelectorTwo()
function is encoding thetransfer(address,uint256)
function selector with the values of the parameters it expects (address
anduint256
).If you printed
functionCallData
you would see the following bytes:0xa9059cbb00000000000000000000000059235ef80c8c63b480734c6888754f464fdb212d000000000000000000000000000000000000000000000000000000000000007b
Notice how the first four bytes are the function selector
a9059cbb
.Then the following 32 bytes are the address of that contract (left-padded with zeros):
00000000000000000000000059235ef80c8c63b480734c6888754f464fdb212d
Then the following 32 bytes are the
123
number in hex (left-padded with zeros):000000000000000000000000000000000000000000000000000000000000007b
7b
hex is123
in decimal.So, the reason why that code is accessing the
functionCallData
bytes array 4 times is because it is copying the first 4 bytes of that data, which we know it's the function selector:functionCallData[0] = a9 functionCallData[1] = 05 functionCallData[2] = 9c functionCallData[3] = bb
It concatenates it and returns it.It cannot do something like
functionCallData[0:4]
to copy a range from thefunctionCallData
bytes array because the slice operator is only available incalldata
bytes array, not on local or storage arrays (yet). So it has to copy it manually, whether in a loop or index by index like it's doing.Check and try my
getTransferFunctionSelectorWithParams
function below: