Guide to Solidity's staticcall and how to use it
A guide to using the Solidity staticcall
Table of Contents for Guide to Solidity's staticcall and how to use it
Solidity had a new feature added back in 2017 (https://github.com/ethereum/EIPs/pull/214) to add STATICCALL.
This was added in EIP-214 - https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md
The staticcall
is a security improvement, as it allows a contract to call another contract (or itself) without modifying the state.
If you try to call something in another contract with staticcall, and that contract attempts to change state then an exception gets thrown and the call fails.
staticcall
works in a similar way as a normal call
(without any value
(sending eth) as this would change state). But when staticcall
is used, the EVM has a STATIC
flag set to true. Then, if any state modification is attempted, an exception is thrown. Once the staticcall
returns, the flag is turned off.
How to use staticcall (example syntax)
[success, returnData] = aContratAddress.staticcall(bytesToSend)
Here is an example of calling staticcall. It is similar to call()
.
// basic example, calling staticcall with encodeWithSignature
(bool success,) = someContract.staticcall(abi.encodeWithSignature("foo(uint256)", 100));
// or if you already have the data to send, and want to see the result:
(bool isSuccess, bytes memory response) = someContract.staticcall(data);
Here is an example of calling staticcall in Solidity assembly (the same as calling call()
but without the value
).
assembly {
staticcall(16000, addr, add(data, 32), mload(data), 0, 0)
}
In the example above (based on https://ethereum.stackexchange.com/a/101452):
16,000
gasaddress
target contract addressadd(data, 32)
inputmload(data)
input size0
output0
output size
When will staticall throw exceptions?
An exception will also be thrown if the code (opcodes in brackets):
- tries to deploy a new contract (
CREATE
andCREATE2
) - emits logs (
LOG0
,LOG1
,LOG2
,LOG3
,LOG4
) - makes state changes (
SSTORE
) - anything that uses
call()
with a value (sending eth)
Why and when to use staticcall
One of the main reasons to use staticcall
is to avoid reentrancy vulnerabilities.
Spotted a typo or have a suggestion to make this crypto dev article better? Please let me know!
Next post
Previous post
π Solidity Auditing online quiz
Learn how to audit smart contracts by looking at some example code and trying to find the bugs
β½ Solidity Gas Optimizations Guide
How to optimize and reduce gas usage in your smart contracts in Solidity
π§ͺ Guide to testing with Foundry
Guide to adding testing for your Solidity contracts, using the Foundry and Forge tools
π Guide to UTXO
UTXO and the UTXO set (used by blockchains such as Bitcoin) explained
π Solidity Assembly Guide
Introduction guide to using assembly in your Solidity smart contracts
π¦ Ethereum EOF format explained
Information explaining what the upcoming Ethereum EOF format is all about