A precompile in the context of Ethereum is a precompiled “contract” that can be run like a smart contract but outside of the context of the EVM. What this means is that, instead of dealing with EVM opcodes, we can deal directly with Golang-compiled machine code instead, which allows us to perform much more complex computation.
This works by:
- Setting up a list of precompiled “contracts” or functions that is referred to by the ethereum client, eg. geth / go-ethereum or op-geth (Optimism’s geth client).
- These precompiled contracts exist at special reserved addresses, for example at
0x01
. - When a smart contract calls a precompile through, say,
ecrecover
, it is actually calling a wrapper function that either callscall
orstaticcall
under the hood, towards the corresponding contract address that contains elliptic curve recovery logic, and sending it the corresponding parameters. - For example, say I would like to add my own precompile to perform
secp256r1
verification at the address0x10
, this is the function I would need to include in the relevant places for my contracts to be able to callsecp256r1Verify()
. So, the call flow goes as dapp / frontend -> my custom contract ->secp256r1Verify
method -> ethereum client Golang code.
function secp256r1Verify(
bytes32 r,
bytes32 s,
bytes32 x,
bytes32 y,
bytes32 hash
) public view returns (uint8) {
uint8 output;
bytes memory args = abi.encodePacked(r, s, x, y, hash);
assembly {
if iszero(
// 0x10 for the precompile address
// add(args, 32) for ???
// 0xa0 for the size of the input (160 bytes)
// output for the output
// 0x01 for the size of the output flag (1 byte)
staticcall(not(0), 0x10, add(args, 32), 0xa0, output, 0x01)
) {
revert(0, 0)
}
}
return output;
}