diff --git a/cairo_zero/kakarot/constants.cairo b/cairo_zero/kakarot/constants.cairo index e5773e42b..677d780a4 100644 --- a/cairo_zero/kakarot/constants.cairo +++ b/cairo_zero/kakarot/constants.cairo @@ -30,16 +30,12 @@ namespace Constants { // Kakarot precompiles const CAIRO_WHITELISTED_CALL_PRECOMPILE = 0x75001; - const CAIRO_MESSAGING_PRECOMPILE = 0x75002; const CAIRO_MULTICALL_PRECOMPILE = 0x75003; const CAIRO_CALL_PRECOMPILE = 0x75004; // FIELD PRIME const FELT252_PRIME_HIGH = 0x8000000000000110000000000000000; const FELT252_PRIME_LOW = 0x1; - - // Infinite gas handle_l1_message - const INFINITE_GAS = 2 ** 64 - 1; } // See model.Opcode: diff --git a/cairo_zero/kakarot/interfaces/interfaces.cairo b/cairo_zero/kakarot/interfaces/interfaces.cairo index 4a31631cd..021a01752 100644 --- a/cairo_zero/kakarot/interfaces/interfaces.cairo +++ b/cairo_zero/kakarot/interfaces/interfaces.cairo @@ -178,12 +178,6 @@ namespace IKakarot { func set_authorized_pre_eip155_tx(sender_address: felt, msg_hash: felt) { } - func set_l1_messaging_contract_address(l1_messaging_contract_address: felt) { - } - - func get_l1_messaging_contract_address() -> (l1_messaging_contract_address: felt) { - } - func eth_call( nonce: felt, origin: felt, diff --git a/cairo_zero/kakarot/kakarot.cairo b/cairo_zero/kakarot/kakarot.cairo index 10ec7bfe1..6d5438bc5 100644 --- a/cairo_zero/kakarot/kakarot.cairo +++ b/cairo_zero/kakarot/kakarot.cairo @@ -325,48 +325,3 @@ func set_authorized_pre_eip155_tx{syscall_ptr: felt*, pedersen_ptr: HashBuiltin* IAccount.set_authorized_pre_eip155_tx(sender_starknet_address, msg_hash); return (); } - -// @notice Sets the L1 messaging contract address -// @param l1_messaging_contract_address The address of the L1 messaging contract -@external -func set_l1_messaging_contract_address{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr -}(l1_messaging_contract_address: felt) { - Ownable.assert_only_owner(); - return Kakarot.set_l1_messaging_contract_address(l1_messaging_contract_address); -} - -// @notice Gets the L1 messaging contract address -// @return l1_messaging_contract_address The address of the L1 messaging contract -@external -func get_l1_messaging_contract_address{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr -}() -> (l1_messaging_contract_address: felt) { - let l1_messaging_contract_address = Kakarot.get_l1_messaging_contract_address(); - return (l1_messaging_contract_address=l1_messaging_contract_address); -} - -// @notice Handles messages from L1 -// @param from_address The address of the L1 contract sending the message -// @param l1_sender The address of the L1 account that initiated the message -// @param to_address The target address on L2 -// @param value The amount of native tokens to be transferred -// @param data_len The length of the EVM calldata -// @param data The EVM calldata -@l1_handler -func handle_l1_message{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin* -}(from_address: felt, l1_sender: felt, to_address: felt, value: felt, data_len: felt, data: felt*) { - alloc_locals; - Pausable.assert_not_paused(); - let l1_messaging_contract_address = Kakarot.get_l1_messaging_contract_address(); - if (from_address != l1_messaging_contract_address) { - return (); - } - - let (_, state, _, _) = Kakarot.handle_l1_message(l1_sender, to_address, value, data_len, data); - - // Reverted or not - commit the state change. If reverted, the state was cleared to only contain gas-related changes. - Starknet.commit(state); - return (); -} diff --git a/cairo_zero/kakarot/library.cairo b/cairo_zero/kakarot/library.cairo index 48f1046f5..09fc95405 100644 --- a/cairo_zero/kakarot/library.cairo +++ b/cairo_zero/kakarot/library.cairo @@ -27,7 +27,6 @@ from kakarot.storages import ( Kakarot_chain_id, Kakarot_evm_to_starknet_address, Kakarot_authorized_cairo_precompiles_callers, - Kakarot_l1_messaging_contract_address, ) from kakarot.events import evm_contract_deployed from kakarot.interpreter import Interpreter @@ -404,44 +403,6 @@ namespace Kakarot { return (evm_address=evm_address); } - func set_l1_messaging_contract_address{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr - }(l1_messaging_contract_address: felt) { - Kakarot_l1_messaging_contract_address.write(l1_messaging_contract_address); - return (); - } - - func get_l1_messaging_contract_address{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr - }() -> felt { - let (l1_messaging_contract_address) = Kakarot_l1_messaging_contract_address.read(); - return l1_messaging_contract_address; - } - - // @notice Handle an L1 message - // Gas is paid on L1 through the starknet messaging system hence this should not - // revert due to OOG. - // The gas limit is set to Constants.INFINITE_GAS. - // The gas price is set to 0 so no gas is paid and no refund is given. - func handle_l1_message{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr, - bitwise_ptr: BitwiseBuiltin*, - }(l1_sender: felt, to_address: felt, value: felt, data_len: felt, data: felt*) -> ( - model.EVM*, model.State*, felt, felt - ) { - // TODO: ensure fair gas limits and prices - let (val_high, val_low) = split_felt(value); - tempvar value_u256 = new Uint256(low=val_low, high=val_high); - let to = model.Option(is_some=1, value=to_address); - let (access_list) = alloc(); - - return eth_call( - 0, l1_sender, to, Constants.INFINITE_GAS, 0, value_u256, data_len, data, 0, access_list - ); - } - // @notice Initialize the chain ID // @param chain_id The chain ID func initialize_chain_id{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( diff --git a/cairo_zero/kakarot/precompiles/kakarot_precompiles.cairo b/cairo_zero/kakarot/precompiles/kakarot_precompiles.cairo index 78cbdd7ff..7d62ef09c 100644 --- a/cairo_zero/kakarot/precompiles/kakarot_precompiles.cairo +++ b/cairo_zero/kakarot/precompiles/kakarot_precompiles.cairo @@ -13,7 +13,6 @@ from kakarot.errors import Errors from kakarot.interfaces.interfaces import IAccount from kakarot.account import Account from kakarot.constants import Constants -from kakarot.storages import Kakarot_l1_messaging_contract_address from utils.utils import Helpers from backend.starknet import Starknet @@ -28,7 +27,6 @@ const NUMBER_OF_CALLS_BYTES = 32; // TODO: compute acceptable EVM gas values for Cairo execution const CAIRO_PRECOMPILE_GAS = 10000; -const CAIRO_MESSAGE_GAS = 5000; // ! Contains precompiles that are specific to Kakarot. // ! @@ -47,11 +45,6 @@ const CAIRO_MESSAGE_GAS = 5000; // ! A contract should never be whitelisted for usage without extensive review and // ! auditing. // ! -// ! - 0x75002: Whitelisted Cairo Message Precompile. Allows the whitelisted caller to send messages to -// ! L1. This can only be used by the L2KakarotMessaging contract. The message sent to L1 must be -// ! formatted in a specific way, and only allowing L2KakarotMessaging to send messages to L1 -// ! ensures this format is respected. -// ! // ! - 0x75003: Multicall Precompile. Allows the caller to execute `n` Cairo calls in a single // ! precompile call. This precompile cannot be called with DELEGATECALL / CALLCODE. As such, it can // ! be used permissionlessly by any contract. @@ -153,32 +146,6 @@ namespace KakarotPrecompiles { ); return (output_len, output, gas_cost, reverted); } - - // @notice Sends a message to L1. - // @dev Only the L2KakarotMessaging contract is allowed to send messages to L1. The caller must - // be whitelisted, and this whitelist _mut_ be enforced upstream. - // @param input_len The length of the input in bytes. - // @param input The input data. - // @param caller_address unused - func cairo_message{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr, - bitwise_ptr: BitwiseBuiltin*, - }(input_len: felt, input: felt*, caller_address: felt) -> ( - output_len: felt, output: felt*, gas_used: felt, reverted: felt - ) { - alloc_locals; - - // TODO: implement packing mechanism that doesn't truncate 32-byte values - // let (data_len, data) = Helpers.load_256_bits_array(data_bytes_len, data_ptr); - - let (target_address) = Kakarot_l1_messaging_contract_address.read(); - - send_message_to_l1(target_address, input_len, input); - let (output) = alloc(); - return (0, output, CAIRO_MESSAGE_GAS, FALSE); - } } namespace Internals { diff --git a/cairo_zero/kakarot/precompiles/precompiles.cairo b/cairo_zero/kakarot/precompiles/precompiles.cairo index 4704f2a88..a491e60b4 100644 --- a/cairo_zero/kakarot/precompiles/precompiles.cairo +++ b/cairo_zero/kakarot/precompiles/precompiles.cairo @@ -158,7 +158,7 @@ namespace Precompiles { jmp rel offset; call KakarotPrecompiles.cairo_call_precompile; // offset 0x0c: precompile 0x75001 ret; - call KakarotPrecompiles.cairo_message; // offset 0x0d: precompile 0x75002 + call not_implemented_precompile; // offset 0x0d ret; call KakarotPrecompiles.cairo_multicall_precompile; // offset 0x0e: precompile 0x75003 ret; diff --git a/cairo_zero/kakarot/precompiles/precompiles_helpers.cairo b/cairo_zero/kakarot/precompiles/precompiles_helpers.cairo index 168c3cc46..faccc09a7 100644 --- a/cairo_zero/kakarot/precompiles/precompiles_helpers.cairo +++ b/cairo_zero/kakarot/precompiles/precompiles_helpers.cairo @@ -42,16 +42,12 @@ namespace PrecompilesHelpers { // @notice Return whether the precompile address requires a whitelist. // @dev The Cairo Call precompile must be whitelisted, as we can use it with DELEGATECALL / CALLCODE // to preserve the msg.sender of the contract that calls this precompile. Use case: DualVM tokens. - // @dev The Cairo Messaging precompile must be whitelisted, as we format the message payload in a specific Solidity contract. // @param precompile_address The address of the precompile. // @return Whether the precompile address requires a whitelist. func requires_whitelist(precompile_address: felt) -> felt { if (precompile_address == Constants.CAIRO_WHITELISTED_CALL_PRECOMPILE) { return TRUE; } - if (precompile_address == Constants.CAIRO_MESSAGING_PRECOMPILE) { - return TRUE; - } return FALSE; } diff --git a/cairo_zero/kakarot/storages.cairo b/cairo_zero/kakarot/storages.cairo index 7efeefd64..c8f404f46 100644 --- a/cairo_zero/kakarot/storages.cairo +++ b/cairo_zero/kakarot/storages.cairo @@ -51,7 +51,3 @@ func Kakarot_chain_id() -> (res: felt) { @storage_var func Kakarot_authorized_cairo_precompiles_callers(address: felt) -> (res: felt) { } - -@storage_var -func Kakarot_l1_messaging_contract_address() -> (res: felt) { -} diff --git a/cairo_zero/tests/src/kakarot/precompiles/test_precompiles.py b/cairo_zero/tests/src/kakarot/precompiles/test_precompiles.py index eaec65405..a4e212371 100644 --- a/cairo_zero/tests/src/kakarot/precompiles/test_precompiles.py +++ b/cairo_zero/tests/src/kakarot/precompiles/test_precompiles.py @@ -1,9 +1,7 @@ import pytest -from eth_abi import encode from starkware.starknet.public.abi import get_selector_from_name from tests.utils.constants import ( - CAIRO_MESSAGE_GAS, CAIRO_PRECOMPILE_GAS, FIRST_KAKAROT_PRECOMPILE_ADDRESS, FIRST_ROLLUP_PRECOMPILE_ADDRESS, @@ -208,79 +206,6 @@ def test__cairo_precompiles( ) return - class TestKakarotMessaging: - @SyscallHandler.patch( - "Kakarot_authorized_cairo_precompiles_callers", - AUTHORIZED_CALLER_ADDRESS, - 1, - ) - @SyscallHandler.patch( - "Kakarot_l1_messaging_contract_address", - 0xC0DE, - ) - @pytest.mark.parametrize( - "address, caller_address, input_data, to_address, expected_reverted_return_data, expected_reverted", - [ - ( - 0x75002, - AUTHORIZED_CALLER_ADDRESS, - encode( - ["uint160", "bytes"], [0xC0DE, encode(["uint128"], [0x2A])] - ), - 0xC0DE, - b"", - False, - ), - ( - 0x75002, - AUTHORIZED_CALLER_ADDRESS, - encode(["uint160", "bytes"], [0xC0DE, 0x2A.to_bytes(1, "big")]), - 0xC0DE, - b"", - False, - ), - ( - 0x75002, - UNAUTHORIZED_CALLER_ADDRESS, - bytes.fromhex("0abcdef0"), - 0xC0DE, - b"Kakarot: unauthorizedPrecompile", - True, - ), - ], - ids=[ - "ok_32_bytes_data", - "ok_1_bytes_data", - "ko_unauthorized_caller", - ], - ) - def test__cairo_message( - self, - caller_address, - cairo_run, - address, - input_data, - to_address, - expected_reverted_return_data, - expected_reverted, - ): - address = 0x75002 - return_data, reverted, gas_used = cairo_run( - "test__precompiles_run", - address=address, - input=input_data, - caller_address=caller_address, - message_address=address, - ) - if expected_reverted: - assert reverted - assert bytes(return_data) == expected_reverted_return_data - return - SyscallHandler.mock_send_message_to_l1.assert_any_call( - to_address=to_address, payload=list(input_data) - ) - assert gas_used == CAIRO_MESSAGE_GAS - class TestIsPrecompile: @pytest.mark.parametrize( "address", range(0, LAST_ETHEREUM_PRECOMPILE_ADDRESS + 2) diff --git a/cairo_zero/tests/src/kakarot/test_kakarot.cairo b/cairo_zero/tests/src/kakarot/test_kakarot.cairo index 4b2031702..f76ade9ae 100644 --- a/cairo_zero/tests/src/kakarot/test_kakarot.cairo +++ b/cairo_zero/tests/src/kakarot/test_kakarot.cairo @@ -20,7 +20,6 @@ from kakarot.kakarot import ( transfer_ownership, upgrade_account, deploy_externally_owned_account, - handle_l1_message, pause, unpause, initialize_chain_id, @@ -253,30 +252,6 @@ func test__upgrade_account{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range return (); } -func test__handle_l1_message{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr, bitwise_ptr: BitwiseBuiltin* -}() { - tempvar from_address; - tempvar l1_sender; - tempvar to_address; - tempvar value; - tempvar data_len; - let (data) = alloc(); - - %{ - ids.from_address = program_input["from_address"] - ids.l1_sender = program_input["l1_sender"] - ids.to_address = program_input["to_address"] - ids.value = program_input["value"] - ids.data_len = len(program_input["data"]) - segments.write_arg(ids.data, list(program_input["data"])) - %} - - handle_l1_message(from_address, l1_sender, to_address, value, data_len, data); - - return (); -} - func test__pause{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { pause(); return (); diff --git a/cairo_zero/tests/src/kakarot/test_kakarot.py b/cairo_zero/tests/src/kakarot/test_kakarot.py index 5d1f0e2e6..ae4c6ca79 100644 --- a/cairo_zero/tests/src/kakarot/test_kakarot.py +++ b/cairo_zero/tests/src/kakarot/test_kakarot.py @@ -510,37 +510,6 @@ def test_upgrade_account_should_replace_class(self, cairo_run): calldata=[0x1234], ) - class TestL1Handler: - @SyscallHandler.patch("Pausable_paused", 1) - def test_should_assert_unpaused(self, cairo_run): - with cairo_error(message="Pausable: paused"): - cairo_run( - "test__handle_l1_message", - from_address=0xABC, - l1_sender=0xABC, - to_address=0xABC, - value=0xABC, - 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 diff --git a/docs/general/cairo_precompiles.md b/docs/general/cairo_precompiles.md index f414a8040..95f52db7d 100644 --- a/docs/general/cairo_precompiles.md +++ b/docs/general/cairo_precompiles.md @@ -32,7 +32,6 @@ From these principles, we can derive the following design. There are 4 precompiles currently deployed on Kakarot: - 0x75001: Whitelisted Cairo Precompile -- 0x75002: Whitelisted Cairo Message Precompile - 0x75003: Multicall Precompile - 0x75004: Cairo Call Precompile @@ -116,40 +115,6 @@ sequenceDiagram end ``` -### 0x75002: Whitelisted Cairo Message Precompile - -This precompile allows any whitelisted caller to execute a Cairo contract. The -whitelisting is based on the address of the caller. The purpose of the whitelist -is to ensure that messages sent to L1 are following a specific format (`to`, -`sender`, `data`). - -```mermaid -sequenceDiagram - participant Alice - participant L2KakarotMessaging - participant NonWhitelistedContract - participant Precompile_75002 - - rect rgb(200, 255, 200) - Note over Alice,Precompile_75002: Successful Flow - Whitelisted Contract - Alice->>L2KakarotMessaging: Call - L2KakarotMessaging->>Precompile_75002: Execute Cairo Message - Note over Precompile_75002: Check if L2KakarotMessaging
is whitelisted ✓ - Note over Precompile_75002: Process message with:
- to
- sender
- data - Precompile_75002-->>L2KakarotMessaging: Success ✓ - L2KakarotMessaging-->>Alice: Success ✓ - end - - rect rgb(255, 200, 200) - Note over Alice,Precompile_75002: Failed Flow - Non-whitelisted Contract - Alice->>NonWhitelistedContract: Call - NonWhitelistedContract->>Precompile_75002: Execute Cairo Message - Note over Precompile_75002: Check if NonWhitelistedContract
is whitelisted ✗ - Precompile_75002-->>NonWhitelistedContract: Fail ✗ - NonWhitelistedContract-->>Alice: Fail ✗ - end -``` - ### 0x75003: Multicall Precompile Allows the caller to execute `n` Cairo calls in a single precompile call. This diff --git a/kakarot_scripts/utils/starknet.py b/kakarot_scripts/utils/starknet.py index ac99c8392..7768497f7 100644 --- a/kakarot_scripts/utils/starknet.py +++ b/kakarot_scripts/utils/starknet.py @@ -301,20 +301,25 @@ def get_artifact(contract_name): return Artifact(sierra=None, casm=artifacts[0]) # Cairo 1 artifacts - artifacts = list(BUILD_DIR_SSJ.glob(f"**/*{contract_name}.*.json")) or [ + artifacts = list(BUILD_DIR_SSJ.glob(f"**/*_{contract_name}.*.json")) or [ artifact - for artifact in list(CAIRO_DIR.glob(f"**/*{contract_name}.*.json")) + for artifact in list(CAIRO_DIR.glob(f"**/*_{contract_name}.*.json")) if "test" not in str(artifact) ] if artifacts: - sierra, casm = ( - artifacts - if "sierra.json" in artifacts[0].name - or ".contract_class.json" in artifacts[0].name - else artifacts[::-1] - ) - return Artifact(sierra=sierra, casm=casm) - + try: + sierra, casm = ( + artifacts + if "sierra.json" in artifacts[0].name + or ".contract_class.json" in artifacts[0].name + else artifacts[::-1] + ) + return Artifact(sierra=sierra, casm=casm) + except Exception as e: + logger.error( + f"Error while loading artifact for {contract_name}: {e}, artifacts: {artifacts}" + ) + raise e raise FileNotFoundError(f"No artifact found for {contract_name}") diff --git a/tests/utils/constants.py b/tests/utils/constants.py index f97cd0022..9a6c128a2 100644 --- a/tests/utils/constants.py +++ b/tests/utils/constants.py @@ -33,7 +33,6 @@ LAST_KAKAROT_PRECOMPILE_ADDRESS = 0x75004 CAIRO_PRECOMPILE_GAS = 10000 -CAIRO_MESSAGE_GAS = 5000 MAX_INT = 2**256 - 1