0

I came across a different version of delegate call via assembly and also tried all of them - no different result so far. How does it differ and which is the best version to use?

OpenZepplin version:

assembly {
  let ptr := mload(0x40)
  calldatacopy(ptr, 0, calldatasize)
  let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
  let size := returndatasize
  returndatacopy(ptr, 0, size)

  switch result
    case 0 { revert(ptr, size) }
    default { re  turn(ptr, size) }
}

MakerDAO version:

assembly {
  let succeeded := delegatecall(sub(gas, 5000), _target, add(_calldata, 0x20), mload(_calldata), 0, 0)
  let size := returndatasize

  response := mload(0x40)
  mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))
  mstore(response, size)
  returndatacopy(add(response, 0x20), 0, size)

  switch iszero(succeeded)
    case 1 {
        revert(add(response, 0x20), size)
    }
}

Simple version:

assembly {
  let succeeded := delegatecall(sub(gas, 5000), _target, add(_calldata, 0x20), mload(_calldata), 0, 32)
  response := mload(0)
  switch iszero(succeeded)
  case 1 {
    revert(0, 0)
  }
}
1

OpenZeppelin's one is the most generic and addresses contract upgrade scenario. It forwards msg.data as is to called contracts, and returns what called contract returned.

MakerDAO's is also generic but it allows passing arbitrary bytes as parameters and packs returned value into bytes as well.

Simple version allows arbitrary bytes as parameters but only returns first 32 bytes of returned value. It also ignores any data returned by failed delegate call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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