Skip to content
This repository has been archived by the owner on Jan 9, 2025. It is now read-only.

overwrite fix to codehash #1654

Merged
merged 5 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions cairo_zero/backend/starknet.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,10 @@

// Update bytecode and jumpdests if required (newly created account)
if (self.created != FALSE) {
IAccount.write_bytecode(starknet_address, self.code_len, self.code);
IAccount.write_bytecode(starknet_address, [self.code_hash], self.code_len, self.code);

Check warning on line 242 in cairo_zero/backend/starknet.cairo

View check run for this annotation

Codecov / codecov/patch

cairo_zero/backend/starknet.cairo#L242

Added line #L242 was not covered by tests
Internals._save_valid_jumpdests(
starknet_address, self.valid_jumpdests_start, self.valid_jumpdests
);
IAccount.set_code_hash(starknet_address, [self.code_hash]);
return ();
}

Expand Down
6 changes: 5 additions & 1 deletion cairo_zero/kakarot/account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,15 @@ namespace Account {
tempvar address = new model.Address(starknet=starknet_address, evm=evm_address);
let balance = fetch_balance(address);
assert balance_ptr = new Uint256(balance.low, balance.high);
// empty code hash see https://eips.ethereum.org/EIPS/eip-1052
tempvar code_hash_ptr = new Uint256(
low=Constants.EMPTY_CODE_HASH_LOW, high=Constants.EMPTY_CODE_HASH_HIGH
);
let account = Account.init(
address=address,
code_len=0,
code=bytecode,
code_hash=cast(0, Uint256*),
code_hash=code_hash_ptr,
nonce=0,
balance=balance_ptr,
);
Expand Down
15 changes: 3 additions & 12 deletions cairo_zero/kakarot/accounts/account_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,16 @@ func __execute__{
}

// @notice Store the bytecode of the contract.
// @param code_hash The hash of the bytecode to store.
// @param bytecode_len The length of the bytecode.
// @param bytecode The bytecode of the contract.
@external
func write_bytecode{
syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin*
}(bytecode_len: felt, bytecode: felt*) {
}(code_hash: Uint256, bytecode_len: felt, bytecode: felt*) {
// Access control check.
Ownable.assert_only_owner();
AccountContract.set_code_hash(code_hash);
return AccountContract.write_bytecode(bytecode_len, bytecode);
}

Expand Down Expand Up @@ -294,17 +296,6 @@ func get_code_hash{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_p
return (code_hash,);
}

// @notice Set the code hash of the account.
// @param code_hash The code hash of the account.
@external
func set_code_hash{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
code_hash: Uint256
) {
Ownable.assert_only_owner();
AccountContract.set_code_hash(code_hash);
return ();
}

// @notice Authorizes a pre-eip155 transaction by message hash.
// @param message_hash The hash of the message.
@external
Expand Down
4 changes: 4 additions & 0 deletions cairo_zero/kakarot/accounts/library.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ namespace AccountContract {
let infinite = Uint256(Constants.UINT128_MAX, Constants.UINT128_MAX);
IERC20.approve(native_token_address, kakarot_address, infinite);

// Write the empty code hash in storage, as this account does not currently have code.
tempvar code_hash = Uint256(Constants.EMPTY_CODE_HASH_LOW, Constants.EMPTY_CODE_HASH_HIGH);
AccountContract.set_code_hash(code_hash);

// Register the account in the Kakarot mapping
IKakarot.register_account(kakarot_address, evm_address);
return ();
Expand Down
22 changes: 6 additions & 16 deletions cairo_zero/kakarot/instructions/environmental_information.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ from starkware.cairo.common.math_cmp import is_not_zero, is_nn
from starkware.cairo.common.uint256 import Uint256, uint256_le

from kakarot.account import Account
from kakarot.constants import Constants

from kakarot.evm import EVM
from kakarot.errors import Errors
Expand Down Expand Up @@ -479,27 +478,18 @@ namespace EnvironmentalInformation {
return evm;
}

let account = State.get_account(evm_address);
let has_code_or_nonce = Account.has_code_or_nonce(account);
let account_exists = has_code_or_nonce + account.balance.low + account.balance.high;
// Relevant cases:
// https://github.com/ethereum/go-ethereum/blob/master/core/vm/instructions.go#L392
let account = State.get_account(evm_address);

// If the account has code, return the code_hash stored in the account storage.
if (account.code_len != 0) {
Stack.push_uint256([account.code_hash]);
if (account_exists == FALSE) {
Stack.push_uint128(0);
return evm;
}

// If the account has no code but a balance or nonce, return the hash of the empty code hash.
if (account.nonce + account.balance.low + account.balance.high != 0) {
let empty_code_hash = Uint256(
low=Constants.EMPTY_CODE_HASH_LOW, high=Constants.EMPTY_CODE_HASH_HIGH
);
Stack.push_uint256(empty_code_hash);
return evm;
}
Stack.push_uint256([account.code_hash]);

// Account is empty (EIP-161), return 0
Stack.push_uint128(0);
return evm;
}
}
5 changes: 1 addition & 4 deletions cairo_zero/kakarot/interfaces/interfaces.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
func bytecode() -> (bytecode_len: felt, bytecode: felt*) {
}

func write_bytecode(bytecode_len: felt, bytecode: felt*) {
func write_bytecode(code_hash: Uint256, bytecode_len: felt, bytecode: felt*) {

Check warning on line 51 in cairo_zero/kakarot/interfaces/interfaces.cairo

View check run for this annotation

Codecov / codecov/patch

cairo_zero/kakarot/interfaces/interfaces.cairo#L51

Added line #L51 was not covered by tests
}

func storage(storage_addr: felt) -> (value: Uint256) {
Expand Down Expand Up @@ -80,9 +80,6 @@
func get_code_hash() -> (code_hash: Uint256) {
}

func set_code_hash(code_hash: Uint256) {
}

func execute_from_outside(
outside_execution: OutsideExecution,
call_array_len: felt,
Expand Down
15 changes: 10 additions & 5 deletions cairo_zero/tests/src/kakarot/accounts/test_account_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ from kakarot.accounts.account_contract import (
set_nonce,
set_authorized_pre_eip155_tx,
execute_starknet_call,
set_code_hash,
execute_from_outside,
upgrade,
)
Expand Down Expand Up @@ -52,13 +51,19 @@ func test__write_bytecode{

// Given
local bytecode_len: felt;
local code_hash: Uint256;
let (bytecode: felt*) = alloc();
%{
ids.bytecode_len = len(program_input["bytecode"])
segments.write_arg(ids.bytecode, program_input["bytecode"])
from ethereum.crypto.hash import keccak256
bytecode = program_input["bytecode"]
ids.bytecode_len = len(bytecode)
segments.write_arg(ids.bytecode, bytecode)
code_hash = keccak256(bytes(bytecode))
ids.code_hash.low = int.from_bytes(code_hash[0:32], "big")
ids.code_hash.high = int.from_bytes(code_hash[32:64], "big")
%}

write_bytecode(bytecode_len, bytecode);
write_bytecode(code_hash, bytecode_len, bytecode);

return ();
}
Expand Down Expand Up @@ -219,7 +224,7 @@ func test__set_code_hash{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_c
ids.code_hash.high = program_input["code_hash"][1]
%}

set_code_hash(code_hash);
AccountContract.set_code_hash(code_hash);

return ();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,21 +213,12 @@ def test__should_return_if_jumpdest_valid(

class TestCodeHash:
@given(code_hash=integers(min_value=0, max_value=2**256 - 1))
@SyscallHandler.patch("Ownable_owner", 0xDEAD)
def test_should_assert_only_owner(self, cairo_run, code_hash):
with cairo_error(message="Ownable: caller is not the owner"):
cairo_run("test__set_code_hash", code_hash=int_to_uint256(code_hash))

@given(code_hash=integers(min_value=0, max_value=2**256 - 1))
@SyscallHandler.patch("Ownable_owner", SyscallHandler.caller_address)
def test__should_set_code_hash(self, cairo_run, code_hash):
with patch.object(SyscallHandler, "mock_storage") as mock_storage:
low, high = int_to_uint256(code_hash)
cairo_run("test__set_code_hash", code_hash=(low, high))
code_hash_address = get_storage_var_address("Account_code_hash")
ownable_address = get_storage_var_address("Ownable_owner")
calls = [
call(address=ownable_address),
call(address=code_hash_address, value=low),
call(address=code_hash_address + 1, value=high),
]
Expand Down
2 changes: 1 addition & 1 deletion cairo_zero/tests/src/kakarot/test_account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func test__fetch_original_storage__state_modified{
let starknet_address = Account.compute_starknet_address(evm_address);
tempvar address = new model.Address(starknet_address, evm_address);
let (local code: felt*) = alloc();
tempvar code_hash = new Uint256(0, 0);
tempvar code_hash = new Uint256(Constants.EMPTY_CODE_HASH_LOW, Constants.EMPTY_CODE_HASH_HIGH);
tempvar balance = new Uint256(0, 0);
let account = Account.init(address, 0, code, code_hash, 0, balance);

Expand Down
Loading