argotorg / argotorg/solidity

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

Open
#15,627 1 comment 0 reactions 0 assignees View on GitHub
feature
Dominant language
C++
Stars
25.7k
Forks
6.2k
Avg merge
2d 19h
Merged PRs (30d)
29

Description

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).

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the Solidity 0.8.x compiler output for the UUPS-style contract with only a fallback function and one assembly block. Trace the compiler path that emits the free-memory pointer initialization, then verify that safe sole-assembly fallbacks omit it without changing behavior for cases where memory can still clash.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, solidity
Domain
blockchain, compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.