2

This is the contract https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol

What is going on in this

 function balance0() private view returns (uint256) {
        (bool success, bytes memory data) =
            token0.staticcall(abi.encodeWithSelector(IERC20Minimal.balanceOf.selector, address(this)));
        require(success && data.length >= 32);
        return abi.decode(data, (uint256));
    }

What is need to complicate this function?

1 Answer 1

2

This question touches two opcodes EXTCODESIZE and returndatasize. There are something called EXTCODESIZE check and returndatasize check. Which used to check whether the address that calling this function is a smart contract or EOA and the returndatasize check to find out what data is touched and return datasize.

Both checks use gas and there aren't many use cases for that. So they are using the static call to skip those checks.

There is a whole article by consensys about why we should avoid EXCTCODESIZE.


Just like the call function, there are two more low level functions. Static call and delegate call.

Static call does the same thing as call function however it cannot change the state of a contract.

STATICCALL was introduced in 2017 or something before solidity v0.5. After that, they started usisng STATICCALL opcode behind view and pure functions.

You can read more about this here.

The famous use case of STATICALL is saving gas fee by simulating transactions.

In some complex contracts, when you aren't sure whether the function would work or not, you can use STATICALL to simulate the function. It does the same work as call, however, it doesn't modify the storage or anything that charge gas.

In the case of uniswap code, they are trying to skip unnecessary steps and save the gas.

And abi.encodeWithSelector is a way of calling contract functions.

token0.staticcall(abi.encodeWithSelector(IERC20Minimal.balanceOf.selector, address(this)));

If you look at that code they are calling balanceOf function selector and passing the address of present contract.

However, you can also use static call with abi.encodewithSignature.

(bool success,) = ContractX.staticcall(abi.encodeWithSignature("foo(uint256)", 100));

You can read about more the STATICALL here.

Tell me if it helps!

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.