Codehash vulnerabilities
Jump to navigation
Jump to search
The addr.codehash
property returns the keccak256 hash of the addr
EVM bytecode[1].
Balance dependency
In the contract below, you can see that the property's output depends on the balance of an address (if the address has no code deployed):
pragma solidity 0.8.23;
contract Test1 {
address subject = address(123);
function getCodehash()
external
payable
returns (
bytes32 codeHashBefore,
bytes32 codeHashAfter,
bytes32 hashBefore,
bytes32 hashAfter
)
{
hashBefore = subject.codehash;
codeHashBefore = keccak256(subject.code);
payable(subject).transfer(1);
hashAfter = subject.codehash;
codeHashAfter = keccak256(subject.code);
}
}
The function's output:
{
"0": "bytes32: codeHashBefore 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
"1": "bytes32: codeHashAfter 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
"2": "bytes32: hashBefore 0x0000000000000000000000000000000000000000000000000000000000000000",
"3": "bytes32: hashAfter 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
}
As you can see, hashBefore
(the balance is 0) is equal to 0, and hashAfter
(the balance is 1) is equal to keccak256("")
.
The combination of the frontrunning and this issue can be used to cause a revert in functions that use .codehash
to distinguish smart contracts and EOA[2].
You can see more about why this is happening in the EIP-1052 and EIP-161.