Jump in creation code leads to reverting of the starknet transaction #44
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
edited-by-warden
M-09
primary issue
Highest quality submission among a set of duplicates
🤖_primary
AI based primary recommendation
🤖_65_group
AI based duplicate group recommendation
selected for report
This submission will be included/highlighted in the audit report
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/evm.cairo#L277
https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/evm.cairo#L364
Vulnerability details
Impact
If the creation code consists of
JUMP
orJUMPI
opcode foroffset
less thancreation code length
, then the starknet transaction reverts.The evm.cairo::jump function is called whenever the
JUMP
orJUMPI
opcode is executed. This function is as follows:It can be seen that, it checks for
out_of_range
which isnew_pc_offset - self.message.bytecode_len
. For the creation code, technicallybytecode_length
should be 0 but here, it will consist the length of the creation code. So, if thenew_pc_offset
is less than thecreation code length
, then this check would pass and then it checks foris_valid_jumpdest
by calling evm.cairo::is_valid_jumpdest, which is as follows:Here,
let (is_valid) = IAccount.is_valid_jumpdest(code_address.starknet, index);
would revert the whole starknet transaction as it will call zero address which isn'tIAccount
contract. So any contract usingCREATE
orCREATE2
opcode will be vulnerable to this issue or if a contract makes a callback to another contract by making sure to only send limited gas and handle the revert case properly, the other contract can useCREATE
orCREATE2
opcode to make the transaction revert forcefully.Proof of Concept
Consider the following code:
Save the above code in a file name
creation_code.huff
( You can refer Installing Huff, if you don't have huff installed ).The above code will jump to the offset
0
which is less than the creation code length ( i.e.2
).The above code can be converted to bytecode using the following command:
The output will be:
The runtime code is ( after removing the first few bytes which are responsible for deployment ):
Also, consider the following code:
Save the above code in a file name
create.huff
( You can refer Installing Huff, if you don't have huff installed ).The above code will jump to the offset
0
which is less than the creation code length ( i.e.2
).The above code can be converted to bytecode using the following command:
The output will be:
The runtime code is ( after removing the first few bytes which are responsible for deployment ):
The
create.huff
would callCREATE
opcode with creation code as0x5f56
(creation_code.huff
).Now to to run the test, follow the below steps:
Add this file named
test_kakarot_jump.py
in kakarot/tests/end_to_end folder:You can run the test by:
This test will throw error as follows:
You can see the error
Requested contract address 0x0000000000000000000000000000000000000000000000000000000000000000 is not deployed
.Tools Used
Python test suite
Recommended Mitigation Steps
For
JUMP
andJUMPI
opcodes, there should be a check whether the current environment is running creation code or runtime code. If it's creation code then it should revert with invalid jump destination error.Assessed type
Error
The text was updated successfully, but these errors were encountered: