3

I have a proxy implementation with method exchange and delegator with method exchange2 with the following code:

function exchange2(int128 i, int128 j, uint256 dx, uint256 min_dy) public {
        (bool success, bytes memory result) = delegationTarget.delegatecall(
            abi.encodeWithSignature("exchange(int128,int128,uint256,uint256)", i, j, dx, min_dy)
        );
        if (!success) {
            if (result.length > 0) {
                revert(string(result));
            } else {
                revert();
            }
        }
        // pay cashback

this simple code above has about 2k gas overhead vs following openzeppelin proxy code:

    function _delegate(address implementation) internal {
        //        // solhint-disable-next-line no-inline-assembly
        assembly {
        // Copy msg.data. We take full control of memory in this inline assembly
        // block because it will not return to Solidity code. We overwrite the
        // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

        // Call the implementation.
        // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

        // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }
    fallback () external {
        _delegate(delegationTarget);
    }

The problem with oz code, I don't know how can I delegate call to exchange of implementation from exchange2 method of proxy.

Is there a way I can optimize abi.encodeWithSignature call if I know that signature of exchange(int128,int128,uint256,uint256) - 0x3df02124? It sounds wastfull to pass same string as an argument every time the function called.

1
  • I am not sure if it works this way, but since the first argument is constant, some of the functions logic could be evaluated at compile time. So it would be possible (if the compuler supports it, an I don't know if it does) that the compiler already does the optimization you are asking for. – jjj Feb 5 at 13:14
0

An approximation to abi.encodeWithSignature is abi.encodePacked(bytes4(keccak256(signature)), abi.encode(parameters...))

You can save 0x3df02124 as byte4 variable in your contract and use an adaptation of the code above:

bytes4 functionSig = 0x3df02124
abi.encodePacked(functionSig, abi.encode(parameters...))

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.