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:


1 Answer 1


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

  • 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 Aug 22, 2018 at 17:00
  • calldatacopy can copy to anywhere in memory, including copying right after storage 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 Aug 22, 2018 at 17:09
  • calldatacopy(add(_message, 36), 100, sub(calldatasize,100)) or something similar workshould 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! 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.