[Ethereum] How to use delegatecall assembly with a storage pointer to a struct

assemblydelegatecallsolidity

I am trying to call a library function using assembly and the delegatecall opcode. The library function accepts two parameters, the state object storage pointer and an address, it returns a single uint.

I can tell if the op fails because the data at in_pos is untouched, however when it does work it always returns zero even if the function being called simply returns a 0x01 value.

state is a struct that is shared by the calling contract and the library, its position is 0

address t = 0xTargetLibraryAddress;
address a = 0xAccount;
bytes32 result;
assembly {
   let in_pos := mload(0x40)
   mstore(in_pos, 0x12345678) //a valid func sig within the library
   mstore(add(in_pos, 0x04), state)
   mstore(add(in_pos, 0x24), a)
   let success := delegatecall(sub(gas, 10000), t, in_pos, 0x44, in_pos, 0x20)
   result := mload(in_pos)
   mstore(0x40, add(in_pos, 0x44))
}

Any suggestions?

Best Answer

From what I can gather mstore() will write in 32 byte chunks, therefore mstore(in_pos, 0x04) is still in the same space as in_pos and will overwrite the 4 bytes function signature.

What I ended up doing is writing the 4 bytes in the first 32 bytes, the 1st arg in the 2nd 32 bytes and the 2nd arg in the 3rd 32 bytes, then called delegatecall pointing to the start of the 4 byte signature by using a 28 byte offset.

delegatecall(sub(gas, 1000), t, add(in_pos, 28), 0x44, in_pos, 0x20)

Related Topic