5

I'm using a low level delegatecall to forward my calls to a library.

I need to (in this order) :

  1. load bytes4 sig into _message from memory

  2. load bounty (STRUCT) into _message from storage

  3. load bytes _data into _message

  4. Delegatecall with the new message

  5. Get return valuesThe contract works (eg the getBounty function will work) but I'm having trouble with the assembly in my forwarder() function. https://ethfiddle.com/po3wHGQraJ

I'm having trouble making my forwarder (in assembly) work properly however.

  function forward(bytes32 _sig, bytes memory _data) public payable {
    bytes memory data = _data;
    bytes4 sig = bytes4(_sig);
    address _impl = impl;
    require(_impl != address(0));
    assembly {
      let _message := mload(0x40) //find empty memory location
      mstore(_message, sig) //place sig at beginning of empty storage
      //add _bounty
      mstore(add(_message, 4), sload(bounty_slot))
      //add _data
      calldatacopy(add(_message, 36), 100, sub(calldatasize,100))
      //mstore(add(_message, 36), data)
      let size := returndatasize
      let result := delegatecall(gas, _impl, _message, msize, 0, 0)
      //return data ??????
      returndatacopy(_message, 0, size)
      switch result
      case 0 {revert(_message, size) }
      default { return(_message, size) }
    }
  }

This is what the storage looks like:

0x00
0x687474703a2f2f6170692e6269746275636b65742e636f6d2f33303433303430
0xe1bb4acb579f780cbaf21cef9ac3641b8e3fcd69
0x5b7eaef7
0x3334303330340000000000000000000000000000000000000000000000000000
0x012a05f200
0x00
0x00
0x059ce9161d4fb0
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00
0x00

1 Answer 1

3

The returndatacopy is the right approach, but you have an issue with _data.

The _data variable is a pointer to memory, since bytes is an array type. You need to copy the data into the message buffer.

This can be done either by making the function external then using calldatacopy, or you can use a loop to copy word-by-word, or you can use the identity precompiled contract at address 0x04

10
  • The isue with calldatacopy is that I would need to encode my storage before the calldata still. I'm not sure this is possible that way? So I essentially need to construct a new message in my forward function consisting out of Signature + Storage + Calldata Commented Aug 22, 2018 at 17:00
  • calldatacopy can copy to anywhere in memory, including copying right after storage Commented Aug 22, 2018 at 17:04
  • But I can't just do calldatacopy(_message, 0, calldatasize) , can I ? Wouldn't that overwrite the _sig and _bounty already stored in memory there? Here are all the contracts for a little more context: gist.github.com/kyriediculous/fd070786ce981a64a981e73487ba73ec Commented Aug 22, 2018 at 17:09
  • calldatacopy(add(_message, 36), 100, sub(calldatasize,100)) or something similar workshould Commented Aug 22, 2018 at 17:13
  • Thanks I think I can manage now. Cool that will help me on my way! I just need to split calldatacopy at the 4th byte (ending of the signature) and put my _bounty in between. I'll try figuring something out later tonight. Thanks for the help! Commented Aug 22, 2018 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.