Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not set freemem pointer when having only fallback function with sole assembly block #15627

Open
radeksvarz opened this issue Dec 9, 2024 · 0 comments
Labels

Comments

@radeksvarz
Copy link

Some contracts having only 1 function aim to be as gas efficient as possible. Such contracts use only fallback() function.

Currently (0.8.x) Solidity compiles freemem pointer allocation even for cases it is not needed.

Here is the UUPS proxy example with the mentioned issue https://eth-sepolia.blockscout.com/address/0xC0bf4d3F67B0B516930B28A90fe4022F20bEbE96?tab=contract

    /**
     * @dev Fallback function that delegates calls to the current implementation address.
     * Will run if no other function in the contract matches the call data.
     * This function will return directly to the external caller.
     */
    fallback() external payable {
        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(), sload(_IMPLEMENTATION_SLOT), 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()) }
        }
    }

This compiles into:

# this part is not needed
PUSH1 80
PUSH1 40
MSTORE
# end of not needed part
CALLDATASIZE
PUSH1 00
...

Proposal is to avoid compiling not needed part when the contract has: only fallback function and such function does not risk having memory clash (such as when having only assembly block).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant