diff --git a/.env.example b/.env.example index 2d56de342..2082795cf 100644 --- a/.env.example +++ b/.env.example @@ -1,52 +1,38 @@ -# A Github token to download the CI artifacts -# Used for fetching resources in the kakarot_scripts +# Tokens for coverage and CI +CODECOV_TOKEN= GITHUB_TOKEN= - -# An infura RPC key for mainnet/testnet +# API keys INFURA_KEY= +VOYAGER_API_KEY= +NETHERMIND_API_KEY= -# Account used by default in all kakarot_scripts -# Prefixed accounts {NETWORK}_ will take precedeance over the default one -MADARA_ACCOUNT_ADDRESS=0x3 -MADARA_PRIVATE_KEY=0x00c1cf1490de1352865301bb8705143f3ef938f97fdf892f1090dcb5ac7bcd1d - -SHARINGAN_ACCOUNT_ADDRESS= -SHARINGAN_PRIVATE_KEY= -SHARINGAN_RPC_URL="https://sharingan.madara.zone" - -# First account when using these networks with seed = 0 -STARKNET_DEVNET_ACCOUNT_ADDRESS=0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691 -STARKNET_DEVNET_PRIVATE_KEY=0x71d7bb07b9a64f6f78ac4c816aff4da9 - -STARKNET_SEPOLIA_RELAYER_ACCOUNT_ADDRESS= -STARKNET_SEPOLIA_RELAYER_PRIVATE_KEY= -STARKNET_SEPOLIA_ACCOUNT_ADDRESS= -STARKNET_SEPOLIA_PRIVATE_KEY= +# Starknet accounts +STARKNET_DEVNET_ACCOUNT_ADDRESS= +STARKNET_DEVNET_PRIVATE_KEY= +# This default value is Anvil first account private key +STARKNET_DEVNET_EVM_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 KATANA_ACCOUNT_ADDRESS=0xb3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca KATANA_PRIVATE_KEY=0x2bbf4f9fd0bbb2e60b0316c1fe0b76cf7a4d0198bd493ced9b8df2a3a24d68a +# This default value is Anvil first account private key +KATANA_EVM_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -# Kakarot Sepolia (Testnet production and Testnet staging) -KAKAROT_SEPOLIA_ACCOUNT_ADDRESS= -KAKAROT_SEPOLIA_PRIVATE_KEY= -KAKAROT_SEPOLIA_RPC_URL=https://juno-kakarot-dev.karnot.xyz/ - -KAKAROT_STAGING_ACCOUNT_ADDRESS= -KAKAROT_STAGING_PRIVATE_KEY= -KAKAROT_STAGING_RPC_URL=https://juno-kakarot-testnet-stage.karnot.xyz +SEPOLIA_ACCOUNT_ADDRESS= +SEPOLIA_PRIVATE_KEY= +SEPOLIA_EVM_PRIVATE_KEY= -# An EVM address that receives the fees -KAKAROT_COINBASE_RECIPIENT=0x20eB005C0b9c906691F885eca5895338E15c36De +STAGING_ACCOUNT_ADDRESS= +STAGING_PRIVATE_KEY= +STAGING_EVM_PRIVATE_KEY= -# Default values in case no network match -ACCOUNT_ADDRESS= -PRIVATE_KEY= +MAINNET_ACCOUNT_ADDRESS= +MAINNET_PRIVATE_KEY= +MAINNET_EVM_PRIVATE_KEY= -# An EVM private to define a default EOA for EVM related kakarot_scripts -STARKNET_SEPOLIA_EVM_PRIVATE_KEY= -# This default value is Anvil first account private key -KATANA_EVM_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +# Network +STARKNET_NETWORK=katana +# Set to python to use the python implementation of Protocol Buffers # Because cairo-land generated files used protobuf<=3.20 and web3.py uses protobuf ~4 PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python @@ -54,11 +40,9 @@ PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python # the default Kakarot RPC URL of kakarot-rpc repo WEB3_HTTP_PROVIDER_URI="http://0.0.0.0:3030" +# Hypothesis profile HYPOTHESIS_PROFILE=dev -VOYAGER_API_URL= -VOYAGER_API_KEY= - # Private key to sign transactions for RLP scripts/compute_rlp_encoding.ts # Warning: Do not use this key in production systems PRIVATE_KEY_RLP_SCRIPT=0x6be0067ba259624aa28f796b703e7d095925a470b17786767bd09aaa3fc2ceea diff --git a/.github/workflows/ssj-ef-tests.yml b/.github/workflows/ssj-ef-tests.yml index 7bdd2abb6..fc227c4d3 100644 --- a/.github/workflows/ssj-ef-tests.yml +++ b/.github/workflows/ssj-ef-tests.yml @@ -11,7 +11,6 @@ permissions: read-all jobs: ef-tests: - # trunk-ignore(actionlint/runner-label) runs-on: ubuntu-latest-16-cores steps: - name: Checkout code diff --git a/.github/workflows/ssj-tests-unit.yml b/.github/workflows/ssj-tests-unit.yml index ab9068492..ee546688d 100644 --- a/.github/workflows/ssj-tests-unit.yml +++ b/.github/workflows/ssj-tests-unit.yml @@ -12,7 +12,7 @@ permissions: read-all jobs: unit-tests: - runs-on: ubuntu-latest-16-cores # trunk-ignore(actionlint/runner-label) + runs-on: ubuntu-latest-16-cores steps: - uses: actions/checkout@v4 - uses: foundry-rs/setup-snfoundry@v3 diff --git a/.gitignore b/.gitignore index 88dc841ef..bcfb427e4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,11 +8,10 @@ venv # starknet deployments/* -!deployments/kakarot-sepolia/ -!deployments/starknet-sepolia/ -!deployments/starknet-sepolia-staging/ -!deployments/starknet-mainnet/ -!deployments/kakarot-staging/ +!deployments/mainnet/ +!deployments/sepolia/ +!deployments/staging/ +!deployments/staging-core/ artifacts build diff --git a/.trunk/configs/.codespellrc b/.trunk/configs/.codespellrc index e4a1d2d22..347fe7d81 100644 --- a/.trunk/configs/.codespellrc +++ b/.trunk/configs/.codespellrc @@ -1,5 +1,5 @@ [codespell] -ignore-words-list = keypair,astroid,uvloop,crate +ignore-words-list = keypair,astroid,uvloop,crate,amountIn skip = '.git' check-filenames = check-hidden = diff --git a/.trunk/configs/ruff.toml b/.trunk/configs/ruff.toml index 346b1d9aa..1bcd9193a 100644 --- a/.trunk/configs/ruff.toml +++ b/.trunk/configs/ruff.toml @@ -1,5 +1,5 @@ # Generic, formatter-friendly config. -select = ["B", "D3", "D4", "E", "F"] +select = ["B", "D3", "D4", "E", "F", "ARG"] # Never enforce `E501` (line length violations). This should be handled by formatters. ignore = ["E501"] diff --git a/Makefile b/Makefile index 941af17cf..c168d88da 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ build: $(SSJ_DIR) declare: build build-sol uv run declare -deploy: build build-sol +deploy: declare uv run deploy fetch-ef-tests: diff --git a/cairo_zero/tests/src/backend/test_starknet.py b/cairo_zero/tests/src/backend/test_starknet.py index 41f7f65bc..b13e01c66 100644 --- a/cairo_zero/tests/src/backend/test_starknet.py +++ b/cairo_zero/tests/src/backend/test_starknet.py @@ -13,9 +13,9 @@ def test_should_return_env_with_given_origin_and_gas_price(self, cairo_run): class TestSaveValidJumpdests: @SyscallHandler.patch( "IERC20.balanceOf", - lambda addr, data: [0, 0], + lambda *_: [0, 0], ) - @SyscallHandler.patch("IAccount.write_jumpdests", lambda addr, data: []) + @SyscallHandler.patch("IAccount.write_jumpdests", lambda *_: []) def test_should_save_jumpdests_to_storage(self, cairo_run): jumpdests = {0x1: True, 0x10: False, 0x101: True} contract_address = 0x97283590 diff --git a/cairo_zero/tests/src/kakarot/accounts/test_account_contract.py b/cairo_zero/tests/src/kakarot/accounts/test_account_contract.py index b79eae432..ae9e37008 100644 --- a/cairo_zero/tests/src/kakarot/accounts/test_account_contract.py +++ b/cairo_zero/tests/src/kakarot/accounts/test_account_contract.py @@ -41,9 +41,9 @@ def bytecode(self, request): return random.randbytes(request.param) class TestInitialize: - @SyscallHandler.patch("IKakarot.register_account", lambda addr, data: []) - @SyscallHandler.patch("IKakarot.get_native_token", lambda addr, data: [0xDEAD]) - @SyscallHandler.patch("IERC20.approve", lambda addr, data: [1]) + @SyscallHandler.patch("IKakarot.register_account", lambda *_: []) + @SyscallHandler.patch("IKakarot.get_native_token", lambda *_: [0xDEAD]) + @SyscallHandler.patch("IERC20.approve", lambda *_: [1]) @SyscallHandler.patch("Ownable_owner", 0x1234) def test_should_set_storage_variables(self, cairo_run): cairo_run("test__initialize", evm_address=0xABDE1) @@ -64,7 +64,7 @@ def test_should_set_storage_variables(self, cairo_run): calldata=[0xABDE1], ) - @SyscallHandler.patch("IKakarot.register_account", lambda addr, data: []) + @SyscallHandler.patch("IKakarot.register_account", lambda *_: []) @SyscallHandler.patch("Account_is_initialized", 1) def test_should_run_only_once(self, cairo_run): with cairo_error(message="Account already initialized"): @@ -270,7 +270,7 @@ def test_should_execute_starknet_call(self, cairo_run): int(True) ] with SyscallHandler.patch( - function_selector, lambda addr, data: expected_return_data + function_selector, lambda *_: expected_return_data ): return_data, success = cairo_run( "test__execute_starknet_call", @@ -383,11 +383,11 @@ def test_should_raise_invalid_signature_for_invalid_chain_id_when_tx_type0_not_p chain_id=CHAIN_ID + 1, ) - @SyscallHandler.patch("IKakarot.get_native_token", lambda _, __: [0xDEAD]) - @SyscallHandler.patch("IERC20.balanceOf", lambda _, __: int_to_uint256(10**128)) + @SyscallHandler.patch("IKakarot.get_native_token", lambda *_: [0xDEAD]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: int_to_uint256(10**128)) @SyscallHandler.patch( "IKakarot.eth_send_raw_unsigned_tx", - lambda _, __: [1, 0x68656C6C6F, 1, 1], # hello + lambda *_: [1, 0x68656C6C6F, 1, 1], # hello ) def test_pass_authorized_pre_eip155_transaction(self, cairo_run): rlp_decoded = rlp.decode(PRE_EIP155_TX["ArachnidProxy"]["signed_tx"]) @@ -429,13 +429,13 @@ def test_pass_authorized_pre_eip155_transaction(self, cairo_run): assert output_len == 1 assert output[0] == 0x68656C6C6F - @SyscallHandler.patch("IERC20.balanceOf", lambda _, __: int_to_uint256(10**128)) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: int_to_uint256(10**128)) @SyscallHandler.patch( "IKakarot.eth_send_raw_unsigned_tx", - lambda _, __: [1, 0x68656C6C6F, 1, 1], # hello + lambda *_: [1, 0x68656C6C6F, 1, 1], # hello ) @pytest.mark.parametrize("transaction", TRANSACTIONS) - def test_pass_all_transactions_types(self, cairo_run, seed, transaction): + def test_pass_all_transactions_types(self, cairo_run, transaction): """ Note: the seeds 41 and 42 have been manually selected after observing that some private keys were making the Counter deploy transaction failing because their signature parameters length (s and v) @@ -466,10 +466,10 @@ def test_pass_all_transactions_types(self, cairo_run, seed, transaction): assert output_len == 1 assert output[0] == 0x68656C6C6F - @SyscallHandler.patch("IERC20.balanceOf", lambda _, __: int_to_uint256(10**128)) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: int_to_uint256(10**128)) @SyscallHandler.patch( "IKakarot.eth_send_raw_unsigned_tx", - lambda _, __: [1, 0x68656C6C6F, 1, 1], # hello + lambda *_: [1, 0x68656C6C6F, 1, 1], # hello ) def test_should_pass_all_data_len(self, cairo_run, bytecode): transaction = { diff --git a/cairo_zero/tests/src/kakarot/instructions/test_environmental_information.py b/cairo_zero/tests/src/kakarot/instructions/test_environmental_information.py index da1abcaeb..f6c36b669 100644 --- a/cairo_zero/tests/src/kakarot/instructions/test_environmental_information.py +++ b/cairo_zero/tests/src/kakarot/instructions/test_environmental_information.py @@ -40,17 +40,15 @@ def test_should_push_address(self, cairo_run): cairo_run("test__exec_address__should_push_address_to_stack") class TestExtCodeSize: - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) - @SyscallHandler.patch("IAccount.get_nonce", lambda addr, data: [1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) + @SyscallHandler.patch("IAccount.get_nonce", lambda *_: [1]) @SyscallHandler.patch( "Kakarot_evm_to_starknet_address", EXISTING_ACCOUNT, 0x1234 ) - @SyscallHandler.patch( - "IAccount.get_code_hash", lambda sn_addr, data: [0x1, 0x1] - ) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) def test_extcodesize_should_push_code_size(self, cairo_run, bytecode, address): with SyscallHandler.patch( - "IAccount.bytecode", lambda addr, data: [len(bytecode), *bytecode] + "IAccount.bytecode", lambda *_: [len(bytecode), *bytecode] ): output = cairo_run("test__exec_extcodesize", address=address) @@ -66,20 +64,18 @@ class TestExtCodeCopy: "offset_is_bytecodelen", ], ) - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) - @SyscallHandler.patch("IAccount.get_nonce", lambda addr, data: [1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) + @SyscallHandler.patch("IAccount.get_nonce", lambda *_: [1]) @SyscallHandler.patch( "Kakarot_evm_to_starknet_address", EXISTING_ACCOUNT, 0x1234 ) - @SyscallHandler.patch( - "IAccount.get_code_hash", lambda sn_addr, data: [0x1, 0x1] - ) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) def test_extcodecopy_should_copy_code( self, cairo_run, size, offset, dest_offset, bytecode, address ): with SyscallHandler.patch( - "IAccount.bytecode", lambda addr, data: [len(bytecode), *bytecode] + "IAccount.bytecode", lambda *_: [len(bytecode), *bytecode] ): memory = cairo_run( "test__exec_extcodecopy", @@ -109,21 +105,19 @@ def test_extcodecopy_should_copy_code( "size_is_0", ], ) - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) - @SyscallHandler.patch("IAccount.get_nonce", lambda addr, data: [1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) + @SyscallHandler.patch("IAccount.get_nonce", lambda *_: [1]) @SyscallHandler.patch( "Kakarot_evm_to_starknet_address", EXISTING_ACCOUNT, 0x1234 ) - @SyscallHandler.patch( - "IAccount.get_code_hash", lambda sn_addr, data: [0x1, 0x1] - ) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) def test_extcodecopy_offset_high_zellic_issue_1258( self, cairo_run, size, bytecode, address ): offset_high = 1 with SyscallHandler.patch( - "IAccount.bytecode", lambda addr, data: [len(bytecode), *bytecode] + "IAccount.bytecode", lambda *_: [len(bytecode), *bytecode] ): memory = cairo_run( "test__exec_extcodecopy_zellic_issue_1258", @@ -228,13 +222,13 @@ def test_gasprice(self, cairo_run): class TestExtCodeHash: @SyscallHandler.patch( "IERC20.balanceOf", - lambda sn_addr, data: ( + lambda sn_addr, _: ( [0, 1] if sn_addr == EXISTING_ACCOUNT_SN_ADDR else [0, 0] ), ) @SyscallHandler.patch( "IAccount.get_nonce", - lambda sn_addr, data: [1] if sn_addr == EXISTING_ACCOUNT_SN_ADDR else [0], + lambda sn_addr, _: [1] if sn_addr == EXISTING_ACCOUNT_SN_ADDR else [0], ) @SyscallHandler.patch( "Kakarot_evm_to_starknet_address", @@ -247,11 +241,11 @@ def test_extcodehash__should_push_hash( with ( SyscallHandler.patch( "IAccount.bytecode", - lambda sn_addr, data: [len(bytecode), *bytecode], + lambda *_: [len(bytecode), *bytecode], ), SyscallHandler.patch( "IAccount.get_code_hash", - lambda sn_addr, data: [*int_to_uint256(bytecode_hash)], + lambda *_: [*int_to_uint256(bytecode_hash)], ), ): output = cairo_run("test__exec_extcodehash", address=address) diff --git a/cairo_zero/tests/src/kakarot/precompiles/test_precompiles.py b/cairo_zero/tests/src/kakarot/precompiles/test_precompiles.py index e4fc74c46..9d040c3b6 100644 --- a/cairo_zero/tests/src/kakarot/precompiles/test_precompiles.py +++ b/cairo_zero/tests/src/kakarot/precompiles/test_precompiles.py @@ -83,9 +83,9 @@ class TestKakarotPrecompiles: AUTHORIZED_CALLER_CODE, 1, ) - @SyscallHandler.patch_deploy(lambda class_hash, data: [0]) + @SyscallHandler.patch("deploy", lambda *_: [0]) @SyscallHandler.patch("Kakarot_evm_to_starknet_address", CALLER_ADDRESS, 0) - @SyscallHandler.patch("ICairo.inc", lambda addr, data: []) + @SyscallHandler.patch("ICairo.inc", lambda *_: []) def test_should_deploy_account_when_sender_starknet_address_zero( self, cairo_run, @@ -188,10 +188,10 @@ def test__cairo_precompiles( ] with SyscallHandler.patch( "ICairo.inc", - lambda addr, data: [], + lambda *_: [], ), SyscallHandler.patch( "ICairo.get", - lambda addr, data: cairo_return_data, + lambda *_: cairo_return_data, ): return_data, reverted, gas_used = cairo_run( "test__precompiles_run", diff --git a/cairo_zero/tests/src/kakarot/test_account.py b/cairo_zero/tests/src/kakarot/test_account.py index 046c39d0a..d63d6d243 100644 --- a/cairo_zero/tests/src/kakarot/test_account.py +++ b/cairo_zero/tests/src/kakarot/test_account.py @@ -57,7 +57,7 @@ def test_should_store_value_at_key(self, cairo_run, key, value): class TestOriginalStorage: @pytest.mark.parametrize("key, value", [(0, 0), (2**256 - 1, 2**256 - 1)]) - @SyscallHandler.patch("IAccount.storage", lambda addr, data: [0x1337, 0]) + @SyscallHandler.patch("IAccount.storage", lambda *_: [0x1337, 0]) @SyscallHandler.patch("Kakarot_evm_to_starknet_address", 0xABDE1, 0x1234) def test_should_return_original_storage_when_state_modified( self, cairo_run, key, value @@ -97,9 +97,7 @@ class TestHasCodeOrNonce: (1, [1], True), ), ) - @SyscallHandler.patch( - "IAccount.get_code_hash", lambda sn_addr, data: [0x1, 0x1] - ) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) def test_should_return_true_when_nonce( self, cairo_run, nonce, code, expected_result ): diff --git a/cairo_zero/tests/src/kakarot/test_evm.py b/cairo_zero/tests/src/kakarot/test_evm.py index 18695cdf1..0bc640fc1 100644 --- a/cairo_zero/tests/src/kakarot/test_evm.py +++ b/cairo_zero/tests/src/kakarot/test_evm.py @@ -23,13 +23,13 @@ class TestExecutionContext: ) @SyscallHandler.patch( "IERC20.balanceOf", - lambda addr, data: [0, 0], + lambda *_: [0, 0], ) def test_jump(self, cairo_run, bytecode, jumpdest, new_pc, expected_return_data): with SyscallHandler.patch( "IAccount.is_valid_jumpdest", - lambda addr, data: [1 if len(expected_return_data) == 0 else 0], + lambda *_: [1 if len(expected_return_data) == 0 else 0], ): evm = cairo_run("test__jump", bytecode=bytecode, jumpdest=jumpdest) assert evm["program_counter"] == new_pc @@ -58,11 +58,11 @@ def test_should_return_cached_valid_jumpdest( @SyscallHandler.patch( "IERC20.balanceOf", - lambda addr, data: [0, 0], + lambda *_: [0, 0], ) @SyscallHandler.patch( "IAccount.is_valid_jumpdest", - lambda addr, data: [1 if data == [0x10] else 0], + lambda _, data: [1 if data == [0x10] else 0], ) @pytest.mark.parametrize( "cached_jumpdests, index, expected", diff --git a/cairo_zero/tests/src/kakarot/test_kakarot.py b/cairo_zero/tests/src/kakarot/test_kakarot.py index d2b1d0027..48baf50aa 100644 --- a/cairo_zero/tests/src/kakarot/test_kakarot.py +++ b/cairo_zero/tests/src/kakarot/test_kakarot.py @@ -375,7 +375,7 @@ def test_should_assert_only_owner(self, cairo_run): "Kakarot_evm_to_starknet_address", EVM_ADDRESS, 0x99999 ) @SyscallHandler.patch("Ownable_owner", SyscallHandler.caller_address) - @SyscallHandler.patch("IAccount.upgrade", lambda addr, data: []) + @SyscallHandler.patch("IAccount.upgrade", lambda *_: []) def test_upgrade_account_should_replace_class(self, cairo_run): cairo_run( "test__upgrade_account", @@ -401,11 +401,29 @@ def test_should_assert_unpaused(self, cairo_run): data=[], ) + def test_should_not_handle_message_from_non_l1_messaging_contract( + self, cairo_run + ): + """ + Test that the L1 handler does not handle messages when from_address is not the L1 + messaging contract address (default is address 0). + If the message were handled, this would fail because no patches are set (e.g. balanceOf, + deploy, all the IAccount interface methods). + """ + cairo_run( + "test__handle_l1_message", + from_address=0xDEAD, + l1_sender=0xABDE1, + to_address=0xABDE1, + value=0x1234, + data=[], + ) + class TestEthCall: @pytest.mark.slow @pytest.mark.SolmateERC20 - @SyscallHandler.patch("IAccount.is_valid_jumpdest", lambda addr, data: [1]) - @SyscallHandler.patch("IAccount.get_code_hash", lambda addr, data: [0x1, 0x1]) + @SyscallHandler.patch("IAccount.is_valid_jumpdest", lambda *_: [1]) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) def test_erc20_transfer(self, get_contract): erc20 = get_contract("Solmate", "ERC20") amount = int(1e18) @@ -426,8 +444,8 @@ def test_erc20_transfer(self, get_contract): @pytest.mark.slow @pytest.mark.SolmateERC721 - @SyscallHandler.patch("IAccount.is_valid_jumpdest", lambda addr, data: [1]) - @SyscallHandler.patch("IAccount.get_code_hash", lambda addr, data: [0x1, 0x1]) + @SyscallHandler.patch("IAccount.is_valid_jumpdest", lambda *_: [1]) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) def test_erc721_transfer(self, get_contract): erc721 = get_contract("Solmate", "ERC721") token_id = 1337 @@ -516,9 +534,9 @@ def test_failing_contract(self, cairo_run): ) assert not evm["reverted"] - @SyscallHandler.patch("IAccount.is_valid_jumpdest", lambda addr, data: [1]) - @SyscallHandler.patch("IAccount.get_code_hash", lambda addr, data: [0x1, 0x1]) - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0x1, 0x1]) + @SyscallHandler.patch("IAccount.is_valid_jumpdest", lambda *_: [1]) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0x1, 0x1]) def test_create_tx_returndata_should_be_20_bytes_evm_address(self, cairo_run): """ Bug reported by Protofire for the simulation of the create tx using eth_call. @@ -578,7 +596,7 @@ def test_should_raise_invalid_chain_id_tx_type_different_from_0( tx_data=tx_data, ) - @SyscallHandler.patch("IAccount.get_nonce", lambda addr, data: [1]) + @SyscallHandler.patch("IAccount.get_nonce", lambda *_: [1]) @SyscallHandler.patch("Kakarot_chain_id", CHAIN_ID) @pytest.mark.parametrize("tx", TRANSACTIONS) def test_should_raise_invalid_nonce(self, cairo_run, tx): @@ -593,7 +611,7 @@ def test_should_raise_invalid_nonce(self, cairo_run, tx): ) @SyscallHandler.patch("Kakarot_chain_id", CHAIN_ID) - @SyscallHandler.patch("IAccount.get_nonce", lambda _, __: [34]) + @SyscallHandler.patch("IAccount.get_nonce", lambda *_: [34]) @given(gas_limit=integers(min_value=2**64, max_value=2**248 - 1)) def test_raise_gas_limit_too_high(self, cairo_run, gas_limit): tx = { @@ -618,7 +636,7 @@ def test_raise_gas_limit_too_high(self, cairo_run, gas_limit): ) @SyscallHandler.patch("Kakarot_chain_id", CHAIN_ID) - @SyscallHandler.patch("IAccount.get_nonce", lambda _, __: [34]) + @SyscallHandler.patch("IAccount.get_nonce", lambda *_: [34]) @given(maxFeePerGas=integers(min_value=2**128, max_value=2**248 - 1)) def test_raise_max_fee_per_gas_too_high(self, cairo_run, maxFeePerGas): tx = { @@ -648,7 +666,7 @@ def test_raise_transaction_gas_limit_too_high(self, cairo_run, tx): tx_data = list(rlp_encode_signed_data(tx)) with ( - SyscallHandler.patch("IAccount.get_nonce", lambda _, __: [tx["nonce"]]), + SyscallHandler.patch("IAccount.get_nonce", lambda *_: [tx["nonce"]]), cairo_error(message="Transaction gas_limit > Block gas_limit"), ): cairo_run( @@ -665,7 +683,7 @@ def test_raise_max_fee_per_gas_too_low(self, cairo_run, tx): tx_data = list(rlp_encode_signed_data(tx)) with ( - SyscallHandler.patch("IAccount.get_nonce", lambda _, __: [tx["nonce"]]), + SyscallHandler.patch("IAccount.get_nonce", lambda *_: [tx["nonce"]]), cairo_error(message="Max fee per gas too low"), ): cairo_run( @@ -683,7 +701,7 @@ def max_priority_fee_too_high(draw): return (max_fee_per_gas, max_priority_fee_per_gas) @SyscallHandler.patch("Kakarot_block_gas_limit", TRANSACTION_GAS_LIMIT) - @SyscallHandler.patch("IAccount.get_nonce", lambda _, __: [34]) + @SyscallHandler.patch("IAccount.get_nonce", lambda *_: [34]) @SyscallHandler.patch("Kakarot_chain_id", CHAIN_ID) @given(max_priority_fee_too_high()) def test_raise_max_priority_fee_too_high( @@ -710,16 +728,16 @@ def test_raise_max_priority_fee_too_high( tx_data=tx_data, ) - @SyscallHandler.patch("IERC20.balanceOf", lambda _, __: [0, 0]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 0]) @SyscallHandler.patch("Kakarot_block_gas_limit", TRANSACTION_GAS_LIMIT) - @SyscallHandler.patch("IAccount.get_evm_address", lambda _, __: [0xABDE1]) + @SyscallHandler.patch("IAccount.get_evm_address", lambda *_: [0xABDE1]) @SyscallHandler.patch("Kakarot_chain_id", CHAIN_ID) @pytest.mark.parametrize("tx", TRANSACTIONS) def test_raise_not_enough_ETH_balance(self, cairo_run, tx): tx_data = list(rlp_encode_signed_data(tx)) with ( - SyscallHandler.patch("IAccount.get_nonce", lambda _, __: [tx["nonce"]]), + SyscallHandler.patch("IAccount.get_nonce", lambda *_: [tx["nonce"]]), cairo_error(message="Not enough ETH to pay msg.value + max gas fees"), ): cairo_run( @@ -731,8 +749,8 @@ def test_raise_not_enough_ETH_balance(self, cairo_run, tx): class TestLoopProfiling: @pytest.mark.slow @pytest.mark.NoCI - @SyscallHandler.patch("IAccount.is_valid_jumpdest", lambda addr, data: [1]) - @SyscallHandler.patch("IAccount.get_code_hash", lambda addr, data: [0x1, 0x1]) + @SyscallHandler.patch("IAccount.is_valid_jumpdest", lambda *_: [1]) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) @pytest.mark.parametrize("steps", [10, 50, 100, 200]) def test_loop_profiling(self, get_contract, steps): plain_opcodes = get_contract("PlainOpcodes", "PlainOpcodes") diff --git a/cairo_zero/tests/src/kakarot/test_state.py b/cairo_zero/tests/src/kakarot/test_state.py index 1da73f048..fd1e43b10 100644 --- a/cairo_zero/tests/src/kakarot/test_state.py +++ b/cairo_zero/tests/src/kakarot/test_state.py @@ -17,7 +17,7 @@ def test_should_return_state_with_default_dicts(self, cairo_run): cairo_run("test__init__should_return_state_with_default_dicts") class TestCopy: - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) def test_should_return_new_state_with_same_attributes(self, cairo_run): cairo_run("test__copy__should_return_new_state_with_same_attributes") @@ -45,19 +45,17 @@ def test_should_return_true_when_existing_account_cached( ) assert is_alive == expected_result - @SyscallHandler.patch("IAccount.bytecode", lambda addr, data: [1, [0x2]]) - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) - @SyscallHandler.patch("IAccount.get_nonce", lambda addr, data: [1]) + @SyscallHandler.patch("IAccount.bytecode", lambda *_: [1, [0x2]]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) + @SyscallHandler.patch("IAccount.get_nonce", lambda *_: [1]) @SyscallHandler.patch("Kakarot_evm_to_starknet_address", 0xABDE1, 0x1234) - @SyscallHandler.patch( - "IAccount.get_code_hash", lambda sn_addr, data: [0x1, 0x1] - ) + @SyscallHandler.patch("IAccount.get_code_hash", lambda *_: [0x1, 0x1]) def test_should_return_true_when_existing_account_not_cached(self, cairo_run): cairo_run( "test__is_account_alive__account_alive_not_in_state", ) - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 0]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 0]) @SyscallHandler.patch("Kakarot_evm_to_starknet_address", 0xABDE1, 0) def test_should_return_false_when_not_in_state_nor_starknet(self, cairo_run): cairo_run("test__is_account_alive__account_not_alive_not_in_state") @@ -66,36 +64,36 @@ class TestIsAccountWarm: def test_should_return_true_when_account_in_state(self, cairo_run): cairo_run("test__is_account_warm__account_in_state") - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) def test_should_return_false_when_account_not_state(self, cairo_run): cairo_run("test__is_account_warm__account_not_in_state") - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) def test_should_warm_up_account(self, cairo_run): cairo_run("test__is_account_warm__warms_up_account") class TestIsStorageWarm: - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) def test_should_return_true_when_already_read(self, cairo_run): cairo_run("test__is_storage_warm__should_return_true_when_already_read") - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) def test_should_return_true_when_already_written(self, cairo_run): cairo_run("test__is_storage_warm__should_return_true_when_already_written") - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) def test_should_return_false_when_not_accessed(self, cairo_run): cairo_run("test__is_storage_warm__should_return_false_when_not_accessed") class TestCachePreaccessedAddresses: - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) def test_should_cache_precompiles(self, cairo_run): state = cairo_run("test__cache_precompiles") assert list(map(Web3.to_checksum_address, state["accounts"].keys())) == [ Web3.to_checksum_address(f"0x{i:040x}") for i in range(1, 11) ] - @SyscallHandler.patch("IERC20.balanceOf", lambda addr, data: [0, 1]) + @SyscallHandler.patch("IERC20.balanceOf", lambda *_: [0, 1]) @pytest.mark.parametrize("transaction", TRANSACTIONS) def test_should_cache_access_list(self, cairo_run, transaction): access_list = transaction.get("accessList") or () diff --git a/conftest.py b/conftest.py index 9bf0ed679..b7da70155 100644 --- a/conftest.py +++ b/conftest.py @@ -1,13 +1,14 @@ import asyncio import logging import os +import random import pytest from dotenv import load_dotenv from hypothesis import Phase, Verbosity, settings from starkware.cairo.lang.instances import LAYOUTS -load_dotenv() +load_dotenv(override=True) logging.getLogger("asyncio").setLevel(logging.ERROR) logger = logging.getLogger() @@ -34,7 +35,7 @@ def pytest_addoption(parser): parser.addoption( "--seed", action="store", - default=None, + default=random.randint(0, 2**64 - 1), type=int, help="The seed to set random with.", ) @@ -48,13 +49,26 @@ def event_loop(): @pytest.fixture(autouse=True, scope="session") -def seed(request): - if request.config.getoption("seed") is not None: - import random +def seed(request, worker_id): + """ + Set the seed for the random module. - logger.info(f"Setting seed to {request.config.getoption('seed')}") + If a seed is provided in the command line, we use it to have pseudo-randomness + across tests (i.e. deterministic tests). - random.seed(request.config.getoption("seed")) + If no seed is provided, we use a random seed. + + The worker_id is used as a salt to avoid collisions between tests in different workers. + """ + import random + + salt = abs(hash(worker_id)) + logger.info(f"Using salt {salt} for worker {worker_id}") + + seed = request.config.getoption("seed") + salt + + logger.info(f"Setting seed to {seed}") + random.seed(seed) pytest_plugins = ["tests.fixtures.starknet"] diff --git a/deployments/kakarot-sepolia/declarations.json b/deployments/kakarot-sepolia/declarations.json deleted file mode 100644 index 5cd4db417..000000000 --- a/deployments/kakarot-sepolia/declarations.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "kakarot": "0x2cc6b6c7488130a31a9028dd67ee736146532516ffa74b780658647b860a33", - "account_contract": "0x75cf60ff9ba89b630f64830245f04439c8749210e58d2192349b7f05d2407c0", - "account_contract_fixture": "0x817604863b7aa6189122443161d885d32c372d468d2a099af0658132131114", - "uninitialized_account": "0x600f6862938312a05a0cfecba0dcaf37693efc9e4075a6adfb62e196022678e", - "EVM": "0x42f8c19050c35a8e3e4cb165ddd03646258802a0bb0cbbc41e855020410615e", - "OpenzeppelinAccount": "0x6153ccf69fd20f832c794df36e19135f0070d0576144f0b47f75a226e4be530", - "Cairo1Helpers": "0x28ece3751ecf5bdf2d791eb64a65bfb6a8816432b698870dba2f38a36101d58", - "Cairo1HelpersFixture": "0x4e7811d9bbba41193bd3c77d05c16f7aaa55dd1d601686b50f6fa0e3766a712", - "replace_class": "0xa187318c5e79b010cf45975f589f0a8d441fadde5b1e7ccad46501568437b5", - "Counter": "0x2abf5b9916d3c6ae6000ab239bf5aba8b40d9a1750ffc54b6d281ac83137382", - "MockPragmaOracle": "0x675f00328ff84f127d71b179b3f3a3a06ce8432054770cddd5729c8d62866da" -} diff --git a/deployments/kakarot-sepolia/deployments.json b/deployments/kakarot-sepolia/deployments.json deleted file mode 100644 index 1839e658f..000000000 --- a/deployments/kakarot-sepolia/deployments.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "kakarot": { - "address": "0x11c5faab8a76b3caff6e243b8d13059a7fb723a0ca12bbaadde95fb9e501bda", - "tx": "0x207a62725950583c5dc7afd67220c11ad99154d9c64b75708efb46b667b0818", - "artifact": "build/kakarot.json" - } -} diff --git a/deployments/kakarot-sepolia/l1-addresses.json b/deployments/kakarot-sepolia/l1-addresses.json deleted file mode 100644 index a365173e0..000000000 --- a/deployments/kakarot-sepolia/l1-addresses.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "StarknetCore": { - "address": "0x74ca1ac5bd4c3c97006d2b7b9375dd3b6c17accd" - } -} diff --git a/deployments/kakarot-staging/declarations.json b/deployments/kakarot-staging/declarations.json deleted file mode 100644 index 6850b04b1..000000000 --- a/deployments/kakarot-staging/declarations.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "kakarot": "0x32eb8cc160720993d8c4fdc1d42ad352706c582ae4896ef105533afeb3ad41", - "account_contract": "0x7a6bb0f84c626d4431bfd32a669546642505c339d0b539db4210e61dfc43e1d", - "account_contract_fixture": "0x7f49ba9ed70cf42c7f5da5d4254bb60db3141bb13f659b44ba69c8124a339bd", - "uninitialized_account": "0x600f6862938312a05a0cfecba0dcaf37693efc9e4075a6adfb62e196022678e", - "EVM": "0x22bc1a47df4b54a622f4aaa11b3b7224df464980cb8d69ea05a89c42b906ab4", - "OpenzeppelinAccount": "0x6153ccf69fd20f832c794df36e19135f0070d0576144f0b47f75a226e4be530", - "Cairo1Helpers": "0x28ece3751ecf5bdf2d791eb64a65bfb6a8816432b698870dba2f38a36101d58", - "Cairo1HelpersFixture": "0x4e7811d9bbba41193bd3c77d05c16f7aaa55dd1d601686b50f6fa0e3766a712", - "replace_class": "0xa187318c5e79b010cf45975f589f0a8d441fadde5b1e7ccad46501568437b5", - "Counter": "0x4fc47610d8c9ce0bcfc2f9e03658f0fbcd3e0a9c351a1aa59d465a33533a7c8", - "MockPragmaOracle": "0x675f00328ff84f127d71b179b3f3a3a06ce8432054770cddd5729c8d62866da" -} diff --git a/deployments/kakarot-staging/deployments.json b/deployments/kakarot-staging/deployments.json deleted file mode 100644 index 4d4eb2461..000000000 --- a/deployments/kakarot-staging/deployments.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "kakarot": { - "address": "0x2824d6ed6759ac4c4a54a39b78d04c0e48be8937237026bf8c3bf46a8bea722", - "tx": "0x1f45a18adeb4392601cba7e3fd5683bac007378cede633fe6df0b5c95267e9d", - "artifact": "build/kakarot.json" - }, - "EVM": { - "address": "0x353af95c41e8788d23e393e13c6b73ffd172188f27e5b169d792b5c80be087e", - "tx": "0x68229e926981041efc89f808547bba75269d4871f15e7926d1c2c1d02dcb509", - "artifact": "build/fixtures/EVM.json" - }, - "Counter": { - "address": "0x53ed7428188383b6cbf361ca62cb4ef7b897c9d4b4ff0fe6edd0fde19225d8b", - "tx": "0x739edaf9a1c5a7e6b48768158771673da6b98c0dbec31f1d3c113fe04d90b51", - "artifact": "build/fixtures/Counter.json" - }, - "MockPragmaOracle": { - "address": "0xd5acd9ad298fd564cf71d1c7c9a4b1ca37b45a5a8bd4b3d88ba6d1ebf87618", - "tx": "0x27f878dbcff30f3d0a031bd5af2af6feb269f5e41df545b92f2ef875bcd385f", - "artifact": "build/ssj/contracts_MockPragmaOracle" - } -} diff --git a/deployments/kakarot-staging/l1-addresses.json b/deployments/kakarot-staging/l1-addresses.json deleted file mode 100644 index ab00407ec..000000000 --- a/deployments/kakarot-staging/l1-addresses.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "StarknetCore": { - "address": "0xc7c9ea7fD0921Cb6EDd9a3184F88cF1b821aA82B" - } -} diff --git a/deployments/starknet-mainnet/declarations.json b/deployments/mainnet/declarations.json similarity index 67% rename from deployments/starknet-mainnet/declarations.json rename to deployments/mainnet/declarations.json index 2a8990def..4435ec835 100644 --- a/deployments/starknet-mainnet/declarations.json +++ b/deployments/mainnet/declarations.json @@ -1,18 +1,18 @@ { - "account_contract": "0x24d700216e7f5a33f7e1426b550bcbba17acd52c5c645ba1e01e783b5cbafab", - "BalanceSender": "0xe85f18e5d88f398b84beba1faf6818fa461c93bc22e13af873d203d0ce1489", + "account_contract": "0x6d8537c7a5d4c20e616a137c11ee87601bf8d3e924091ce0f283820d3a8e9fe", + "BalanceSender": "0x292ec825bc8f7a528218ca8a3306684fbf53589afe5626b2c71790f893ac39a", "BenchmarkCairoCalls": "0x58dc8a979af32668e05579313d1d6c672d3b668f72778780e8b2e97964159c3", "Cairo1Helpers": "0x6c84a7ed6ee3fa25d198f058b8c8a06d9d4e4dc040efd6fa4d741f00fdc1b63", "Cairo1HelpersFixture": "0x3810527e57a1df22d701b2c48f3d739e8fe3550876cb16435706d1448f89cbe", "Counter": "0x27ccfaf84757dabd7885d410018bf0e264c881e4799a47f555b96bf21e5af5b", - "ERC20": "0xb36ee7670ae475d6c195e066201a526f7d850bb01961850405dcbd7aedd9bc", - "EVM": "0x2a754741315d3267c71386a5c02e247a1879ab5775997f75b8e3b386e2a09ab", - "kakarot": "0x27a3d4582f5401b0212a449492811c074d5d823d05c8ebc100dee6242a32f16", + "ERC20": "0x4254337f7006c7c084dd9b13788b20e299791a5449a42f1b1b2f79929295fe7", + "EVM": "0x43874217327a745d07d5048a6a62d56dea6874aad134c6f21cd717aa5ae10ae", + "kakarot": "0xd86d695be75d6ad8230240725f827aa6818cbd9de8af6b544ede6d5ad06a42", "MockPragmaOracle": "0x62b05bb353abcee67e5ebc49bfb1c3582151963a15a02a56cefc0bb4497ee59", "MockPragmaSummaryStats": "0x70cebf28afbc91d72f0adde181565ae21f5b5f37ab712ac96a079cd4a97051f", "OpenzeppelinAccount": "0x3a58e037be64a3608dfe423eeb8a77b400b0f56f1f5e0ed4937d3c873f988e2", "replace_class": "0x451a4decb11b581b288d8a0512ab6f6ea7f1fd89caefbb415e510ec7f17efe1", - "StarknetToken": "0x314a6a9f01e5a28beb6a7e2e8907243469d98a7e364054657e7593bea5dcee7", + "StarknetToken": "0x6f21cf3ad9047d263aa8cc3a0565fcacff33a13746348017b2ad851d23f3290", "uninitialized_account_fixture": "0x60d4817e4e3881965ff4e27a55a4a7da7bf2865c7209bdb367af2f86c740b35", "uninitialized_account": "0x7b2de5e73ff7eb338d76c967dd5aa3f3004574d326b8c1402bb819d4983b8b6", "UniversalLibraryCaller": "0x244fd35db35b48882ca2e6c2966821bd54f302b131fb22ea98e5534da390482" diff --git a/deployments/starknet-mainnet/deployments.json b/deployments/mainnet/deployments.json similarity index 100% rename from deployments/starknet-mainnet/deployments.json rename to deployments/mainnet/deployments.json diff --git a/deployments/starknet-mainnet/kakarot_deployments.json b/deployments/mainnet/kakarot_deployments.json similarity index 100% rename from deployments/starknet-mainnet/kakarot_deployments.json rename to deployments/mainnet/kakarot_deployments.json diff --git a/deployments/starknet-mainnet/l1_addresses.json b/deployments/mainnet/l1_addresses.json similarity index 100% rename from deployments/starknet-mainnet/l1_addresses.json rename to deployments/mainnet/l1_addresses.json diff --git a/deployments/starknet-sepolia/declarations.json b/deployments/sepolia/declarations.json similarity index 67% rename from deployments/starknet-sepolia/declarations.json rename to deployments/sepolia/declarations.json index 2a8990def..4435ec835 100644 --- a/deployments/starknet-sepolia/declarations.json +++ b/deployments/sepolia/declarations.json @@ -1,18 +1,18 @@ { - "account_contract": "0x24d700216e7f5a33f7e1426b550bcbba17acd52c5c645ba1e01e783b5cbafab", - "BalanceSender": "0xe85f18e5d88f398b84beba1faf6818fa461c93bc22e13af873d203d0ce1489", + "account_contract": "0x6d8537c7a5d4c20e616a137c11ee87601bf8d3e924091ce0f283820d3a8e9fe", + "BalanceSender": "0x292ec825bc8f7a528218ca8a3306684fbf53589afe5626b2c71790f893ac39a", "BenchmarkCairoCalls": "0x58dc8a979af32668e05579313d1d6c672d3b668f72778780e8b2e97964159c3", "Cairo1Helpers": "0x6c84a7ed6ee3fa25d198f058b8c8a06d9d4e4dc040efd6fa4d741f00fdc1b63", "Cairo1HelpersFixture": "0x3810527e57a1df22d701b2c48f3d739e8fe3550876cb16435706d1448f89cbe", "Counter": "0x27ccfaf84757dabd7885d410018bf0e264c881e4799a47f555b96bf21e5af5b", - "ERC20": "0xb36ee7670ae475d6c195e066201a526f7d850bb01961850405dcbd7aedd9bc", - "EVM": "0x2a754741315d3267c71386a5c02e247a1879ab5775997f75b8e3b386e2a09ab", - "kakarot": "0x27a3d4582f5401b0212a449492811c074d5d823d05c8ebc100dee6242a32f16", + "ERC20": "0x4254337f7006c7c084dd9b13788b20e299791a5449a42f1b1b2f79929295fe7", + "EVM": "0x43874217327a745d07d5048a6a62d56dea6874aad134c6f21cd717aa5ae10ae", + "kakarot": "0xd86d695be75d6ad8230240725f827aa6818cbd9de8af6b544ede6d5ad06a42", "MockPragmaOracle": "0x62b05bb353abcee67e5ebc49bfb1c3582151963a15a02a56cefc0bb4497ee59", "MockPragmaSummaryStats": "0x70cebf28afbc91d72f0adde181565ae21f5b5f37ab712ac96a079cd4a97051f", "OpenzeppelinAccount": "0x3a58e037be64a3608dfe423eeb8a77b400b0f56f1f5e0ed4937d3c873f988e2", "replace_class": "0x451a4decb11b581b288d8a0512ab6f6ea7f1fd89caefbb415e510ec7f17efe1", - "StarknetToken": "0x314a6a9f01e5a28beb6a7e2e8907243469d98a7e364054657e7593bea5dcee7", + "StarknetToken": "0x6f21cf3ad9047d263aa8cc3a0565fcacff33a13746348017b2ad851d23f3290", "uninitialized_account_fixture": "0x60d4817e4e3881965ff4e27a55a4a7da7bf2865c7209bdb367af2f86c740b35", "uninitialized_account": "0x7b2de5e73ff7eb338d76c967dd5aa3f3004574d326b8c1402bb819d4983b8b6", "UniversalLibraryCaller": "0x244fd35db35b48882ca2e6c2966821bd54f302b131fb22ea98e5534da390482" diff --git a/deployments/starknet-sepolia/deployments.json b/deployments/sepolia/deployments.json similarity index 100% rename from deployments/starknet-sepolia/deployments.json rename to deployments/sepolia/deployments.json diff --git a/deployments/starknet-sepolia/kakarot_deployments.json b/deployments/sepolia/kakarot_deployments.json similarity index 100% rename from deployments/starknet-sepolia/kakarot_deployments.json rename to deployments/sepolia/kakarot_deployments.json diff --git a/deployments/starknet-sepolia/l1_addresses.json b/deployments/sepolia/l1_addresses.json similarity index 100% rename from deployments/starknet-sepolia/l1_addresses.json rename to deployments/sepolia/l1_addresses.json diff --git a/deployments/starknet-sepolia-staging/declarations.json b/deployments/staging-core/declarations.json similarity index 66% rename from deployments/starknet-sepolia-staging/declarations.json rename to deployments/staging-core/declarations.json index c47f8e0c7..4435ec835 100644 --- a/deployments/starknet-sepolia-staging/declarations.json +++ b/deployments/staging-core/declarations.json @@ -1,19 +1,19 @@ { - "account_contract": "0x24d700216e7f5a33f7e1426b550bcbba17acd52c5c645ba1e01e783b5cbafab", - "BalanceSender": "0xe85f18e5d88f398b84beba1faf6818fa461c93bc22e13af873d203d0ce1489", + "account_contract": "0x6d8537c7a5d4c20e616a137c11ee87601bf8d3e924091ce0f283820d3a8e9fe", + "BalanceSender": "0x292ec825bc8f7a528218ca8a3306684fbf53589afe5626b2c71790f893ac39a", "BenchmarkCairoCalls": "0x58dc8a979af32668e05579313d1d6c672d3b668f72778780e8b2e97964159c3", "Cairo1Helpers": "0x6c84a7ed6ee3fa25d198f058b8c8a06d9d4e4dc040efd6fa4d741f00fdc1b63", "Cairo1HelpersFixture": "0x3810527e57a1df22d701b2c48f3d739e8fe3550876cb16435706d1448f89cbe", "Counter": "0x27ccfaf84757dabd7885d410018bf0e264c881e4799a47f555b96bf21e5af5b", - "ERC20": "0xb36ee7670ae475d6c195e066201a526f7d850bb01961850405dcbd7aedd9bc", - "EVM": "0x2a754741315d3267c71386a5c02e247a1879ab5775997f75b8e3b386e2a09ab", - "kakarot": "0x27a3d4582f5401b0212a449492811c074d5d823d05c8ebc100dee6242a32f16", + "ERC20": "0x4254337f7006c7c084dd9b13788b20e299791a5449a42f1b1b2f79929295fe7", + "EVM": "0x43874217327a745d07d5048a6a62d56dea6874aad134c6f21cd717aa5ae10ae", + "kakarot": "0xd86d695be75d6ad8230240725f827aa6818cbd9de8af6b544ede6d5ad06a42", "MockPragmaOracle": "0x62b05bb353abcee67e5ebc49bfb1c3582151963a15a02a56cefc0bb4497ee59", "MockPragmaSummaryStats": "0x70cebf28afbc91d72f0adde181565ae21f5b5f37ab712ac96a079cd4a97051f", "OpenzeppelinAccount": "0x3a58e037be64a3608dfe423eeb8a77b400b0f56f1f5e0ed4937d3c873f988e2", "replace_class": "0x451a4decb11b581b288d8a0512ab6f6ea7f1fd89caefbb415e510ec7f17efe1", - "StarknetToken": "0x314a6a9f01e5a28beb6a7e2e8907243469d98a7e364054657e7593bea5dcee7", + "StarknetToken": "0x6f21cf3ad9047d263aa8cc3a0565fcacff33a13746348017b2ad851d23f3290", "uninitialized_account_fixture": "0x60d4817e4e3881965ff4e27a55a4a7da7bf2865c7209bdb367af2f86c740b35", "uninitialized_account": "0x7b2de5e73ff7eb338d76c967dd5aa3f3004574d326b8c1402bb819d4983b8b6", "UniversalLibraryCaller": "0x244fd35db35b48882ca2e6c2966821bd54f302b131fb22ea98e5534da390482" -} +} \ No newline at end of file diff --git a/deployments/staging-core/deployments.json b/deployments/staging-core/deployments.json new file mode 100644 index 000000000..d2d696ad2 --- /dev/null +++ b/deployments/staging-core/deployments.json @@ -0,0 +1,9 @@ +{ + "EVM": "0x3681f3cfdc97e89714dcc272074d7513e78aec979252e0e59eb85857de89b22", + "Counter": "0x41872aef44417ee222b17cf58aef434e10bb29604d3f789e01cd292ed8cd3f3", + "MockPragmaOracle": "0x487893f3414f9b3a90c3ef8221fabe73ea190b206ee1c969cb1fc5da40ff04a", + "MockPragmaSummaryStats": "0x6b824a7106aa7428e880e58db35ffba50e90fc3baabaa6418daed099774c2dd", + "UniversalLibraryCaller": "0x4c6cc89ccbd932b1cf72e1e8ae45950cf84fc15ad134eda9daea9d8748a3b1b", + "BenchmarkCairoCalls": "0x2eb949afed5b91b2a3a154edfa773f3a8e4b7002f71c909bf585607c6dfbdce", + "kakarot": "0x2728e29541ceb8f741427e8efc88e8c7f73d2a9289e658800a146eec97c8bcc" +} \ No newline at end of file diff --git a/deployments/staging-core/kakarot_deployments.json b/deployments/staging-core/kakarot_deployments.json new file mode 100644 index 000000000..3d229177f --- /dev/null +++ b/deployments/staging-core/kakarot_deployments.json @@ -0,0 +1,50 @@ +{ + "WETH9": { + "address": "0xd52042e28e6f726738A48497A0728Fc5977AF3F8", + "starknet_address": "0xe9868dd0908f1d08e0aac73b671f24a7dd9187a38b214dc66812a4630fc52b" + }, + "Coinbase": { + "address": "0x61B3bF630b719D54cE0D5256b598d40da1680Eec", + "starknet_address": "0x14be2e9a4d8682aff133e39a713f2ad95ad4e08830cbc21138638a28d96875a" + }, + "Starknet Token": { + "address": "0x87Ce4c6e0BF156031e74a07C5b725800f9dF56CA", + "starknet_address": "0x236a0f0203f26abd8b33086a4c5b2a4c256bc2cb42f9b2b0116d3efc732e27b" + }, + "Starknet Voting Token": { + "address": "0x7a2deE402F31632592e3c9270D4F12E450877F86", + "starknet_address": "0x5f811868759a352ad8fa70de1e2330f8ce5154994651812d330cb558abf690" + }, + "USDC": { + "address": "0xc9c677a629AAe7A149f5F0E7546394f2630e8E9e", + "starknet_address": "0x647f8288e798f12f18bd3b5248fc77596460b6ebcb035f26b903b6567a8d64" + }, + "USDT": { + "address": "0x506De97018260b95ddF3D1b4C3d795a639b04d3F", + "starknet_address": "0x7ccff26a88476ebc02602605cafdbfd927205477f44a0e55ae53017a72d1d73" + }, + "Wrapped BTC": { + "address": "0x20a6338AE7C41A5f70Fb8C660C8cc5B3F5f631f7", + "starknet_address": "0x3399b49e88c37c9d5ce0846ffe99f0d24852a59b02c9c958d1ef9d050531a2f" + }, + "Wrapped liquid staked Ether 2.0": { + "address": "0xd88b092890db8c02E0c7a838841d88f3Cf4D8286", + "starknet_address": "0xc09188bad513771a223bc19e4dd1e06631622353425a61cb3210191c3267f7" + }, + "Multicall3": { + "address": "0xcA11bde05977b3631167028862bE2a173976CA11", + "starknet_address": "0x1790e5d1c67fdfd8cbe8fdfc4d0299934238970f0b5c9ce1cc6708988c36816" + }, + "ArachnidProxy": { + "address": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "starknet_address": "0x4bf0a6cf4450fba581b0d52d270f535be5c97dff4fe77187d881153d0da6a8a" + }, + "CreateX": { + "address": "0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed", + "starknet_address": "0x500affd7e59226cb5fc6d16d5da6da4a3c9c4bc04e137f33291c88a6fcd6638" + }, + "L2KakarotMessaging": { + "address": "0x91DB3f3f7cA7607647885F2CF2ccEA28892aC049", + "starknet_address": "0x1b34166ef30a0b85721efafe75488055b0bfebea1a0855d99086850595adbf2" + } +} \ No newline at end of file diff --git a/deployments/staging-core/l1_addresses.json b/deployments/staging-core/l1_addresses.json new file mode 100644 index 000000000..4f2096d0d --- /dev/null +++ b/deployments/staging-core/l1_addresses.json @@ -0,0 +1,5 @@ +{ + "StarknetCore": "0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057", + "StarknetVerifier": "0x07ec0D28e50322Eb0C159B9090ecF3aeA8346DFe", + "L1KakarotMessaging": "0x116E79f6127494Ee0D04B721b9F2530c6903E2C7" +} \ No newline at end of file diff --git a/deployments/staging/declarations.json b/deployments/staging/declarations.json new file mode 100644 index 000000000..4435ec835 --- /dev/null +++ b/deployments/staging/declarations.json @@ -0,0 +1,19 @@ +{ + "account_contract": "0x6d8537c7a5d4c20e616a137c11ee87601bf8d3e924091ce0f283820d3a8e9fe", + "BalanceSender": "0x292ec825bc8f7a528218ca8a3306684fbf53589afe5626b2c71790f893ac39a", + "BenchmarkCairoCalls": "0x58dc8a979af32668e05579313d1d6c672d3b668f72778780e8b2e97964159c3", + "Cairo1Helpers": "0x6c84a7ed6ee3fa25d198f058b8c8a06d9d4e4dc040efd6fa4d741f00fdc1b63", + "Cairo1HelpersFixture": "0x3810527e57a1df22d701b2c48f3d739e8fe3550876cb16435706d1448f89cbe", + "Counter": "0x27ccfaf84757dabd7885d410018bf0e264c881e4799a47f555b96bf21e5af5b", + "ERC20": "0x4254337f7006c7c084dd9b13788b20e299791a5449a42f1b1b2f79929295fe7", + "EVM": "0x43874217327a745d07d5048a6a62d56dea6874aad134c6f21cd717aa5ae10ae", + "kakarot": "0xd86d695be75d6ad8230240725f827aa6818cbd9de8af6b544ede6d5ad06a42", + "MockPragmaOracle": "0x62b05bb353abcee67e5ebc49bfb1c3582151963a15a02a56cefc0bb4497ee59", + "MockPragmaSummaryStats": "0x70cebf28afbc91d72f0adde181565ae21f5b5f37ab712ac96a079cd4a97051f", + "OpenzeppelinAccount": "0x3a58e037be64a3608dfe423eeb8a77b400b0f56f1f5e0ed4937d3c873f988e2", + "replace_class": "0x451a4decb11b581b288d8a0512ab6f6ea7f1fd89caefbb415e510ec7f17efe1", + "StarknetToken": "0x6f21cf3ad9047d263aa8cc3a0565fcacff33a13746348017b2ad851d23f3290", + "uninitialized_account_fixture": "0x60d4817e4e3881965ff4e27a55a4a7da7bf2865c7209bdb367af2f86c740b35", + "uninitialized_account": "0x7b2de5e73ff7eb338d76c967dd5aa3f3004574d326b8c1402bb819d4983b8b6", + "UniversalLibraryCaller": "0x244fd35db35b48882ca2e6c2966821bd54f302b131fb22ea98e5534da390482" +} \ No newline at end of file diff --git a/deployments/starknet-sepolia-staging/deployments.json b/deployments/staging/deployments.json similarity index 54% rename from deployments/starknet-sepolia-staging/deployments.json rename to deployments/staging/deployments.json index e3f8189ba..e59fbe5aa 100644 --- a/deployments/starknet-sepolia-staging/deployments.json +++ b/deployments/staging/deployments.json @@ -1,8 +1,9 @@ { - "EVM": "0x168990f4995fefdd9b4feb5bbfe62dc665950eafaaed4fd83cce173a534a161", + "EVM": "0x44f4754dc813f9496d5d1ac781592a85ff16b00e45ecd41dfe2702b98bc9ee2", "Counter": "0x5785f46ccba39af91693e162baa3d9db0d4aeea316e82c85c204b48b74da060", - "MockPragmaOracle": "0x40defdc02602d71d53daf87f53ba4dca0de26384f1e9834411b38700439648f", + "MockPragmaOracle": "0x67f9f7d4b1cc9cb35c0e65ae4ddcffcf07bda309a80331068f6054f7ad5bb40", "UniversalLibraryCaller": "0xcf3afbce535bd3a85d776d4646d34e8b510ce7eb7580a64616e731a4012515", "BenchmarkCairoCalls": "0x3564648a7110e73f4672733c59b5ac81eff8dbc1ab46491216452e130abc6b4", - "kakarot": "0x48fc2888aad166304e63af35a48e00e32da9831e49fe30a22148fdecdb7e66f" -} + "kakarot": "0x48fc2888aad166304e63af35a48e00e32da9831e49fe30a22148fdecdb7e66f", + "MockPragmaSummaryStats": "0x61600a212d419ea4fcf32f944eb3548cbb99a97fb51c667f6f3f3acb2d895d0" +} \ No newline at end of file diff --git a/deployments/staging/kakarot_deployments.json b/deployments/staging/kakarot_deployments.json new file mode 100644 index 000000000..4e1961a29 --- /dev/null +++ b/deployments/staging/kakarot_deployments.json @@ -0,0 +1,58 @@ +{ + "Bridge": { + "address": "0x663F3ad617193148711d28f5334eE4Ed07016602", + "starknet_address": "0x3c4fbbf15be984c1c17658f0b6ca0155c75ffc61551020d4a566165b2ce7a61" + }, + "WETH": { + "address": "0x2E983A1Ba5e8b38AAAeC4B440B9dDcFBf72E15d1", + "starknet_address": "0x130a102efefe1bee562f6d014ba32499d578895781a17271458e228fbe0b346" + }, + "WETH9": { + "address": "0xd52042e28e6f726738A48497A0728Fc5977AF3F8", + "starknet_address": "0x72ee3ae25c98b53e5f7879c7642112b82e804d4ac6c541a6e94f0670afd0d85" + }, + "Coinbase": { + "address": "0x7a2deE402F31632592e3c9270D4F12E450877F86", + "starknet_address": "0x3b44d33827c5dbdec5a1b407de088f1941da9a576e24920de6c3b41f2047d7" + }, + "Multicall3": { + "address": "0xcA11bde05977b3631167028862bE2a173976CA11", + "starknet_address": "0x4a8daeb5db2bfe2d9a37f74e6f4a2f7bfa7947bca35f4553c071d66cc242f82" + }, + "ArachnidProxy": { + "address": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "starknet_address": "0x15701d69558e5cb4a56581aead3381cff3cc604063d9882eeff228b830d2bef" + }, + "CreateX": { + "address": "0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed", + "starknet_address": "0x3cf1d8802ffc46c152fbdb8b213468ca6aad2c51d2ab43fa7cc57884b3ff2f0" + }, + "L2KakarotMessaging": { + "address": "0xc9c677a629AAe7A149f5F0E7546394f2630e8E9e", + "starknet_address": "0x4fc85a8f1dd13464031e996dec1aeb1734eac3141413577638e0529487137df" + }, + "Starknet Token": { + "address": "0x8ffd5161d2a62020f5198FBfd28c470621187034", + "starknet_address": "0x399968119bf832072fcd40964ac876cccf8f0c3cc14168910feb1a52b399785" + }, + "Starknet Voting Token": { + "address": "0x48b5435271917C8439d73f9456cB4074Bd1D07E6", + "starknet_address": "0x2a84cbf7e785f147ce409eea6a88af602793a1f0a416d4417a279a859fe1075" + }, + "USDC": { + "address": "0x46B77dC345c2ad6991EfD10f654165108206219B", + "starknet_address": "0x16721decd06a035ff89d07f0af4a343d350eac928cc8925310dc0a103eff674" + }, + "USDT": { + "address": "0x489d4482D00b09F444e01a38799C6C250F9BF55C", + "starknet_address": "0x2f0463914c51b40e9165a3eb271a9d67d67ebcab7cfd5a9594daf90ef7ce9c1" + }, + "Wrapped BTC": { + "address": "0xAB49f91Df268bF260D100E431536520B6fB791de", + "starknet_address": "0x6c5ca7d5cbe3bb07b98a221b416dce194bfb84715a9161ee02140511366410e" + }, + "Wrapped liquid staked Ether 2.0": { + "address": "0xBdaE60b4272856f87ABE843Aeb8E3fbC014419C5", + "starknet_address": "0x20cfffc3e25b98ba0dd5025667bca44f245687406226c36a0976e0eba1b514d" + } +} \ No newline at end of file diff --git a/deployments/starknet-sepolia-staging/l1_addresses.json b/deployments/staging/l1_addresses.json similarity index 100% rename from deployments/starknet-sepolia-staging/l1_addresses.json rename to deployments/staging/l1_addresses.json diff --git a/deployments/starknet-sepolia-staging/kakarot_deployments.json b/deployments/starknet-sepolia-staging/kakarot_deployments.json deleted file mode 100644 index 82ae20b27..000000000 --- a/deployments/starknet-sepolia-staging/kakarot_deployments.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "Bridge": { - "address": "0x663f3ad617193148711d28f5334ee4ed07016602", - "starknet_address": "0x3c4fbbf15be984c1c17658f0b6ca0155c75ffc61551020d4a566165b2ce7a61" - }, - "WETH": { - "address": "0x2e983a1ba5e8b38aaaec4b440b9ddcfbf72e15d1", - "starknet_address": "0x130a102efefe1bee562f6d014ba32499d578895781a17271458e228fbe0b346" - }, - "WETH9": { - "address": "0xd52042e28e6f726738a48497a0728fc5977af3f8", - "starknet_address": "0x72ee3ae25c98b53e5f7879c7642112b82e804d4ac6c541a6e94f0670afd0d85" - }, - "KakarotETH": { - "address": "0x61b3bf630b719d54ce0d5256b598d40da1680eec", - "starknet_address": "0x26b38fa9a6b88d0bcc3267585651206a6652bbd3ae6e0dc45cdbc69f6200ce2" - }, - "KakarotSTRK": { - "address": "0x87ce4c6e0bf156031e74a07c5b725800f9df56ca", - "starknet_address": "0x6dd744038e504ee3252255509519a6e419534221a47b00f61966a3d80ec3b5b" - }, - "Coinbase": { - "address": "0x7a2dee402f31632592e3c9270d4f12e450877f86", - "starknet_address": "0x3b44d33827c5dbdec5a1b407de088f1941da9a576e24920de6c3b41f2047d7" - }, - "Multicall3": { - "address": "0xca11bde05977b3631167028862be2a173976ca11", - "starknet_address": "0x4a8daeb5db2bfe2d9a37f74e6f4a2f7bfa7947bca35f4553c071d66cc242f82" - }, - "ArachnidProxy": { - "address": "0x4e59b44847b379578588920ca78fbf26c0b4956c", - "starknet_address": "0x15701d69558e5cb4a56581aead3381cff3cc604063d9882eeff228b830d2bef" - }, - "CreateX": { - "address": "0xba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed", - "starknet_address": "0x3cf1d8802ffc46c152fbdb8b213468ca6aad2c51d2ab43fa7cc57884b3ff2f0" - }, - "L2KakarotMessaging": { - "address": "0xc9c677a629aae7a149f5f0e7546394f2630e8e9e", - "starknet_address": "0x4fc85a8f1dd13464031e996dec1aeb1734eac3141413577638e0529487137df" - } -} \ No newline at end of file diff --git a/kakarot_scripts/artifacts.py b/kakarot_scripts/artifacts.py index ddf70924e..bb3dc9967 100644 --- a/kakarot_scripts/artifacts.py +++ b/kakarot_scripts/artifacts.py @@ -12,7 +12,7 @@ import requests from dotenv import load_dotenv -load_dotenv() +load_dotenv(override=True) logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) diff --git a/kakarot_scripts/constants.py b/kakarot_scripts/constants.py index ca8fb5649..c23d55268 100644 --- a/kakarot_scripts/constants.py +++ b/kakarot_scripts/constants.py @@ -3,26 +3,25 @@ import os from enum import Enum, IntEnum from pathlib import Path -from typing import Dict, List import requests from dotenv import load_dotenv from eth_keys import keys -from starknet_py.net.account.account import Account from starknet_py.net.full_node_client import FullNodeClient from starknet_py.net.models.chains import StarknetChainId -from starknet_py.net.signer.stark_curve_signer import KeyPair from web3 import Web3 -logging.basicConfig() +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) -load_dotenv() +load_dotenv(override=True) BLOCK_GAS_LIMIT = 7_000_000 DEFAULT_GAS_PRICE = 1 BEACON_ROOT_ADDRESS = "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" +# see https://gist.github.com/rekmarks/a47bd5f2525936c4b8eee31a16345553 +MAX_SAFE_CHAIN_ID = 4503599627370476 # See https://github.com/kkrt-labs/kakarot/issues/1530 MAX_LEDGER_CHAIN_ID = 2**32 - 1 @@ -42,7 +41,7 @@ class NetworkType(Enum): "rpc_url": f"https://rpc.nethermind.io/mainnet-juno/?apikey={os.getenv('NETHERMIND_API_KEY')}", "l1_rpc_url": f"https://mainnet.infura.io/v3/{os.getenv('INFURA_KEY')}", "type": NetworkType.PROD, - "chain_id": StarknetChainId.MAINNET, + "chain_id": StarknetChainId.MAINNET % MAX_LEDGER_CHAIN_ID, "check_interval": 1, "max_wait": 60, "class_hash": 0x061DAC032F228ABEF9C6626F995015233097AE253A7F72D68552DB02F2971B8F, @@ -56,7 +55,7 @@ class NetworkType(Enum): "rpc_url": f"https://rpc.nethermind.io/sepolia-juno/?apikey={os.getenv('NETHERMIND_API_KEY')}", "l1_rpc_url": f"https://sepolia.infura.io/v3/{os.getenv('INFURA_KEY')}", "type": NetworkType.STAGING, - "chain_id": StarknetChainId.SEPOLIA, + "chain_id": StarknetChainId.SEPOLIA % MAX_SAFE_CHAIN_ID, "check_interval": 1, "max_wait": 30, "class_hash": 0x061DAC032F228ABEF9C6626F995015233097AE253A7F72D68552DB02F2971B8F, @@ -70,7 +69,21 @@ class NetworkType(Enum): "rpc_url": f"https://rpc.nethermind.io/sepolia-juno/?apikey={os.getenv('NETHERMIND_API_KEY')}", "l1_rpc_url": f"https://sepolia.infura.io/v3/{os.getenv('INFURA_KEY')}", "type": NetworkType.STAGING, - "chain_id": StarknetChainId.SEPOLIA, + "chain_id": StarknetChainId.SEPOLIA % MAX_SAFE_CHAIN_ID, + "check_interval": 1, + "max_wait": 30, + "class_hash": 0x061DAC032F228ABEF9C6626F995015233097AE253A7F72D68552DB02F2971B8F, + "voyager_api_url": "https://sepolia-api.voyager.online/beta", + "argent_multisig_api": "https://cloud.argent-api.com/v1/multisig/starknet/sepolia", + "token_addresses_file": TOKEN_ADDRESSES_DIR / "sepolia.json", + }, + "staging-core": { + "name": "staging-core", + "explorer_url": "https://sepolia.starkscan.co/", + "rpc_url": f"https://rpc.nethermind.io/sepolia-juno/?apikey={os.getenv('NETHERMIND_API_KEY')}", + "l1_rpc_url": f"https://sepolia.infura.io/v3/{os.getenv('INFURA_KEY')}", + "type": NetworkType.STAGING, + "chain_id": StarknetChainId.SEPOLIA % MAX_SAFE_CHAIN_ID, "check_interval": 1, "max_wait": 30, "class_hash": 0x061DAC032F228ABEF9C6626F995015233097AE253A7F72D68552DB02F2971B8F, @@ -93,47 +106,11 @@ class NetworkType(Enum): "rpc_url": os.getenv("KATANA_RPC_URL", "http://127.0.0.1:5050"), "l1_rpc_url": "http://127.0.0.1:8545", "type": NetworkType.DEV, + "chain_id": int.from_bytes(b"KKRT", "big") % MAX_LEDGER_CHAIN_ID, "check_interval": 0.01, "max_wait": 3, + "class_hash": 0x05400E90F7E0AE78BD02C77CD75527280470E2FE19C54970DD79DC37A9D3645C, "token_addresses_file": TOKEN_ADDRESSES_DIR / "sepolia.json", - "relayers": [ - { - "address": 0xE29882A1FCBA1E7E10CAD46212257FEA5C752A4F9B1B1EC683C503A2CF5C8A, - "private_key": 0x14D6672DCB4B77CA36A887E9A11CD9D637D5012468175829E9C6E770C61642, - }, - { - "address": 0x29873C310FBEFDE666DC32A1554FEA6BB45EECC84F680F8A2B0A8FBB8CB89AF, - "private_key": 0xC5B2FCAB997346F3EA1C00B002ECF6F382C5F9C9659A3894EB783C5320F912, - }, - { - "address": 0x2D71E9C974539BB3FFB4B115E66A23D0F62A641EA66C4016E903454C8753BBC, - "private_key": 0x33003003001800009900180300D206308B0070DB00121318D17B5E6262150B, - }, - { - "address": 0x3EBB4767AAE1262F8EB28D9368DB5388CFE367F50552A8244123506F0B0BCCA, - "private_key": 0x3E3979C1ED728490308054FE357A9F49CF67F80F9721F44CC57235129E090F4, - }, - { - "address": 0x541DA8F7F3AB8247329D22B3987D1FFB181BC8DC7F9611A6ECCEC3B0749A585, - "private_key": 0x736ADBBCDAC7CC600F89051DB1ABBC16B9996B46F6B58A9752A11C1028A8EC8, - }, - { - "address": 0x56C155B624FDF6BFC94F7B37CF1DBEBB5E186EF2E4AB2762367CD07C8F892A1, - "private_key": 0x6BF3604BCB41FED6C42BCCA5436EEB65083A982FF65DB0DC123F65358008B51, - }, - { - "address": 0x6162896D1D7AB204C7CCAC6DD5F8E9E7C25ECD5AE4FCB4AD32E57786BB46E03, - "private_key": 0x1800000000300000180000000000030000000000003006001800006600, - }, - { - "address": 0x66EFB28AC62686966AE85095FF3A772E014E7FBF56D4C5F6FAC5606D4DDE23A, - "private_key": 0x283D1E73776CD4AC1AC5F0B879F561BDED25ECEB2CC589C674AF0CEC41DF441, - }, - { - "address": 0x6B86E40118F29EBE393A75469B4D926C7A44C2E2681B6D319520B7C1156D114, - "private_key": 0x1C9053C053EDF324AEC366A34C6901B1095B07AF69495BFFEC7D7FE21EFFB1B, - }, - ], }, "madara": { "name": "madara", @@ -186,8 +163,7 @@ class NetworkType(Enum): if WEB3.is_connected(): chain_id = WEB3.eth.chain_id else: - # Before making any changes to chain_id see https://github.com/kkrt-labs/kakarot/issues/1530 - chain_id = starknet_chain_id % MAX_LEDGER_CHAIN_ID + chain_id = NETWORK["chain_id"] except ( requests.exceptions.ConnectionError, requests.exceptions.MissingSchema, @@ -196,9 +172,7 @@ class NetworkType(Enum): logger.info( f"⚠️ Could not get chain Id from {NETWORK['rpc_url']}: {e}, defaulting to KKRT" ) - starknet_chain_id = int.from_bytes(b"KKRT", "big") - # Before making any changes to chain_id see https://github.com/kkrt-labs/kakarot/issues/1530 - chain_id = starknet_chain_id % MAX_LEDGER_CHAIN_ID + chain_id = starknet_chain_id = int.from_bytes(b"KKRT", "big") class ChainId(IntEnum): @@ -206,7 +180,6 @@ class ChainId(IntEnum): starknet_chain_id = starknet_chain_id -# Before making any changes to chain_id see https://github.com/kkrt-labs/kakarot/issues/1530 NETWORK["chain_id"] = ChainId.chain_id ETH_TOKEN_ADDRESS = 0x49D36570D4E46F48E99674BD3FCC84644DDD6B96F7C741B1562B82F9E004DC7 @@ -301,48 +274,8 @@ class ChainId(IntEnum): NETWORK["private_key"] = os.getenv("PRIVATE_KEY") -class RelayerPool: - def __init__(self, relayers: List[Dict[str, int]]): - self.relayer_accounts = [ - Account( - address=relayer["address"], - client=RPC_CLIENT, - chain=ChainId.starknet_chain_id, - key_pair=KeyPair.from_private_key(relayer["private_key"]), - ) - for relayer in relayers - ] - self.index = 0 - - def __next__(self) -> Account: - relayer = self.relayer_accounts[self.index] - self.index = (self.index + 1) % len(self.relayer_accounts) - return relayer - - -if ( - os.getenv(f"{prefix}_RELAYER_ACCOUNT_ADDRESS") is not None - and os.getenv(f"{prefix}_RELAYER_PRIVATE_KEY") is not None -): - default_relayer = { - "address": int(os.environ[f"{prefix}_RELAYER_ACCOUNT_ADDRESS"], 16), - "private_key": int(os.environ[f"{prefix}_RELAYER_PRIVATE_KEY"], 16), - } -elif NETWORK["account_address"] is not None and NETWORK["private_key"] is not None: - default_relayer = { - "address": int(NETWORK["account_address"], 16), - "private_key": int(NETWORK["private_key"], 16), - } -else: - default_relayer = None - -if default_relayer is None and NETWORK.get("relayers") is None: - raise ValueError("No account nor relayers defined for this network") - -NETWORK["relayers"] = RelayerPool(NETWORK.get("relayers", [default_relayer])) - kakarot_chain_ascii = bytes.fromhex(f"{ChainId.chain_id.value:014x}").lstrip(b"\x00") logger.info( f"ℹ️ Connected to Starknet chain id {bytes.fromhex(f'{ChainId.starknet_chain_id.value:x}')} " - f"and Kakarot chain id {kakarot_chain_ascii}" + f"and Kakarot chain id {kakarot_chain_ascii}\n\nNetwork: {NETWORK['name']}\n" ) diff --git a/kakarot_scripts/deployment/dualvm_token_deployments.py b/kakarot_scripts/deployment/dualvm_token_deployments.py index 170d1f3d8..c00842d95 100644 --- a/kakarot_scripts/deployment/dualvm_token_deployments.py +++ b/kakarot_scripts/deployment/dualvm_token_deployments.py @@ -29,7 +29,7 @@ # %% async def deploy_dualvm_tokens() -> None: - # %% Deploy DualVM Tokens + # %% Setup # The lazy execution must be done before we check the deployments succeeded, as the l2 contracts # need to be deployed first @@ -59,12 +59,12 @@ async def deploy_dualvm_tokens() -> None: (await call_contract("ERC20", "symbol", address=kakarot_native_token)).symbol ) - # Filter tokens based on deployment criteria + # %% Deploy DualVM Tokens for token in tokens: # Skip if entry is not a token if "l2_token_address" not in token: - logger.info("Skipping %s: missing l2_token_address", token["name"]) + logger.info("ℹ️ Skipping %s: missing l2_token_address", token["name"]) continue l2_token_address = int(token["l2_token_address"], 16) @@ -74,7 +74,7 @@ async def deploy_dualvm_tokens() -> None: token["name"] == kakarot_native_token_name and token["symbol"] == kakarot_native_token_symbol ): - logger.info("Skipping %s: native token", token["name"]) + logger.info("ℹ️ Skipping %s: native token", token["name"]) continue # Check if DualVM token is a deployed contract on Starknet @@ -89,13 +89,16 @@ async def deploy_dualvm_tokens() -> None: evm_deployments[token["name"]]["address"], ) assert await token_contract.kakarot() == kakarot_address - logger.info("Skipping %s: already deployed on Starknet", token["name"]) + logger.info( + "✅ Skipping %s: already deployed on Starknet", token["name"] + ) continue except Exception: pass # DualVM token is not deployed, deploy one # Check if the L2 token exists, if not deploy one + new_l2_token = False try: await RPC_CLIENT.get_class_hash_at(l2_token_address) except Exception as e: @@ -103,7 +106,6 @@ async def deploy_dualvm_tokens() -> None: raise ValueError( f"Starknet token for {token['name']} doesn't exist on L2" ) from e - logger.info(f"⏳ {token['name']} doesn't exist on Starknet, deploying...") owner = await get_starknet_account() l2_token_address = await deploy_starknet( @@ -114,8 +116,9 @@ async def deploy_dualvm_tokens() -> None: int(2**256 - 1), owner.address, ) + new_l2_token = True - if token["name"] not in evm_deployments: + if token["name"] not in evm_deployments or new_l2_token: contract = await deploy_kakarot( "CairoPrecompiles", "DualVmToken", kakarot_address, l2_token_address ) @@ -134,12 +137,13 @@ async def deploy_dualvm_tokens() -> None: "CairoPrecompiles", "DualVmToken", evm_deployments[token["name"]]["address"] ) assert await token_contract.starknetToken() == l2_token_address - assert await token_contract.name() == token["name"] - assert await token_contract.symbol() == token["symbol"] + assert (await token_contract.name()).lstrip("\x00") == token["name"] + assert (await token_contract.symbol()).lstrip("\x00") == token["symbol"] assert await token_contract.decimals() == token["decimals"] + # %% Save deployments dump_evm_deployments(evm_deployments) - logger.info("Finished processing all DualVM tokens") + logger.info("✅ Finished processing all DualVM tokens") register_lazy_account(account.address) diff --git a/kakarot_scripts/deployment/evm_deployments.py b/kakarot_scripts/deployment/evm_deployments.py index 222f2d8a2..fef72eafa 100644 --- a/kakarot_scripts/deployment/evm_deployments.py +++ b/kakarot_scripts/deployment/evm_deployments.py @@ -25,11 +25,6 @@ async def deploy_evm_contracts(): # %% Deployments logger.info(f"ℹ️ Using account {EVM_ADDRESS} as deployer") - - await deploy_and_fund_evm_address( - EVM_ADDRESS, amount=100 if NETWORK["type"] is NetworkType.DEV else 0.01 - ) - evm_deployments = get_evm_deployments() # %% Pure EVM Tokens @@ -67,7 +62,6 @@ async def deploy_evm_contracts(): "address": int(contract.address, 16), "starknet_address": contract.starknet_address, } - logger.info(f"✅ Coinbase deployed at {contract.address}") await invoke("kakarot", "set_coinbase", int(contract.address, 16)) # %% Tear down @@ -86,6 +80,9 @@ async def main(): logger.warn("⚠️ No EVM address provided, skipping EVM deployments") return + await deploy_and_fund_evm_address( + EVM_ADDRESS, amount=100 if NETWORK["type"] is NetworkType.DEV else 0.01 + ) account = await get_starknet_account() register_lazy_account(account.address) await deploy_evm_contracts() diff --git a/kakarot_scripts/deployment/main.py b/kakarot_scripts/deployment/main.py index 09c1ad601..ffeae858e 100644 --- a/kakarot_scripts/deployment/main.py +++ b/kakarot_scripts/deployment/main.py @@ -3,8 +3,7 @@ from uvloop import run -from kakarot_scripts.constants import EVM_ADDRESS, L1_RPC_PROVIDER, NETWORK -from kakarot_scripts.deployment.declarations import declare_contracts +from kakarot_scripts.constants import EVM_ADDRESS, L1_RPC_PROVIDER, NETWORK, NetworkType from kakarot_scripts.deployment.dualvm_token_deployments import deploy_dualvm_tokens from kakarot_scripts.deployment.evm_deployments import deploy_evm_contracts from kakarot_scripts.deployment.kakarot_deployment import deploy_or_upgrade_kakarot @@ -18,7 +17,11 @@ whitelist_pre_eip155_txs, ) from kakarot_scripts.deployment.starknet_deployments import deploy_starknet_contracts -from kakarot_scripts.utils.kakarot import eth_balance_of, get_contract +from kakarot_scripts.utils.kakarot import ( + deploy_and_fund_evm_address, + eth_balance_of, + get_contract, +) from kakarot_scripts.utils.starknet import ( call, execute_calls, @@ -28,7 +31,7 @@ remove_lazy_account, ) -logging.basicConfig() +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -42,9 +45,6 @@ async def main(): logger.info(f"ℹ️ Using account 0x{account.address:064x} as deployer") balance_before = await get_balance(account.address) - # %% Declarations - await declare_contracts() - # %% Starknet Deployments await deploy_starknet_contracts(account) await deploy_or_upgrade_kakarot(account) @@ -52,8 +52,11 @@ async def main(): # %% EVM Deployments await deploy_pre_eip155_senders() - await deploy_evm_contracts() + await deploy_and_fund_evm_address( + EVM_ADDRESS, amount=100 if NETWORK["type"] is NetworkType.DEV else 0.01 + ) await execute_calls() + await deploy_evm_contracts() # DualVM Tokens deployment have their own invoke batching strategy await deploy_dualvm_tokens() @@ -80,7 +83,7 @@ async def main(): coinbase_balance = await eth_balance_of(coinbase_address) if coinbase_balance / 1e18 > 0.001: logger.info( - f"ℹ️ Withdrawing {coinbase_balance / 1e18} ETH from Coinbase to Starknet deployer" + f"ℹ️ Withdrawing {coinbase_balance / 1e18} ETH from Coinbase to Starknet deployer" ) await coinbase.withdraw(account.address) @@ -91,15 +94,6 @@ async def main(): logger.info( f"💰 Coinbase balance: {await eth_balance_of(coinbase_address) / 1e18} ETH" ) - logger.info( - "💰 Relayers balance:\n" - + "\n".join( - [ - f" {hex(account.address)}: {await get_balance(account.address) / 1e18} ETH" - for account in NETWORK["relayers"].relayer_accounts - ] - ) - ) l2_balance = await eth_balance_of(EVM_ADDRESS) / 1e18 l1_balance = L1_RPC_PROVIDER.eth.get_balance(EVM_ADDRESS) / 1e18 logger.info( diff --git a/kakarot_scripts/ef_tests/debug.py b/kakarot_scripts/ef_tests/debug.py index 1c71916f3..ac9a9a1ab 100644 --- a/kakarot_scripts/ef_tests/debug.py +++ b/kakarot_scripts/ef_tests/debug.py @@ -19,7 +19,7 @@ logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) -load_dotenv() +load_dotenv(override=True) TESTS_PATH = Path("tests/ef_tests/test_data/BlockchainTests/GeneralStateTests") TEST_NAME = os.getenv("TEST_NAME") diff --git a/kakarot_scripts/ef_tests/resources.py b/kakarot_scripts/ef_tests/resources.py index 8b44e54a4..c17e301b6 100644 --- a/kakarot_scripts/ef_tests/resources.py +++ b/kakarot_scripts/ef_tests/resources.py @@ -12,7 +12,7 @@ import requests from dotenv import load_dotenv -load_dotenv() +load_dotenv(override=True) logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) diff --git a/kakarot_scripts/utils/kakarot.py b/kakarot_scripts/utils/kakarot.py index e2d8f2177..133d5a05f 100644 --- a/kakarot_scripts/utils/kakarot.py +++ b/kakarot_scripts/utils/kakarot.py @@ -1,6 +1,8 @@ +import asyncio import functools import json import logging +import math import re import time from collections import defaultdict @@ -43,7 +45,7 @@ ChainId, ) from kakarot_scripts.data.pre_eip155_txs import PRE_EIP155_TX -from kakarot_scripts.utils.starknet import _max_fee +from kakarot_scripts.utils.starknet import RelayerPool, _max_fee from kakarot_scripts.utils.starknet import call from kakarot_scripts.utils.starknet import call as _call_starknet from kakarot_scripts.utils.starknet import fund_address as _fund_starknet_address @@ -55,10 +57,74 @@ from tests.utils.constants import TRANSACTION_GAS_LIMIT from tests.utils.helpers import pack_calldata, rlp_encode_signed_data -logging.basicConfig() +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) +_nonces = {} + + +async def get_nonce(account): + global _nonces + if account.address not in _nonces: + if WEB3.is_connected(): + _nonces[account.address] = WEB3.eth.get_transaction_count( + account.signer.public_key.to_checksum_address() + ) + else: + _nonces[account.address] = ( + await ( + _get_starknet_contract("account_contract", address=account.address) + .functions["get_nonce"] + .call(block_number="pending") + ) + ).nonce + + if WEB3.is_connected(): + network_nonce = WEB3.eth.get_transaction_count( + account.signer.public_key.to_checksum_address() + ) + else: + network_nonce = ( + await ( + _get_starknet_contract("account_contract", address=account.address) + .functions["get_nonce"] + .call(block_number="pending") + ) + ).nonce + + retries = 10 + while network_nonce != _nonces[account.address] and retries > 0: + logger.info( + f"⏳ Waiting for network nonce {network_nonce} to be {_nonces[account.address]}" + ) + await asyncio.sleep(0.1) + + if WEB3.is_connected(): + network_nonce = WEB3.eth.get_transaction_count( + account.signer.public_key.to_checksum_address() + ) + else: + network_nonce = ( + await ( + _get_starknet_contract("account_contract", address=account.address) + .functions["get_nonce"] + .call(block_number="pending") + ) + ).nonce + + retries -= 1 + if retries == 0: + logger.warning( + f"⏳ Network nonce {network_nonce} did not match expected nonce {_nonces[account.address]}" + ) + # After 1 second, the nonce should have been updated by the network in any case + _nonces[account.address] = network_nonce + + nonce = _nonces[account.address] + _nonces[account.address] += 1 + return nonce + class EvmTransactionError(Exception): pass @@ -188,9 +254,6 @@ async def get_contract( except NoABIFunctionsFound: pass contract.events.parse_events = MethodType(_parse_events, contract.events) - contract.w3.eth.send_transaction = MethodType( - _wrap_kakarot(fun=None, caller_eoa=caller_eoa), contract - ) return contract @@ -451,7 +514,9 @@ async def _wrapper(self, *args, **kwargs): payload["data"] = list(payload["data"]) payload["origin"] = int(payload["from"], 16) del payload["from"] - result = await kakarot_contract.functions["eth_call"].call(**payload) + result = await kakarot_contract.functions["eth_call"].call( + **payload, block_number="pending" + ) if result.success == 0: raise EvmTransactionError(bytes(result.return_data)) result = result.return_data @@ -460,7 +525,7 @@ async def _wrapper(self, *args, **kwargs): normalized = map_abi_data(BASE_RETURN_NORMALIZERS, types, decoded) return normalized[0] if len(normalized) == 1 else normalized - logger.info(f"⏳ Executing {fun} at address {self.address}") + logger.info(f"⏳ Executing {self.address}.{fun or 'fallback'}") receipt, response, success, gas_used = await eth_send_transaction( to=self.address, value=value, @@ -471,9 +536,9 @@ async def _wrapper(self, *args, **kwargs): gas_price=gas_price, ) if success == 0: - logger.error(f"❌ {self.address}.{fun} failed") + logger.error(f"❌ {self.address}.{fun or 'fallback'} failed") raise EvmTransactionError(bytes(response)) - logger.info(f"✅ {self.address}.{fun}") + logger.info(f"✅ {self.address}.{fun or 'fallback'}") return { "receipt": receipt, "response": response, @@ -494,11 +559,10 @@ async def _contract_exists(address: int) -> bool: async def get_eoa(private_key=None, amount=0) -> Account: private_key = private_key or keys.PrivateKey(bytes.fromhex(EVM_PRIVATE_KEY[2:])) - starknet_address = await deploy_and_fund_evm_address( - private_key.public_key.to_checksum_address(), amount - ) + evm_address = private_key.public_key.to_checksum_address() + starknet_address = await deploy_and_fund_evm_address(evm_address, amount) - return Account( + account = Account( address=starknet_address, client=RPC_CLIENT, chain=ChainId.starknet_chain_id, @@ -507,6 +571,8 @@ async def get_eoa(private_key=None, amount=0) -> Account: # and the access to the private key key_pair=KeyPair(int(private_key), private_key.public_key), ) + account.evm_address = evm_address + return account async def whitelist_pre_eip155_tx(name: str): @@ -609,6 +675,11 @@ async def eth_balance_of(address: Union[int, str]): return await get_balance(starknet_address) +@alru_cache +async def eth_chain_id(): + return (await call("kakarot", "eth_chain_id")).chain_id + + async def eth_send_transaction( to: Union[int, str], data: Union[str, bytes], @@ -625,17 +696,11 @@ async def eth_send_transaction( evm_account.signer.public_key.to_checksum_address() ) else: - nonce = ( - await ( - _get_starknet_contract("account_contract", address=evm_account.address) - .functions["get_nonce"] - .call() - ) - ).nonce + nonce = await get_nonce(evm_account) payload = { "type": 0x1, - "chainId": NETWORK["chain_id"], + "chainId": await eth_chain_id(), "nonce": nonce, "gas": gas, "gasPrice": gas_price, @@ -678,7 +743,7 @@ async def send_starknet_transaction( packed_encoded_unsigned_tx: List[int], max_fee: Optional[int] = None, ): - relayer = next(NETWORK["relayers"]) + relayer = await RelayerPool.get(evm_account.address) current_timestamp = (await RPC_CLIENT.get_block("latest")).timestamp outside_execution = { "caller": int.from_bytes(b"ANY_CALLER", "big"), @@ -709,13 +774,19 @@ async def send_starknet_transaction( account=relayer, ) - try: - receipt = await RPC_CLIENT.get_transaction_receipt(tx_hash) - except Exception: - # Sometime the RPC_CLIENT is too fast and the first pool raises with - # starknet_py.net.client_errors.ClientError: Client failed with code 29. Message: Transaction hash not found - time.sleep(2) - receipt = await RPC_CLIENT.get_transaction_receipt(tx_hash) + check_interval = math.ceil(NETWORK["check_interval"]) + attempts = NETWORK["max_wait"] // check_interval + for _ in range(attempts): + try: + receipt = await RPC_CLIENT.get_transaction_receipt(tx_hash) + break + except Exception: + # Sometime the RPC_CLIENT is too fast and the first pool raises with + # starknet_py.net.client_errors.ClientError: Client failed with code 29. Message: Transaction hash not found + time.sleep(check_interval) + else: + raise ValueError(f"❌ Transaction not found: 0x{tx_hash:064x}") + transaction_events = [ event for event in receipt.events @@ -723,6 +794,7 @@ async def send_starknet_transaction( and event.keys[0] == starknet_keccak(b"transaction_executed") ] if receipt.execution_status.name == "REVERTED": + _nonces[evm_account.address] -= 1 raise StarknetTransactionError(f"Starknet tx reverted: {receipt.revert_reason}") if len(transaction_events) != 1: raise ValueError("Cannot locate the single event giving the actual tx status") @@ -765,7 +837,7 @@ async def deploy_and_fund_evm_address(evm_address: str, amount: float): "kakarot", "deploy_externally_owned_account", int(evm_address, 16), - account=next(NETWORK["relayers"]), + account=await RelayerPool.get(int(evm_address, 16)), ) return starknet_address diff --git a/kakarot_scripts/utils/l1.py b/kakarot_scripts/utils/l1.py index 100d377be..8727b32cb 100644 --- a/kakarot_scripts/utils/l1.py +++ b/kakarot_scripts/utils/l1.py @@ -23,7 +23,7 @@ get_solidity_artifacts, ) -logging.basicConfig() +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -121,8 +121,8 @@ def send_l1_transaction( evm_account = caller_eoa or EvmAccount.from_key(EVM_PRIVATE_KEY) evm_tx = L1_RPC_PROVIDER.eth.account.sign_transaction(transaction, evm_account.key) tx_hash = L1_RPC_PROVIDER.eth.send_raw_transaction(evm_tx.raw_transaction) - logger.info(f"ℹ⏳ Transaction sent: 0x{tx_hash.hex()}") - receipt = L1_RPC_PROVIDER.eth.wait_for_transaction_receipt(tx_hash) + logger.info(f"⏳ Waiting for transaction {tx_hash}") + receipt = L1_RPC_PROVIDER.eth.wait_for_transaction_receipt(tx_hash, timeout=5 * 60) response = [] if not receipt.status: trace = L1_RPC_PROVIDER.manager.request_blocking( @@ -181,7 +181,7 @@ def _wrapper(self, *args, **kwargs): normalized = map_abi_data(BASE_RETURN_NORMALIZERS, types, decoded) return normalized[0] if len(normalized) == 1 else normalized - logger.info(f"⏳ Executing {fun} at address {self.address}") + logger.info(f"⏳ Executing {self.address}.{fun}") receipt, response = send_l1_transaction(transaction, caller_eoa) if receipt["status"] == 0: logger.error(f"❌ {self.address}.{fun} failed") diff --git a/kakarot_scripts/utils/starknet.py b/kakarot_scripts/utils/starknet.py index 8be66dbb0..ac99c8392 100644 --- a/kakarot_scripts/utils/starknet.py +++ b/kakarot_scripts/utils/starknet.py @@ -5,6 +5,7 @@ import random import re import subprocess +import time from collections import defaultdict, namedtuple from copy import deepcopy from datetime import datetime @@ -42,6 +43,7 @@ ) from starknet_py.net.signer.stark_curve_signer import KeyPair from starknet_py.net.udc_deployer.deployer import Deployer +from starknet_py.transaction_errors import TransactionRejectedError from starkware.starknet.public.abi import get_selector_from_name from kakarot_scripts.constants import ( @@ -54,23 +56,23 @@ ETH_TOKEN_ADDRESS, NETWORK, RPC_CLIENT, - ChainId, NetworkType, ) -logging.basicConfig() +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # Due to some fee estimation issues, we skip it in all the calls and set instead # this hardcoded value. This has no impact apart from enforcing the signing wallet # to have at least 0.1 ETH -_max_fee = int(0.05e18) +_max_fee = int(0.005e18) if NETWORK["type"] == NetworkType.PROD else int(0.05e18) # Global variables for lazy execution and multisig accounts _logs = defaultdict(list) _lazy_execute = defaultdict(bool) _multisig_account = defaultdict(bool) +_nonces = {} # Dict to store selector to name mapping because argent api requires the name but calls have selector _selector_to_name = {get_selector_from_name("deployContract"): "deployContract"} @@ -149,7 +151,8 @@ async def get_starknet_account( ) if len(public_keys) > 1: register_multisig_account(address) - logger.info("ℹ️ Account is a multisig") + logger.info("ℹ️ Account is a multisig") + else: logger.warning( f"⚠️ Unable to verify public key for account at address 0x{address:x}" @@ -158,7 +161,7 @@ async def get_starknet_account( return Account( address=address, client=RPC_CLIENT, - chain=ChainId.starknet_chain_id, + chain=NETWORK["chain_id"].starknet_chain_id, key_pair=key_pair, ) @@ -168,7 +171,7 @@ async def get_eth_contract(provider=None) -> Contract: return Contract( ETH_TOKEN_ADDRESS, get_abi("ERC20"), - provider or next(NETWORK["relayers"]), + provider or await get_starknet_account(), cairo_version=0, ) @@ -201,20 +204,30 @@ async def fund_address( else: logger.info(f"{amount / 1e18} ETH minted to {hex(address)}") else: - account = funding_account or next(NETWORK["relayers"]) + account = funding_account or await get_starknet_account() eth_contract = token_contract or await get_eth_contract(account) balance = await get_balance(account.address, eth_contract) - if balance < amount: + to_balance = await get_balance(address, eth_contract) + required_amount = amount - to_balance + if balance < required_amount: raise ValueError( f"Cannot send {amount / 1e18} ETH from account 0x{account.address:064x} with current balance {balance / 1e18} ETH" ) - prepared = eth_contract.functions["transfer"].prepare_invoke_v1(address, amount) - tx = await prepared.invoke(max_fee=_max_fee) + if required_amount <= 0: + return - status = await wait_for_transaction(tx.hash) logger.info( - f"{status} {amount / 1e18} ETH sent from {hex(account.address)} to {hex(address)}" + f"ℹ️ Funding account {hex(address)} with {required_amount / 1e18} ETH" ) + await invoke( + "ERC20", + "transfer", + address, + required_amount, + account=account, + address=eth_contract.address, + ) + balance = (await eth_contract.functions["balanceOf"].call(address)).balance # type: ignore logger.info(f"💰 Balance of {hex(address)}: {balance / 1e18}") @@ -369,8 +382,10 @@ def compile_contract(contract): ) -async def deploy_starknet_account(class_hash=None, private_key=None, amount=1): - salt = random.randint(0, 2**251) +async def deploy_starknet_account( + class_hash=None, private_key=None, amount=1, salt=None +): + salt = salt or random.randint(0, 2**251) private_key = private_key or NETWORK["private_key"] if private_key is None: raise ValueError( @@ -387,18 +402,43 @@ async def deploy_starknet_account(class_hash=None, private_key=None, amount=1): constructor_calldata=constructor_calldata, deployer_address=0, ) - logger.info(f"ℹ️ Funding account {hex(address)} with {amount} ETH") - await fund_address(address, amount=amount) - logger.info("ℹ️ Deploying account") - res = await Account.deploy_account_v1( - address=address, - class_hash=class_hash, - salt=salt, - key_pair=key_pair, - client=RPC_CLIENT, - constructor_calldata=constructor_calldata, - max_fee=_max_fee, - ) + current_balance = await get_balance(address) + required_amount = amount - current_balance + if required_amount > 0: + await fund_address(address, amount=required_amount) + + try: + await RPC_CLIENT.get_class_hash_at(address) + logger.info(f"✅ Account at 0x{address:064x}") + return { + "address": address, + } + except Exception: + pass + + logger.info(f"ℹ️ Deploying account at 0x{address:064x} with salt {hex(salt)}") + try: + res = await Account.deploy_account_v1( + address=address, + class_hash=class_hash, + salt=salt, + key_pair=key_pair, + client=RPC_CLIENT, + constructor_calldata=constructor_calldata, + max_fee=_max_fee, + ) + except Exception as e: + logger.info(f"❌ Error deploying account: {e}, waiting 5s before retrying") + time.sleep(5) + res = await Account.deploy_account_v1( + address=address, + class_hash=class_hash, + salt=salt, + key_pair=key_pair, + client=RPC_CLIENT, + constructor_calldata=constructor_calldata, + max_fee=_max_fee, + ) status = await wait_for_transaction(res.hash) logger.info(f"{status} Account deployed at: 0x{res.account.address:064x}") @@ -434,7 +474,10 @@ async def declare(contract_name): except Exception: pass - account = next(NETWORK["relayers"]) + account = await get_starknet_account() + if _multisig_account[account.address]: + account = await RelayerPool.get(account.address) + nonce = await get_nonce(account) if artifact.sierra is not None: casm_compiled_contract = artifact.casm.read_text() @@ -445,6 +488,7 @@ async def declare(contract_name): compiled_contract=sierra_compiled_contract, compiled_class_hash=class_hash, max_fee=_max_fee, + nonce=nonce, ) resp = await account.client.declare(transaction=declare_v2_transaction) @@ -461,7 +505,7 @@ async def declare(contract_name): calldata=[deployed_class_hash], max_fee=_max_fee, chain_id=account.signer.chain_id.value, - additional_data=[await account.get_nonce()], + additional_data=[nonce], ) signature = message_signature( msg_hash=tx_hash, priv_key=account.signer.private_key @@ -471,7 +515,7 @@ async def declare(contract_name): sender_address=account.address, max_fee=_max_fee, signature=signature, - nonce=await account.get_nonce(), + nonce=nonce, version=1, ) params = _create_broadcasted_txn(transaction=transaction) @@ -486,7 +530,7 @@ async def declare(contract_name): ) deployed_class_hash = resp.class_hash - status = await wait_for_transaction(resp.transaction_hash) + status = await wait_for_transaction(resp.transaction_hash, account) logger.info(f"{status} {contract_name} class hash: {hex(resp.class_hash)}") return deployed_class_hash @@ -564,9 +608,40 @@ async def execute_calls(): _logs = defaultdict(list) +async def get_nonce(account): + global _nonces + if account.address not in _nonces: + _nonces[account.address] = await account.get_nonce(block_number="pending") + + network_nonce = await account.get_nonce(block_number="pending") + retries = 10 + while network_nonce != _nonces[account.address] and retries > 0: + logger.info( + f"⏳ Waiting for network nonce {network_nonce} to be {_nonces[account.address]}" + ) + await asyncio.sleep(0.1) + network_nonce = await account.get_nonce(block_number="pending") + retries -= 1 + if retries == 0: + logger.warning( + f"⏳ Network nonce {network_nonce} did not match expected nonce {_nonces[account.address]}" + ) + # After 1 second, the nonce should have been updated by the network in any case + _nonces[account.address] = network_nonce + + nonce = _nonces[account.address] + _nonces[account.address] += 1 + return nonce + + @lazy_execute async def execute_v1(account, calls): + for call in calls: + # Convert calldata to int (in case some boolean values are passed) + call.calldata = [int(data) for data in call.calldata] + calldata = _parse_calls(await account.cairo_version, calls) + nonce = await get_nonce(account) msg_hash = compute_transaction_hash( tx_hash_prefix=TransactionHashPrefix.INVOKE, version=1, @@ -575,7 +650,7 @@ async def execute_v1(account, calls): calldata=calldata, max_fee=_max_fee, chain_id=NETWORK["chain_id"].starknet_chain_id, - additional_data=[await account.get_nonce()], + additional_data=[nonce], ) signature = message_signature( msg_hash=msg_hash, priv_key=account.signer.private_key, seed=None @@ -583,7 +658,7 @@ async def execute_v1(account, calls): transaction = InvokeV1( version=1, signature=signature, - nonce=await account.get_nonce(), + nonce=nonce, max_fee=_max_fee, sender_address=account.address, calldata=calldata, @@ -610,8 +685,17 @@ async def execute_v1(account, calls): response = requests.post( f"{NETWORK['argent_multisig_api']}/0x{account.address:064x}/request", json=data, - ) - content = response.json()["content"] + ).json() + if response.get("status") == "transactionForMultisigBeingSubmitted": + await asyncio.sleep(5) + response = requests.post( + f"{NETWORK['argent_multisig_api']}/0x{account.address:064x}/request", + json=data, + ).json() + content = response.get("content") + if content is None: + raise ValueError(f"❌ Multisig transaction rejected: {response}") + transaction_id = content["id"] status = content["state"] while status not in {"TX_ACCEPTED_L2", "REVERTED", "REJECTED"}: @@ -630,8 +714,7 @@ async def execute_v1(account, calls): status = content["state"] logger.info(f"⏳ Multisig transaction status: {status}") if status != "TX_ACCEPTED_L2": - logger.error(f"❌ Transaction rejected:\n{content}") - raise ValueError(f"Transaction rejected: {status}") + logger.error(f"❌ Multisig transaction rejected:\n{status}") return { "transaction_hash": content["transactionHash"], @@ -649,7 +732,7 @@ async def execute_v1(account, calls): ), ) - status = await wait_for_transaction(res.transaction_hash) + status = await wait_for_transaction(res.transaction_hash, account) logger.info(f"{status} 0x{res.transaction_hash:064x}") return res @@ -719,7 +802,8 @@ async def call(contract: Union[str, int], *args, **kwargs): @functools.wraps(RPC_CLIENT.wait_for_tx) -async def wait_for_transaction(tx_hash): +async def wait_for_transaction(tx_hash, account=None): + global _nonces try: await RPC_CLIENT.wait_for_tx( tx_hash, @@ -728,6 +812,9 @@ async def wait_for_transaction(tx_hash): ) return "✅" except Exception as e: + if isinstance(e, TransactionRejectedError): + if account: + _nonces[account.address] -= 1 logger.error(f"Error while waiting for transaction 0x{tx_hash:064x}: {e}") return "❌" @@ -737,3 +824,143 @@ async def get_class_hash_at(address): return await RPC_CLIENT.get_class_hash_at(address) except Exception: return None + + +class RelayerPool: + _cached_relayers = None + + def __init__(self, accounts): + self.relayer_accounts = accounts + self.index = 0 + + @staticmethod + def compute_addresses(n): + private_key = NETWORK["private_key"] + public_key = KeyPair.from_private_key(int(private_key, 16)).public_key + constructor_calldata = [public_key] + class_hash = NETWORK.get( + "class_hash", get_declarations().get("OpenzeppelinAccount") + ) + return [ + compute_address( + salt=public_key + i, + class_hash=class_hash, + constructor_calldata=constructor_calldata, + deployer_address=0, + ) + for i in range(n) + ] + + @classmethod + @alru_cache + async def create(cls, n, **kwargs): + logger.info(f"ℹ️ Creating {n} relayer accounts") + + account = await get_starknet_account() + is_lazy = _lazy_execute[account.address] + _lazy_execute[account.address] = True + # Extracted the fund_address part to be able to fund all the accounts at once + private_key = NETWORK["private_key"] + public_key = KeyPair.from_private_key(int(private_key, 16)).public_key + addresses = cls.compute_addresses(n) + for address in addresses: + await fund_address( + address, + amount=kwargs.pop( + "amount", 1 if NETWORK["type"] != NetworkType.PROD else 0.01 + ), + ) + + await execute_calls() + _lazy_execute[account.address] = is_lazy + + addresses = [ + ( + await deploy_starknet_account( + salt=i + public_key, amount=0, private_key=private_key + ) + )["address"] + for i in range(n) + ] + logger.info(f"✅ Created {n} relayer accounts") + + eth_contract = await get_eth_contract() + accounts = [] + for address in addresses: + account = await get_starknet_account(address=address) + # Give infinite allowance to the main account so it's easier to move funds + allowance = ( + await call( + "ERC20", + "allowance", + account.address, + int(NETWORK["account_address"], 16), + address=eth_contract.address, + ) + ).remaining + if allowance != 2**256 - 1: + await invoke( + "ERC20", + "approve", + int(NETWORK["account_address"], 16), + 2**256 - 1, + account=account, + address=eth_contract.address, + ) + accounts.append(account) + return cls(accounts) + + def __next__(self) -> Account: + relayer = self.relayer_accounts[self.index] + self.index = (self.index + 1) % len(self.relayer_accounts) + return relayer + + @classmethod + @alru_cache + async def default(cls, **kwargs): + return await cls.create( + NETWORK.get("relayers", 20 if NETWORK["type"] != NetworkType.PROD else 1), + **kwargs, + ) + + @classmethod + @alru_cache + async def get(cls, salt: int): + if cls._cached_relayers is None: + cls._cached_relayers = await cls.default() + + return cls._cached_relayers.relayer_accounts[ + salt % len(cls._cached_relayers.relayer_accounts) + ] + + async def balances(self): + eth_contract = await get_eth_contract() + return [ + ( + f"0x{relayer.address:064x}", + f"{(await eth_contract.functions['balanceOf'].call(relayer.address)).balance / 1e18:.2f} ETH", + ) + for relayer in self.relayer_accounts + ] + + async def withdraw_all(self, to: int = int(NETWORK["account_address"], 16)): + account = await get_starknet_account() + is_lazy = _lazy_execute[account.address] + _lazy_execute[account.address] = True + eth_contract = await get_eth_contract() + for relayer in self.relayer_accounts: + balance = ( + await eth_contract.functions["balanceOf"].call(relayer.address) + ).balance + if balance > 0: + await invoke( + "ERC20", + "transferFrom", + relayer.address, + to, + balance, + address=eth_contract.address, + account=account, + ) + await execute_calls() + _lazy_execute[account.address] = is_lazy diff --git a/solidity_contracts/src/CairoPrecompiles/DualVmToken.sol b/solidity_contracts/src/CairoPrecompiles/DualVmToken.sol index ff4af0aeb..3f1075237 100644 --- a/solidity_contracts/src/CairoPrecompiles/DualVmToken.sol +++ b/solidity_contracts/src/CairoPrecompiles/DualVmToken.sol @@ -60,11 +60,23 @@ contract DualVmToken { function name() external view returns (string memory) { bytes memory returnData = starknetToken.staticcallCairo("name"); + + // Legacy tokens return a felt for name instead of a ByteArray + if (returnData.length == 32) { + return string(returnData); + } + return CairoLib.byteArrayToString(returnData); } function symbol() external view returns (string memory) { bytes memory returnData = starknetToken.staticcallCairo("symbol"); + + // Legacy tokens return a felt for name instead of a ByteArray + if (returnData.length == 32) { + return string(returnData); + } + return CairoLib.byteArrayToString(returnData); } diff --git a/tests/end_to_end/CairoPrecompiles/Pragma/test_pragma_precompile.py b/tests/end_to_end/CairoPrecompiles/Pragma/test_pragma_precompile.py index fc12fc45a..9826466ef 100644 --- a/tests/end_to_end/CairoPrecompiles/Pragma/test_pragma_precompile.py +++ b/tests/end_to_end/CairoPrecompiles/Pragma/test_pragma_precompile.py @@ -91,7 +91,7 @@ async def pragma_caller(owner): ) -@pytest_asyncio.fixture() +@pytest_asyncio.fixture(autouse=True) async def cairo_pragma_oracle(mocked_values, pragma_caller): await invoke("MockPragmaOracle", "set_price", *mocked_values) await invoke( @@ -160,7 +160,6 @@ async def test_should_return_data_median_for_query( data_type, aggregation_mode, mocked_values, - max_fee, ): (cairo_res,) = await cairo_pragma_oracle.functions["get_data"].call( data_type.to_dict(), @@ -229,13 +228,11 @@ async def test_should_return_data_median_for_query( ) async def test_should_get_mean_for_query( self, - cairo_pragma_oracle, cairo_pragma_summary_stats, pragma_caller, data_type, aggregation_mode, mocked_values, - max_fee, ): (cairo_res,) = await cairo_pragma_summary_stats.functions[ "calculate_mean" @@ -295,13 +292,11 @@ async def test_should_get_mean_for_query( ) async def test_should_get_volatility_for_query( self, - cairo_pragma_oracle, cairo_pragma_summary_stats, pragma_caller, data_type, aggregation_mode, mocked_values, - max_fee, ): (cairo_res,) = await cairo_pragma_summary_stats.functions[ "calculate_volatility" @@ -362,13 +357,11 @@ async def test_should_get_volatility_for_query( ) async def test_should_get_twap_for_query( self, - cairo_pragma_oracle, cairo_pragma_summary_stats, pragma_caller, data_type, aggregation_mode, mocked_values, - max_fee, ): (cairo_res,) = await cairo_pragma_summary_stats.functions[ "calculate_twap" diff --git a/tests/end_to_end/CairoPrecompiles/test_call_cairo_precompile.py b/tests/end_to_end/CairoPrecompiles/test_call_cairo_precompile.py index 536175c04..640bd79cf 100644 --- a/tests/end_to_end/CairoPrecompiles/test_call_cairo_precompile.py +++ b/tests/end_to_end/CairoPrecompiles/test_call_cairo_precompile.py @@ -2,6 +2,7 @@ import pytest_asyncio from eth_abi import encode +from kakarot_scripts.constants import NETWORK from kakarot_scripts.utils.kakarot import deploy, eth_send_transaction from kakarot_scripts.utils.starknet import get_contract, invoke from tests.utils.errors import cairo_error @@ -10,7 +11,7 @@ @pytest_asyncio.fixture(scope="module") -async def cairo_counter(max_fee, deployer): +async def cairo_counter(deployer): cairo_counter = get_contract("Counter", provider=deployer) yield cairo_counter @@ -105,9 +106,12 @@ async def test_should_fail_when_called_with_callcode( ): await cairo_counter_caller.incrementCairoCounterCallcode() + @pytest.mark.skipif( + NETWORK["name"] != "katana", reason="Not yet declared on sepolia" + ) class TestReentrancyKakarot: async def test_should_fail_when_reentrancy_cairo_call( - self, kakarot, kakarot_reentrancy, new_eoa, eth_call_calldata + self, kakarot_reentrancy, eth_call_calldata ): with cairo_error("ReentrancyGuard: reentrant call"): await kakarot_reentrancy.staticcallKakarot( @@ -115,7 +119,7 @@ async def test_should_fail_when_reentrancy_cairo_call( ) async def test_should_fail_when_reentrancy_cairo_call_whitelisted( - self, kakarot, kakarot_reentrancy, new_eoa, eth_call_calldata + self, kakarot_reentrancy, eth_call_calldata ): # Setup for whitelisted precompile await invoke( diff --git a/tests/end_to_end/CairoPrecompiles/test_dual_vm_token.py b/tests/end_to_end/CairoPrecompiles/test_dual_vm_token.py index 756757f46..936a4fe58 100644 --- a/tests/end_to_end/CairoPrecompiles/test_dual_vm_token.py +++ b/tests/end_to_end/CairoPrecompiles/test_dual_vm_token.py @@ -90,17 +90,13 @@ async def test_should_return_balance( ) assert balance_owner_starknet == balance_owner_evm - async def test_should_revert_balance_of_invalid_address( - self, starknet_token, dual_vm_token - ): + async def test_should_revert_balance_of_invalid_address(self, dual_vm_token): evm_error = keccak(b"InvalidStarknetAddress()")[:4] with cairo_error(evm_error): await dual_vm_token.functions["balanceOf(uint256)"](2**256 - 1) class TestActions: - async def test_should_transfer( - self, starknet_token, dual_vm_token, owner, other - ): + async def test_should_transfer(self, dual_vm_token, owner, other): amount = 1 balance_owner_before = await dual_vm_token.functions["balanceOf(address)"]( owner.address @@ -185,7 +181,7 @@ async def test_should_revert_transfer_insufficient_balance( ) async def test_should_revert_transfer_starknet_address_invalid_address( - self, starknet_token, dual_vm_token + self, dual_vm_token ): evm_error = keccak(b"InvalidStarknetAddress()")[:4] with cairo_error(evm_error): @@ -217,7 +213,7 @@ async def test_should_approve(self, dual_vm_token, owner, other): assert allowance_after == allowance_before + amount async def test_should_approve_starknet_address( - self, starknet_token, dual_vm_token, owner, other + self, dual_vm_token, owner, other ): allowance_before = await dual_vm_token.functions[ "allowance(address,uint256)" @@ -242,7 +238,7 @@ async def test_should_approve_starknet_address( assert allowance_after == amount async def test_should_revert_approve_starknet_address_invalid_address( - self, starknet_token, dual_vm_token + self, dual_vm_token ): evm_error = keccak(b"InvalidStarknetAddress()")[:4] with cairo_error(evm_error): @@ -271,7 +267,7 @@ async def test_allowance_owner_starknet_address( assert allowance_after == allowance_before + amount async def test_should_revert_allowance_starknet_address_owner_invalid_address( - self, starknet_token, dual_vm_token, other + self, dual_vm_token, other ): with cairo_error( "EVM tx reverted, reverting SN tx because of previous calls to cairo precompiles" @@ -281,7 +277,7 @@ async def test_should_revert_allowance_starknet_address_owner_invalid_address( ) async def test_should_revert_allowance_starknet_address_spender_invalid_address( - self, starknet_token, dual_vm_token, owner + self, dual_vm_token, owner ): with cairo_error( "EVM tx reverted, reverting SN tx because of previous calls to cairo precompiles" @@ -313,9 +309,7 @@ async def test_allowance_owner_and_spender_starknet_address( ](owner.address, other.starknet_contract.address) assert allowance_after == allowance_before + amount - async def test_should_transfer_from( - self, starknet_token, dual_vm_token, owner, other - ): + async def test_should_transfer_from(self, dual_vm_token, owner, other): amount = 1 balance_owner_before = await dual_vm_token.functions["balanceOf(address)"]( owner.address @@ -353,7 +347,7 @@ async def test_should_transfer_from( assert balance_other_before + amount == balance_other_after async def test_should_transfer_from_starknet_address_from( - self, starknet_token, dual_vm_token, owner, other + self, dual_vm_token, owner, other ): amount = 1 balance_owner_before = await dual_vm_token.functions["balanceOf(address)"]( @@ -392,7 +386,7 @@ async def test_should_transfer_from_starknet_address_from( assert balance_other_before + amount == balance_other_after async def test_should_transfer_from_starknet_address_to( - self, starknet_token, dual_vm_token, owner, other + self, dual_vm_token, owner, other ): amount = 1 balance_owner_before = await dual_vm_token.functions["balanceOf(address)"]( @@ -431,7 +425,7 @@ async def test_should_transfer_from_starknet_address_to( assert balance_other_before + amount == balance_other_after async def test_should_transfer_from_starknet_address_from_and_to( - self, starknet_token, dual_vm_token, owner, other + self, dual_vm_token, owner, other ): amount = 1 balance_owner_before = await dual_vm_token.functions["balanceOf(address)"]( @@ -576,7 +570,7 @@ async def test_should_revert_transfer_from_starknet_address_invalid_address( ) async def test_should_revert_transfer_from_starknet_address_from_and_to_invalid_address( - self, starknet_token, dual_vm_token, other + self, dual_vm_token, other ): evm_error = keccak(b"InvalidStarknetAddress()")[:4] with cairo_error(evm_error): @@ -584,9 +578,7 @@ async def test_should_revert_transfer_from_starknet_address_from_and_to_invalid_ 2**256 - 1, 2**256 - 1, 1, caller_eoa=other.starknet_contract ) - async def test_should_revert_tx_cairo_precompiles( - self, starknet_token, dual_vm_token, owner, other - ): + async def test_should_revert_tx_cairo_precompiles(self, dual_vm_token, other): with cairo_error( "EVM tx reverted, reverting SN tx because of previous calls to cairo precompiles" ): @@ -596,7 +588,7 @@ async def test_should_revert_tx_cairo_precompiles( class TestIntegrationUniswap: async def test_should_add_liquidity_and_swap( - starknet_token, dual_vm_token, token_a, router, owner, other + self, dual_vm_token, token_a, router, owner, other ): amount_a_desired = 1000 * await token_a.decimals() amount_dual_vm_token_desired = 500 * await dual_vm_token.decimals() diff --git a/tests/end_to_end/CairoPrecompiles/test_multicall_cairo_precompile.py b/tests/end_to_end/CairoPrecompiles/test_multicall_cairo_precompile.py index 5fe1401e1..b1d2c6611 100644 --- a/tests/end_to_end/CairoPrecompiles/test_multicall_cairo_precompile.py +++ b/tests/end_to_end/CairoPrecompiles/test_multicall_cairo_precompile.py @@ -12,7 +12,7 @@ @pytest_asyncio.fixture(scope="module") -async def cairo_counter(max_fee, deployer): +async def cairo_counter(deployer): cairo_counter = get_contract("Counter", provider=deployer) yield cairo_counter @@ -21,7 +21,7 @@ async def cairo_counter(max_fee, deployer): @pytest_asyncio.fixture(scope="module") -async def multicall_cairo_counter_caller(owner, cairo_counter): +async def multicall_cairo_counter_caller(cairo_counter): caller_contract = await deploy( "CairoPrecompiles", "MulticallCairoPrecompileTest", @@ -49,7 +49,7 @@ class TestCounterPrecompiles: @given(calls_per_batch=st.integers(min_value=0, max_value=100)) @settings(max_examples=5) async def test_should_increase_counter_in_batches( - self, cairo_counter, owner, calls_per_batch + self, cairo_counter, calls_per_batch ): prev_count = (await cairo_counter.functions["get"].call()).count @@ -122,7 +122,7 @@ async def test_should_fail_when_called_with_delegatecall( await multicall_cairo_counter_caller.incrementCairoCounterDelegatecall() async def test_should_fail_when_called_with_callcode( - self, multicall_cairo_counter_caller, cairo_counter + self, multicall_cairo_counter_caller ): with cairo_error( "EVM tx reverted, reverting SN tx because of previous calls to cairo precompiles" diff --git a/tests/end_to_end/CairoPrecompiles/test_whitelisted_call_cairo_precompile.py b/tests/end_to_end/CairoPrecompiles/test_whitelisted_call_cairo_precompile.py index fe7346a07..10cda7053 100644 --- a/tests/end_to_end/CairoPrecompiles/test_whitelisted_call_cairo_precompile.py +++ b/tests/end_to_end/CairoPrecompiles/test_whitelisted_call_cairo_precompile.py @@ -58,7 +58,7 @@ async def test_should_get_cairo_counter( assert evm_count == cairo_count == 1 async def test_should_increase_cairo_counter( - self, cairo_counter, cairo_counter_caller, max_fee + self, cairo_counter, cairo_counter_caller ): prev_count = (await cairo_counter.functions["get"].call()).count await cairo_counter_caller.incrementCairoCounter() @@ -67,7 +67,7 @@ async def test_should_increase_cairo_counter( @pytest.mark.parametrize("count", [0, 1, 2**128 - 1, 2**128, 2**256 - 1]) async def test_should_set_cairo_counter( - self, cairo_counter, cairo_counter_caller, owner, count + self, cairo_counter, cairo_counter_caller, count ): await cairo_counter_caller.setCairoCounter(count) new_count = (await cairo_counter.functions["get"].call()).count diff --git a/tests/end_to_end/Kakarot/test_coinbase.py b/tests/end_to_end/Kakarot/test_coinbase.py index 4cffb370e..4bfa2177e 100644 --- a/tests/end_to_end/Kakarot/test_coinbase.py +++ b/tests/end_to_end/Kakarot/test_coinbase.py @@ -5,7 +5,12 @@ from eth_utils.address import to_checksum_address from web3.contract import Contract as Web3Contract -from kakarot_scripts.utils.kakarot import deploy, eth_balance_of, fund_address +from kakarot_scripts.utils.kakarot import ( + deploy, + eth_balance_of, + eth_send_transaction, + fund_address, +) from kakarot_scripts.utils.starknet import call_contract from tests.utils.errors import evm_error @@ -47,8 +52,12 @@ async def test_should_receive_ether(self, coinbase: Web3Contract, owner): amount_wei = int(amount * 1e18) await fund_address(owner.address, 0.001) balance_coinbase_prev = await eth_balance_of(coinbase.address) - await coinbase.w3.eth.send_transaction( - caller_eoa=owner.starknet_contract, value=amount_wei + await eth_send_transaction( + coinbase.address, + data=b"", + value=amount_wei, + caller_eoa=owner.starknet_contract, + gas=40_000, ) balance_coinbase_after = await eth_balance_of(coinbase.address) assert balance_coinbase_after == balance_coinbase_prev + amount_wei diff --git a/tests/end_to_end/L1L2Messaging/test_messaging.py b/tests/end_to_end/L1L2Messaging/test_messaging.py index 30aabc2f4..f32cf90e1 100644 --- a/tests/end_to_end/L1L2Messaging/test_messaging.py +++ b/tests/end_to_end/L1L2Messaging/test_messaging.py @@ -1,14 +1,16 @@ import asyncio -import time import pytest import pytest_asyncio from eth_utils.address import to_checksum_address +from starknet_py.net.client_errors import ClientError +from starknet_py.net.client_models import L1HandlerTransaction +from kakarot_scripts.constants import NETWORK, RPC_CLIENT from kakarot_scripts.utils.kakarot import deploy from kakarot_scripts.utils.kakarot import get_deployments as get_evm_deployments from kakarot_scripts.utils.l1 import deploy_on_l1, get_l1_addresses, get_l1_contract -from kakarot_scripts.utils.starknet import invoke +from kakarot_scripts.utils.starknet import get_deployments as get_starknet_deployments from tests.utils.errors import evm_error @@ -55,7 +57,7 @@ async def message_app_l2(message_app_l1): @pytest.fixture(scope="function") -def wait_for_messaging(starknet_core): +def wait_for_l1_messaging(starknet_core): async def _factory(): event_filter_sn_messaging_local = ( @@ -72,21 +74,59 @@ async def _factory(): return _factory +@pytest.fixture(scope="function") +def wait_for_l2_messaging(): + async def _factory(block_number, l2_address): + l1_handlers = [] + i = 0 + interval = 4 + # L1 block time is 12s and Starknet block time is 30s + # 2 minutes should be enough to trigger the L1 handler + while i < 2 * 60: + try: + # Reach the tip of the chain + block = await RPC_CLIENT.get_block(block_number=block_number + i) + except ClientError: + # If the block is not found, it means we reached the pending block + block = await RPC_CLIENT.get_block(block_number="pending") + + l1_handlers += [ + transaction + for transaction in block.transactions + if isinstance(transaction, L1HandlerTransaction) + and transaction.contract_address + == get_starknet_deployments()["kakarot"] + and transaction.calldata[2] == int(l2_address, 16) + ] + i += interval + await asyncio.sleep(interval) + if l1_handlers: + return l1_handlers + + raise Exception("L1 handlers not found in 2 minutes") + + return _factory + + @pytest.mark.slow @pytest.mark.asyncio(scope="module") +@pytest.mark.skipif( + NETWORK["name"] != "katana", + reason="L2 to L1 messaging on sepolia requires waiting for Starknet to prove blocks", +) class TestL2ToL1Messages: async def test_should_increment_counter_on_l1( self, message_app_l1, message_app_l2, - wait_for_messaging, + wait_for_l1_messaging, ): msg_counter_before = message_app_l1.receivedMessagesCounter() increment_value = 8 await message_app_l2.increaseL1AppCounter( message_app_l1.address, increment_value ) - await wait_for_messaging() + await wait_for_l1_messaging() message_payload = increment_value.to_bytes(32, "big") message_app_l1.consumeCounterIncrease(message_app_l2.address, message_payload) msg_counter_after = message_app_l1.receivedMessagesCounter() @@ -97,13 +137,13 @@ async def test_should_fail_unauthorized_message_sender( message_app_l1, message_app_l2, l1_kakarot_messaging, - wait_for_messaging, + wait_for_l1_messaging, ): increment_value = 8 await message_app_l2.increaseL1AppCounter( message_app_l1.address, increment_value ) - await wait_for_messaging() + await wait_for_l1_messaging() message_payload = increment_value.to_bytes(32, "big") with evm_error("INVALID_MESSAGE_TO_CONSUME"): await l1_kakarot_messaging.consumeMessageFromL2( @@ -114,38 +154,28 @@ async def test_should_fail_unauthorized_message_sender( @pytest.mark.slow @pytest.mark.asyncio(scope="module") class TestL1ToL2Messages: - async def test_should_increment_counter_on_l2(self, message_app_l1, message_app_l2): + async def test_should_increment_counter_on_l2( + self, message_app_l1, message_app_l2, wait_for_l2_messaging + ): msg_counter_before = await message_app_l2.receivedMessagesCounter() increment_value = 1 + current_l2_block = await RPC_CLIENT.get_block_number() message_app_l1.increaseL2AppCounter( message_app_l2.address, value=increment_value ) - time.sleep(4) + await wait_for_l2_messaging(current_l2_block, message_app_l2.address) msg_counter_after = await message_app_l2.receivedMessagesCounter() assert msg_counter_after == msg_counter_before + increment_value - async def test_should_apply_alias_from_l1(self, message_app_l1, message_app_l2): + async def test_should_apply_alias_from_l1( + self, message_app_l1, message_app_l2, wait_for_l2_messaging + ): msg_counter_before = await message_app_l2.receivedMessagesCounter() increment_value = 1 + current_l2_block = await RPC_CLIENT.get_block_number() message_app_l1.increaseL2AppCounterFromCounterPartOnly( message_app_l2.address, value=increment_value ) - time.sleep(4) + await wait_for_l2_messaging(current_l2_block, message_app_l2.address) msg_counter_after = await message_app_l2.receivedMessagesCounter() assert msg_counter_after == msg_counter_before + increment_value - - async def test_should_fail_unauthorized_message_sender( - self, l1_kakarot_messaging, message_app_l1, message_app_l2 - ): - msg_counter_before = await message_app_l2.receivedMessagesCounter() - await invoke("kakarot", "set_l1_messaging_contract_address", 0) - message_app_l1.increaseL2AppCounter(message_app_l2.address, value=1) - time.sleep(4) - msg_counter_after = await message_app_l2.receivedMessagesCounter() - assert msg_counter_after == msg_counter_before - # teardown - await invoke( - "kakarot", - "set_l1_messaging_contract_address", - int(l1_kakarot_messaging.address, 16), - ) diff --git a/tests/end_to_end/PlainOpcodes/test_plain_opcodes.py b/tests/end_to_end/PlainOpcodes/test_plain_opcodes.py index e755223be..c0f2b35cf 100644 --- a/tests/end_to_end/PlainOpcodes/test_plain_opcodes.py +++ b/tests/end_to_end/PlainOpcodes/test_plain_opcodes.py @@ -5,6 +5,7 @@ from eth_utils import keccak from web3 import Web3 +from kakarot_scripts.constants import NETWORK from kakarot_scripts.utils.kakarot import ( eth_balance_of, eth_get_code, @@ -63,6 +64,9 @@ async def test_should_return_zero_with_invalid_block_number( assert int.from_bytes(blockhash_invalid_number, byteorder="big") == 0 + @pytest.mark.skipif( + NETWORK["name"] != "katana", reason="Not yet declared on sepolia" + ) async def test_should_return_zero_for_last_10_blocks( self, plain_opcodes, block_number ): @@ -438,9 +442,9 @@ class TestKeccak: @pytest.mark.parametrize( "input_length", [ - 20000, + 20_000, pytest.param( - 272000, marks=pytest.mark.xfail(reason="input length too big") + 272_000, marks=pytest.mark.xfail(reason="input length too big") ), ], ) diff --git a/tests/end_to_end/PlainOpcodes/test_safe.py b/tests/end_to_end/PlainOpcodes/test_safe.py index 6ea5e7ef3..520e105d6 100644 --- a/tests/end_to_end/PlainOpcodes/test_safe.py +++ b/tests/end_to_end/PlainOpcodes/test_safe.py @@ -3,7 +3,6 @@ from kakarot_scripts.constants import DEFAULT_GAS_PRICE from kakarot_scripts.utils.kakarot import deploy, eth_balance_of -from tests.utils.constants import ACCOUNT_BALANCE @pytest_asyncio.fixture(scope="package") @@ -14,16 +13,17 @@ async def safe(): @pytest.mark.asyncio(scope="package") @pytest.mark.Safe class TestSafe: - class TestReceive: + class TestDeposit: async def test_should_receive_eth(self, safe): balance_before = await safe.balance() - await safe.deposit(value=ACCOUNT_BALANCE) + await safe.deposit(value=1) balance_after = await safe.balance() - assert balance_after - balance_before == ACCOUNT_BALANCE + assert balance_after - balance_before == 1 class TestWithdrawTransfer: async def test_should_withdraw_transfer_eth(self, safe, owner): - await safe.deposit(value=ACCOUNT_BALANCE) + # Make sure the contract has some balance + await safe.deposit(value=1) safe_balance = await safe.balance() owner_balance_before = await eth_balance_of(owner.address) @@ -43,7 +43,8 @@ async def test_should_withdraw_transfer_eth(self, safe, owner): class TestWithdrawCall: async def test_should_withdraw_call_eth(self, safe, owner): - await safe.deposit(value=ACCOUNT_BALANCE) + # Make sure the contract has some balance + await safe.deposit(value=1) safe_balance = await safe.balance() owner_balance_before = await eth_balance_of(owner.address) diff --git a/tests/end_to_end/UniswapV2/test_uniswap_v2_factory.py b/tests/end_to_end/UniswapV2/test_uniswap_v2_factory.py index 6687bf622..c16b4da82 100644 --- a/tests/end_to_end/UniswapV2/test_uniswap_v2_factory.py +++ b/tests/end_to_end/UniswapV2/test_uniswap_v2_factory.py @@ -62,13 +62,6 @@ async def test_should_create_pair_only_once(self, factory, owner): assert await pair.token0() == token_0 assert await pair.token1() == token_1 - @pytest.mark.xfail(reason="Gas metering is inaccurate in kakarot") - async def test_should_use_correct_gas(self, factory, owner): - await factory.createPair( - *TEST_ADDRESSES, caller_eoa=owner.starknet_contract, max_fee=0 - ) - assert factory.tx.result.gas_used == 2_512_920 - class TestSetFeeTo: async def test_should_revert_when_caller_is_not_owner(self, factory, other): with evm_error("UniswapV2: FORBIDDEN"): diff --git a/tests/end_to_end/bytecodes.py b/tests/end_to_end/bytecodes.py index 40696d766..e810449e3 100644 --- a/tests/end_to_end/bytecodes.py +++ b/tests/end_to_end/bytecodes.py @@ -1860,11 +1860,7 @@ "success": 1, }, "id": "Precompiles - EC_ADD - playground test case", - "marks": [ - pytest.mark.EC_ADD, - pytest.mark.Precompiles, - pytest.mark.xfail(reason="Hint is not whitelisted"), - ], + "marks": [pytest.mark.EC_ADD, pytest.mark.Precompiles], }, { "params": { @@ -1906,11 +1902,7 @@ "success": 1, }, "id": "Precompiles - EC_MUL - playground test case", - "marks": [ - pytest.mark.EC_MUL, - pytest.mark.Precompiles, - pytest.mark.xfail(reason="Hint is not whitelisted"), - ], + "marks": [pytest.mark.EC_MUL, pytest.mark.Precompiles], }, { "params": { diff --git a/tests/end_to_end/conftest.py b/tests/end_to_end/conftest.py index b45c2993c..a4fe21b1a 100644 --- a/tests/end_to_end/conftest.py +++ b/tests/end_to_end/conftest.py @@ -8,20 +8,20 @@ from starknet_py.contract import Contract from starknet_py.net.account.account import Account -from kakarot_scripts.constants import NETWORK, RPC_CLIENT, NetworkType +from kakarot_scripts.constants import RPC_CLIENT, NetworkType from kakarot_scripts.utils.kakarot import deploy as deploy_kakarot -from kakarot_scripts.utils.kakarot import eth_balance_of +from kakarot_scripts.utils.kakarot import eth_balance_of, eth_send_transaction from kakarot_scripts.utils.kakarot import get_contract as get_solidity_contract from kakarot_scripts.utils.kakarot import get_deployments, get_eoa from kakarot_scripts.utils.starknet import ( + RelayerPool, call, get_contract, get_eth_contract, - get_starknet_account, ) from tests.utils.helpers import generate_random_private_key -logging.basicConfig() +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -52,6 +52,17 @@ def max_fee(): return int(5e17) +@pytest_asyncio.fixture(scope="session") +async def deployer(worker_id) -> Account: + """ + Return a cached version of the deployer contract. + """ + + account = await RelayerPool.get(abs(hash(worker_id))) + logger.info(f"ℹ️ Deployer for worker {worker_id}: 0x{account.address:064x}") + return account + + @pytest_asyncio.fixture(scope="session") async def new_eoa(deployer) -> Wallet: """ @@ -86,19 +97,21 @@ async def _factory(amount=0): if balance < tx_cost: continue - # Send the funds to the coinbase contract. The owner will be able to withdraw them. - await coinbase.w3.eth.send_transaction( - caller_eoa=wallet.starknet_contract, + await eth_send_transaction( + coinbase.address, + data=b"", + gas=gas_limit, value=balance - tx_cost, - gas_limit=gas_limit, gas_price=gas_price, + caller_eoa=wallet.starknet_contract, ) # Withdraw the funds to the deployer + coinbase_owner = await get_eoa() + assert coinbase_owner.evm_address == await coinbase.owner() await coinbase.functions["withdraw(uint256)"]( - toStarknetAddress=deployer.address, - gas_limit=gas_limit, - gas_price=gas_price, + deployer.address, + caller_eoa=coinbase_owner, ) @@ -107,7 +120,9 @@ async def owner(new_eoa): """ Return the main caller of all tests. """ - return await new_eoa(0.1) + account = await new_eoa(0.1) + logger.info(f"ℹ️ Owner: {account.address}") + return account @pytest_asyncio.fixture(scope="module") @@ -115,21 +130,16 @@ async def other(new_eoa): """ Just another EOA. """ - return await new_eoa(0.1) - - -@pytest_asyncio.fixture(scope="session") -async def deployer() -> Account: - """ - Return a cached version of the deployer contract. - """ - - return await get_starknet_account() + account = await new_eoa(0.1) + logger.info(f"ℹ️ Other: {account.address}") + return account @pytest_asyncio.fixture(scope="session") async def eth(deployer) -> Contract: - return await get_eth_contract(provider=deployer) + contract = await get_eth_contract(provider=deployer) + logger.info(f"ℹ️ ETH contract: {contract.address}") + return contract @pytest.fixture(scope="session") @@ -137,7 +147,9 @@ def cairo_counter(deployer) -> Contract: """ Return a cached version of the cairo_counter contract. """ - return get_contract("Counter", provider=deployer) + contract = get_contract("Counter", provider=deployer) + logger.info(f"ℹ️ Cairo counter: 0x{contract.address:064x}") + return contract @pytest.fixture(scope="session") @@ -145,7 +157,9 @@ def kakarot(deployer) -> Contract: """ Return a cached deployer for the whole session. """ - return get_contract("kakarot", provider=deployer) + contract = get_contract("kakarot", provider=deployer) + logger.info(f"ℹ️ Kakarot: 0x{contract.address:064x}") + return contract @pytest.fixture @@ -193,19 +207,6 @@ async def _factory(block_number: Optional[Union[int, str]] = "latest"): return _factory -@pytest.fixture(autouse=True, scope="session") -def relayers(worker_id): - """ - Override NETWORK["relayers"] to use the worker_id as the index and avoid nonce issues. - """ - try: - logger.info(f"Setting relayer index to {int(worker_id[2:])}") - NETWORK["relayers"].index = int(worker_id[2:]) - except ValueError: - logger.info(f"Error while setting relayer index to {worker_id}") - return - - # Uniswap fixtures TOTAL_SUPPLY = 10000 * 10**18 @@ -222,7 +223,7 @@ async def token_a(owner): @pytest_asyncio.fixture(scope="module") -async def weth(owner): +async def weth(): return await deploy_kakarot("WETH", "WETH9") @@ -232,7 +233,7 @@ async def factory(owner): @pytest_asyncio.fixture(scope="module") -async def router(owner, factory, weth): +async def router(factory, weth): return await deploy_kakarot( "UniswapV2Router", "UniswapV2Router02", factory.address, weth.address ) diff --git a/tests/end_to_end/test_kakarot.py b/tests/end_to_end/test_kakarot.py index e7d03781a..e9afe8946 100644 --- a/tests/end_to_end/test_kakarot.py +++ b/tests/end_to_end/test_kakarot.py @@ -25,7 +25,7 @@ params_execute = [pytest.param(case.pop("params"), **case) for case in test_cases] -logging.basicConfig() +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -248,6 +248,9 @@ async def test_eth_call_should_succeed(self, kakarot, new_eoa): assert result.gas_used == 21_000 class TestEthCallJumpCreationCodeDeployTx: + @pytest.mark.skipif( + NETWORK["name"] != "katana", reason="Not yet declared on sepolia" + ) async def test_eth_call_jump_creation_code_deploy_tx_should_succeed( self, kakarot, new_eoa ): @@ -345,7 +348,7 @@ async def test_should_transfer_ownership(self, kakarot, other): class TestAssertViewCall: @pytest.mark.parametrize("entrypoint", ["eth_call", "eth_estimate_gas"]) - async def test_should_raise_when_tx_view_entrypoint(self, kakarot, entrypoint): + async def test_should_raise_when_tx_view_entrypoint(self, entrypoint): evm_account = await get_eoa() calldata = bytes.fromhex("6001") tx_hash = await invoke( diff --git a/tests/utils/constants.py b/tests/utils/constants.py index 98a478d3b..f97cd0022 100644 --- a/tests/utils/constants.py +++ b/tests/utils/constants.py @@ -14,12 +14,6 @@ # Class hash of the cairo1 helpers CAIRO1_HELPERS_CLASS_HASH = 0xDEADBEEFABDE1E11A5 -# Amount of funds to pre-fund the account with -PRE_FUND_AMOUNT = int(1e17) # 0.01 ETH - -# Account balance is the amount of funds that the account has after being deployed -ACCOUNT_BALANCE = PRE_FUND_AMOUNT - # STACK STACK_MAX_DEPTH = 1024 diff --git a/tests/utils/helpers.py b/tests/utils/helpers.py index c33d76531..fb3411f2a 100644 --- a/tests/utils/helpers.py +++ b/tests/utils/helpers.py @@ -180,10 +180,6 @@ def encode_price(reserve_0: int, reserve_1: int) -> list: ] -def private_key_from_hex(hex_key: str): - return keys.PrivateKey(bytes.fromhex(hex_key)) - - def generate_random_private_key(): return keys.PrivateKey(int.to_bytes(random.getrandbits(256), 32, "big")) diff --git a/tests/utils/syscall_handler.py b/tests/utils/syscall_handler.py index 3300d90b8..b94424c2b 100644 --- a/tests/utils/syscall_handler.py +++ b/tests/utils/syscall_handler.py @@ -20,7 +20,7 @@ from tests.utils.constants import CAIRO1_HELPERS_CLASS_HASH, CHAIN_ID -def cairo_keccak(class_hash, calldata): +def cairo_keccak(_, calldata): return int_to_uint256( int.from_bytes( keccak( @@ -34,7 +34,7 @@ def cairo_keccak(class_hash, calldata): ) -def cairo_recover_eth_address(class_hash, calldata): +def cairo_recover_eth_address(_, calldata): """ Convert the input calldata from Cairo's `recover_eth_address` into a signature and a message hash, and then recover the Ethereum address from the signature. @@ -59,7 +59,7 @@ def cairo_recover_eth_address(class_hash, calldata): ] # return [is_some: 1, address: int] -def cairo_verify_signature_secp256r1(class_hash, calldata): +def cairo_verify_signature_secp256r1(_, calldata): """ Convert the input calldata from Cairo's `verify_signature_secp256r1` into a message hash, signature and public key, and verify the signature on the secp256r1 curve. @@ -81,7 +81,7 @@ def cairo_verify_signature_secp256r1(class_hash, calldata): return [is_valid] -def cairo_compute_sha256_u32_array(class_hash, calldata): +def cairo_compute_sha256_u32_array(_, calldata): """ Compute the sha256 of a u32 array and return its bytes4 array representation. """ @@ -193,7 +193,7 @@ class SyscallHandler: get_selector_from_name( "verify_signature_secp256r1" ): cairo_verify_signature_secp256r1, - get_selector_from_name("get_cairo1_helpers_class_hash"): lambda addr, data: [ + get_selector_from_name("get_cairo1_helpers_class_hash"): lambda *_: [ CAIRO1_HELPERS_CLASS_HASH ], get_selector_from_name( @@ -206,7 +206,7 @@ def __post_init__(self): lambda addr, data: self.execute_starknet_call(addr, data) ) - def execute_starknet_call(self, account_address, calldata): + def execute_starknet_call(self, _, calldata): contract_address = calldata[0] function_selector = calldata[1] calldata = calldata[2:] @@ -568,24 +568,13 @@ def deploy(self, segments, syscall_ptr): deploy_from_zero=deploy_from_zero, ) - retdata = self.patches.get("deploy")(class_hash, constructor_calldata) + retdata = self.patches.get(get_selector_from_name("deploy"))( + class_hash, constructor_calldata + ) retdata_segment = segments.add() segments.write_arg(retdata_segment, retdata) segments.write_arg(syscall_ptr + 6, [len(retdata), retdata_segment]) - @classmethod - @contextmanager - def patch_deploy(cls, value: callable): - """ - Patch the deploy syscall with the value. - - :param value: The value to patch with, a callable that will be called with the class hash, - the contract address salt, the constructor calldata and the deploy from zero flag. - """ - cls.patches["deploy"] = value - yield - del cls.patches["deploy"] - @classmethod @contextmanager def patch( @@ -643,27 +632,27 @@ def patch_state(cls, state: dict): """ patched_before = set(cls.patches.keys()) - def _balance_of(erc20_address, calldata): + def _balance_of(_, calldata): return int_to_uint256(state.get(calldata[0], {}).get("balance", 0)) balance_selector = get_selector_from_name("balanceOf") cls.patches[balance_selector] = _balance_of - def _bytecode(contract_address, calldata): + def _bytecode(contract_address, _): code = state.get(contract_address, {}).get("code", []) return [len(code), *code] bytecode_selector = get_selector_from_name("bytecode") cls.patches[bytecode_selector] = _bytecode - def _bytecode_len(contract_address, calldata): + def _bytecode_len(contract_address, _): code = state.get(contract_address, {}).get("code", []) return [len(code)] bytecode_len_selector = get_selector_from_name("bytecode_len") cls.patches[bytecode_len_selector] = _bytecode_len - def _get_nonce(contract_address, calldata): + def _get_nonce(contract_address, _): return [state.get(contract_address, {}).get("nonce", 0)] nonce_selector = get_selector_from_name("get_nonce")