diff --git a/scripts/utils/kakarot.py b/scripts/utils/kakarot.py index 9b2a70879..28843cd59 100644 --- a/scripts/utils/kakarot.py +++ b/scripts/utils/kakarot.py @@ -221,6 +221,7 @@ async def _wrapper(self, *args, **kwargs): else int(EVM_ADDRESS, 16) ) result = await kakarot_contract.functions["eth_call"].call( + nonce=0, origin=origin, to={ "is_some": 1, diff --git a/src/kakarot/interfaces/interfaces.cairo b/src/kakarot/interfaces/interfaces.cairo index 8c4396143..82b25b12e 100644 --- a/src/kakarot/interfaces/interfaces.cairo +++ b/src/kakarot/interfaces/interfaces.cairo @@ -102,6 +102,7 @@ namespace IKakarot { } func eth_call( + nonce: felt, origin: felt, to: model.Option, gas_limit: felt, diff --git a/src/kakarot/kakarot.cairo b/src/kakarot/kakarot.cairo index acf6d5312..e033db268 100644 --- a/src/kakarot/kakarot.cairo +++ b/src/kakarot/kakarot.cairo @@ -8,7 +8,7 @@ from starkware.cairo.common.bool import FALSE, TRUE from starkware.cairo.common.cairo_builtins import HashBuiltin, BitwiseBuiltin from starkware.cairo.common.math_cmp import is_not_zero from starkware.cairo.common.uint256 import Uint256 -from starkware.starknet.common.syscalls import get_caller_address, replace_class +from starkware.starknet.common.syscalls import get_caller_address, replace_class, get_tx_info from starkware.cairo.common.registers import get_fp_and_pc from openzeppelin.access.ownable.library import Ownable @@ -160,6 +160,7 @@ func deploy_externally_owned_account{ func eth_call{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin* }( + nonce: felt, origin: felt, to: model.Option, gas_limit: felt, @@ -174,7 +175,16 @@ func eth_call{ let fp_and_pc = get_fp_and_pc(); local __fp__: felt* = fp_and_pc.fp_val; let (evm, state, gas_used) = Kakarot.eth_call( - origin, to, gas_limit, gas_price, &value, data_len, data, access_list_len, access_list + nonce, + origin, + to, + gas_limit, + gas_price, + &value, + data_len, + data, + access_list_len, + access_list, ); let is_reverted = is_not_zero(evm.reverted); return (evm.return_data_len, evm.return_data, 1 - is_reverted, gas_used); @@ -213,8 +223,20 @@ func eth_send_transaction{ local __fp__: felt* = fp_and_pc.fp_val; let (local starknet_caller_address) = get_caller_address(); let (local origin) = Kakarot.safe_get_evm_address(starknet_caller_address); + + let (tx_info) = get_tx_info(); + let (evm, state, gas_used) = Kakarot.eth_call( - origin, to, gas_limit, gas_price, &value, data_len, data, access_list_len, access_list + tx_info.nonce, + origin, + to, + gas_limit, + gas_price, + &value, + data_len, + data, + access_list_len, + access_list, ); let is_reverted = is_not_zero(evm.reverted); let result = (evm.return_data_len, evm.return_data, 1 - is_reverted, gas_used); diff --git a/src/kakarot/library.cairo b/src/kakarot/library.cairo index b83e0bcac..5c17d4be1 100644 --- a/src/kakarot/library.cairo +++ b/src/kakarot/library.cairo @@ -73,6 +73,7 @@ namespace Kakarot { range_check_ptr, bitwise_ptr: BitwiseBuiltin*, }( + nonce: felt, origin: felt, to: model.Option, gas_limit: felt, @@ -86,7 +87,7 @@ namespace Kakarot { alloc_locals; let is_regular_tx = is_not_zero(to.is_some); let is_deploy_tx = 1 - is_regular_tx; - let evm_contract_address = resolve_to(to, origin); + let evm_contract_address = resolve_to(to, origin, nonce); let starknet_contract_address = Account.compute_starknet_address(evm_contract_address); tempvar address = new model.Address( starknet=starknet_contract_address, evm=evm_contract_address @@ -189,21 +190,19 @@ namespace Kakarot { // @dev When to=None, it's a deploy tx so we first compute the target address // @param to The transaction to parameter // @param origin The transaction origin parameter + // @param nonce The transaction nonce parameter, used to compute the target address if it's a deploy tx // @return the target evm address func resolve_to{ syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin*, - }(to: model.Option, origin: felt) -> felt { + }(to: model.Option, origin: felt, nonce: felt) -> felt { alloc_locals; if (to.is_some != 0) { return to.value; } - // TODO: read the nonce from the provided origin address, otherwise in view mode this will - // TODO: always use a 0 nonce - let (tx_info) = get_tx_info(); - let (local evm_contract_address) = CreateHelper.get_create_address(origin, tx_info.nonce); + let (local evm_contract_address) = CreateHelper.get_create_address(origin, nonce); return evm_contract_address; } diff --git a/tests/end_to_end/test_kakarot.py b/tests/end_to_end/test_kakarot.py index 4e76659bf..257b7f2cb 100644 --- a/tests/end_to_end/test_kakarot.py +++ b/tests/end_to_end/test_kakarot.py @@ -189,6 +189,7 @@ async def test_eth_call_should_succeed( assert status == "✅" result = await kakarot.functions["eth_call"].call( + nonce=0, origin=int(evm_address, 16), to={ "is_some": 1, diff --git a/tests/utils/contracts.py b/tests/utils/contracts.py index 37e6e65fd..eb6f63507 100644 --- a/tests/utils/contracts.py +++ b/tests/utils/contracts.py @@ -99,6 +99,7 @@ async def _wrapped(self, *args, **kwargs): } call_kwargs = { + "nonce": 0, "origin": caller_evm_address, **invoke_kwargs, }