From bdfa507a90ab2903ea2aa14032f95fc48c2069c2 Mon Sep 17 00:00:00 2001 From: Oba Date: Wed, 20 Nov 2024 09:33:16 +0100 Subject: [PATCH] [KGA-71][KGA-69][KGA-66][KGA-115][KGA-123] fix: remove messaging (#1623) Feature needs rework. Will not be used until further notice. https://github.com/code-423n4/2024-09-kakarot-findings/issues/111 https://github.com/code-423n4/2024-09-kakarot-findings/issues/105 --- cairo_zero/kakarot/constants.cairo | 4 - .../kakarot/interfaces/interfaces.cairo | 6 - cairo_zero/kakarot/kakarot.cairo | 45 ----- cairo_zero/kakarot/library.cairo | 39 ---- .../precompiles/kakarot_precompiles.cairo | 33 ---- .../kakarot/precompiles/precompiles.cairo | 2 +- .../precompiles/precompiles_helpers.cairo | 4 - cairo_zero/kakarot/storages.cairo | 4 - .../kakarot/precompiles/test_precompiles.py | 75 -------- .../tests/src/kakarot/test_kakarot.cairo | 25 --- cairo_zero/tests/src/kakarot/test_kakarot.py | 31 --- docs/general/cairo_precompiles.md | 35 ---- kakarot_scripts/deployment/main.py | 8 - .../deployment/messaging_deployments.py | 116 ----------- kakarot_scripts/utils/starknet.py | 25 ++- .../src/L1L2Messaging/AddressAliasHelper.sol | 45 ----- .../src/L1L2Messaging/L1KakarotMessaging.sol | 61 ------ .../src/L1L2Messaging/L2KakarotMessaging.sol | 18 -- .../src/L1L2Messaging/MessageAppL1.sol | 63 ------ .../src/L1L2Messaging/MessageAppL2.sol | 31 --- .../NoDelegateCall/L2KakarotMessagingHack.sol | 18 -- .../tests/L1KakarotMessage.t.sol | 70 ------- .../L1L2Messaging/test_messaging.py | 181 ------------------ .../NoDelegateCall/test_l2_messaging_hack.py | 35 ---- tests/utils/constants.py | 1 - 25 files changed, 16 insertions(+), 959 deletions(-) delete mode 100644 kakarot_scripts/deployment/messaging_deployments.py delete mode 100644 solidity_contracts/src/L1L2Messaging/AddressAliasHelper.sol delete mode 100644 solidity_contracts/src/L1L2Messaging/L1KakarotMessaging.sol delete mode 100644 solidity_contracts/src/L1L2Messaging/L2KakarotMessaging.sol delete mode 100644 solidity_contracts/src/L1L2Messaging/MessageAppL1.sol delete mode 100644 solidity_contracts/src/L1L2Messaging/MessageAppL2.sol delete mode 100644 solidity_contracts/src/NoDelegateCall/L2KakarotMessagingHack.sol delete mode 100644 solidity_contracts/tests/L1KakarotMessage.t.sol delete mode 100644 tests/end_to_end/L1L2Messaging/test_messaging.py delete mode 100644 tests/end_to_end/NoDelegateCall/test_l2_messaging_hack.py 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/deployment/main.py b/kakarot_scripts/deployment/main.py index ffeae858e..4891aef9d 100644 --- a/kakarot_scripts/deployment/main.py +++ b/kakarot_scripts/deployment/main.py @@ -7,10 +7,6 @@ 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 -from kakarot_scripts.deployment.messaging_deployments import ( - deploy_l1_messaging_contracts, - deploy_l2_messaging_contracts, -) from kakarot_scripts.deployment.pre_eip155_deployments import ( deploy_pre_eip155_contracts, deploy_pre_eip155_senders, @@ -69,10 +65,6 @@ async def main(): # Needs whitelist tx to be executed first await deploy_pre_eip155_contracts() - # %% Messaging - await deploy_l1_messaging_contracts() - await deploy_l2_messaging_contracts() - # %% Tear down coinbase_address = (await call("kakarot", "get_coinbase")).coinbase if coinbase_address == 0: diff --git a/kakarot_scripts/deployment/messaging_deployments.py b/kakarot_scripts/deployment/messaging_deployments.py deleted file mode 100644 index de0b37825..000000000 --- a/kakarot_scripts/deployment/messaging_deployments.py +++ /dev/null @@ -1,116 +0,0 @@ -# %% Imports -import logging - -from eth_abi.exceptions import InsufficientDataBytes -from uvloop import run -from web3.exceptions import ContractLogicError - -from kakarot_scripts.constants import NETWORK, RPC_CLIENT, NetworkType -from kakarot_scripts.utils.kakarot import deploy as deploy_evm -from kakarot_scripts.utils.kakarot import dump_deployments as dump_evm_deployments -from kakarot_scripts.utils.kakarot import get_deployments as get_evm_deployments -from kakarot_scripts.utils.l1 import ( - deploy_on_l1, - dump_l1_addresses, - get_l1_addresses, - get_l1_contract, -) -from kakarot_scripts.utils.starknet import call -from kakarot_scripts.utils.starknet import get_deployments as get_starknet_deployments -from kakarot_scripts.utils.starknet import invoke - -logger = logging.getLogger(__name__) - - -# %% -async def deploy_l1_messaging_contracts(): - # %% L1 - starknet_deployments = get_starknet_deployments() - l1_addresses = get_l1_addresses() - - l1_kakarot_messaging_registered_address = None - if address := l1_addresses.get("L1KakarotMessaging"): - l1_kakarot_messaging = get_l1_contract( - "L1L2Messaging", "L1KakarotMessaging", address=address - ) - try: - l1_kakarot_messaging_registered_address = ( - l1_kakarot_messaging.kakarotAddress() - ) - except (ContractLogicError, InsufficientDataBytes): - pass - - if l1_kakarot_messaging_registered_address != starknet_deployments["kakarot"]: - if NETWORK["type"] == NetworkType.DEV: - starknet_core = deploy_on_l1("Starknet", "StarknetMessagingLocal") - l1_addresses.update({"StarknetCore": starknet_core.address}) - else: - if "StarknetCore" not in l1_addresses: - raise ValueError("StarknetCore missing in L1 addresses") - - l1_kakarot_messaging = deploy_on_l1( - "L1L2Messaging", - "L1KakarotMessaging", - l1_addresses["StarknetCore"], - starknet_deployments["kakarot"], - ) - l1_addresses.update({"L1KakarotMessaging": l1_kakarot_messaging.address}) - - dump_l1_addresses(l1_addresses) - - -async def deploy_l2_messaging_contracts(): - # %% Messaging - evm_deployments = get_evm_deployments() - l1_kakarot_messaging_address = get_l1_addresses()["L1KakarotMessaging"] - deployment = evm_deployments.get("L2KakarotMessaging") - starknet_address = None - if deployment is not None: - starknet_address = ( - await call("kakarot", "get_starknet_address", deployment["address"]) - ).starknet_address - - if deployment is None or deployment["starknet_address"] != starknet_address: - l2_kakarot_messaging = await deploy_evm("L1L2Messaging", "L2KakarotMessaging") - await invoke( - "kakarot", - "set_authorized_cairo_precompile_caller", - int(l2_kakarot_messaging.address, 16), - 1, - ) - evm_deployments["L2KakarotMessaging"] = { - "address": int(l2_kakarot_messaging.address, 16), - "starknet_address": l2_kakarot_messaging.starknet_address, - } - - l1_messaging_contract_address = ( - await call("kakarot", "get_l1_messaging_contract_address") - ).l1_messaging_contract_address - if l1_messaging_contract_address != int(l1_kakarot_messaging_address, 16): - await invoke( - "kakarot", - "set_l1_messaging_contract_address", - int(l1_kakarot_messaging_address, 16), - ) - - dump_evm_deployments(evm_deployments) - - -# %% Run -async def main(): - try: - await RPC_CLIENT.get_class_hash_at(get_starknet_deployments()["kakarot"]) - except Exception: - logger.error("❌ Kakarot is not deployed, exiting...") - return - await deploy_l1_messaging_contracts() - await deploy_l2_messaging_contracts() - - -def main_sync(): - run(main()) - - -# %% -if __name__ == "__main__": - main_sync() 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/solidity_contracts/src/L1L2Messaging/AddressAliasHelper.sol b/solidity_contracts/src/L1L2Messaging/AddressAliasHelper.sol deleted file mode 100644 index 8788b2452..000000000 --- a/solidity_contracts/src/L1L2Messaging/AddressAliasHelper.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2019-2021, Offchain Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// from https://github.com/ethereum-optimism/optimism/blob/a080bd23666513269ff241f1b7bc3bce74b6ad15/packages/contracts-bedrock/src/vendor/AddressAliasHelper.sol - -pragma solidity ^0.8.0; - -library AddressAliasHelper { - uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); - - /// @notice Utility function that converts the address in the L1 that submitted a tx to - /// the inbox to the msg.sender viewed in the L2 - /// @param l1Address the address in the L1 that triggered the tx to L2 - /// @return l2Address L2 address as viewed in msg.sender - function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { - unchecked { - l2Address = address(uint160(l1Address) + offset); - } - } - - /// @notice Utility function that converts the msg.sender viewed in the L2 to the - /// address in the L1 that submitted a tx to the inbox - /// @param l2Address L2 address as viewed in msg.sender - /// @return l1Address the address in the L1 that triggered the tx to L2 - function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { - unchecked { - l1Address = address(uint160(l2Address) - offset); - } - } -} diff --git a/solidity_contracts/src/L1L2Messaging/L1KakarotMessaging.sol b/solidity_contracts/src/L1L2Messaging/L1KakarotMessaging.sol deleted file mode 100644 index db4113a69..000000000 --- a/solidity_contracts/src/L1L2Messaging/L1KakarotMessaging.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.27; - -import {AddressAliasHelper} from "./AddressAliasHelper.sol"; -import {IStarknetMessaging} from "../Starknet/IStarknetMessaging.sol"; - -interface IL1KakarotMessaging { - function sendMessageToL2(address to, uint248 value, bytes memory data) external payable; - function consumeMessageFromL2(address fromAddress, bytes calldata payload) external; -} - -contract L1KakarotMessaging { - /// @dev The selector of the function to call on the L2 contract. - uint256 public constant HANDLE_L1_MESSAGE_SELECTOR = uint256(keccak256("handle_l1_message")) % 2 ** 250; - - /// @dev The Starknet messaging contract. - IStarknetMessaging public immutable starknetMessaging; - /// @dev The address of the Kakarot contract on L2. - uint256 public immutable kakarotAddress; - - constructor(address starknetMessaging_, uint256 kakarotAddress_) { - starknetMessaging = IStarknetMessaging(starknetMessaging_); - kakarotAddress = kakarotAddress_; - } - - /// @notice Sends a message to a contract on L2. - /// @dev The bytes are split into individual uint256 values to use with the Starknet messaging system. - /// @dev This function must be called with a value sufficient to pay for the L1 message fee. - /// @param to The address of the contract on L2 to send the message to. - /// @param value The value to send to the contract on L2. The value is taken from the L2 contract address. - /// @param data The data to send to the contract on L2. - function sendMessageToL2(address to, uint248 value, bytes calldata data) external payable { - uint256 totalLength = data.length + 4; - uint256[] memory convertedData = new uint256[](totalLength); - convertedData[0] = uint256(uint160(AddressAliasHelper.applyL1ToL2Alias(msg.sender))); - convertedData[1] = uint256(uint160(to)); - convertedData[2] = uint256(value); - convertedData[3] = data.length; - for (uint256 i = 4; i < totalLength; ++i) { - convertedData[i] = uint256(uint8(data[i - 4])); - } - - // Send the converted data to L2 - starknetMessaging.sendMessageToL2{value: msg.value}(kakarotAddress, HANDLE_L1_MESSAGE_SELECTOR, convertedData); - } - - /// @notice Consumes a message sent from L2. - /// @param fromAddress L2 address sending the message. - /// @param payload The payload of the message to consume. - function consumeMessageFromL2(address fromAddress, bytes calldata payload) external { - // Will revert if the message is not consumable. - // Consider each byte of calldata as a uint256. - bytes memory fullPayload = abi.encode(msg.sender, fromAddress, payload); - uint256 totalLength = fullPayload.length; - uint256[] memory convertedPayload = new uint256[](totalLength); - for (uint256 i = 0; i < totalLength; ++i) { - convertedPayload[i] = uint256(uint8(fullPayload[i])); - } - starknetMessaging.consumeMessageFromL2(kakarotAddress, convertedPayload); - } -} diff --git a/solidity_contracts/src/L1L2Messaging/L2KakarotMessaging.sol b/solidity_contracts/src/L1L2Messaging/L2KakarotMessaging.sol deleted file mode 100644 index becbeebe5..000000000 --- a/solidity_contracts/src/L1L2Messaging/L2KakarotMessaging.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.27; - -import {CairoLib} from "kakarot-lib/CairoLib.sol"; -import {NoDelegateCall} from "../NoDelegateCall/NoDelegateCall.sol"; - -contract L2KakarotMessaging is NoDelegateCall { - /// @notice Sends a message to a contract on L1. - /// @dev This function is noDelegateCall to prevent attack vectors where a - /// contract can send messages to L1 with arbitrary target addresses and payloads; - /// these messages appear as originated by victim's EVM address. - /// @param to The address of the contract on L1 to send the message to. - /// @param data The data to send to the contract on L1. - function sendMessageToL1(address to, bytes calldata data) external noDelegateCall { - bytes memory payload = abi.encode(to, msg.sender, data); - CairoLib.sendMessageToL1(payload); - } -} diff --git a/solidity_contracts/src/L1L2Messaging/MessageAppL1.sol b/solidity_contracts/src/L1L2Messaging/MessageAppL1.sol deleted file mode 100644 index ac21e2e6b..000000000 --- a/solidity_contracts/src/L1L2Messaging/MessageAppL1.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import "./L1KakarotMessaging.sol"; -import "./MessageAppL2.sol"; -import "../Starknet/IStarknetMessaging.sol"; - -// Define some custom error as an example. -// It saves a lot's of space to use those custom error instead of strings. -error InvalidPayload(); - -/// @title Test contract to receive / send messages to starknet. -/// @author Glihm https://github.com/glihm/starknet-messaging-dev -contract MessageAppL1 { - IStarknetMessaging private _starknetMessaging; - IL1KakarotMessaging private _l1KakarotMessaging; - uint256 private _kakarotAddress; - uint256 public receivedMessagesCounter; - - /// @notice Constructor. - /// @param starknetMessaging The address of the StarknetMessaging contract. - /// @param l1KakarotMessaging The address of the L1KakarotMessaging contract. - /// @param kakarotAddress The Starknet address, on L2, of the Kakarot contract. - constructor(address starknetMessaging, address l1KakarotMessaging, uint256 kakarotAddress) { - _starknetMessaging = IStarknetMessaging(starknetMessaging); - _l1KakarotMessaging = IL1KakarotMessaging(l1KakarotMessaging); - _kakarotAddress = kakarotAddress; - } - - /// @notice Increases the counter inside the MessageAppL2 contract deployed on Kakarot. - /// @dev Must be called with a value sufficient to pay for the L1 message fee. - /// @param l2AppAddress The address of the L2 contract to trigger. - function increaseL2AppCounter(address l2AppAddress) external payable { - _l1KakarotMessaging.sendMessageToL2{value: msg.value}( - l2AppAddress, 0, abi.encodeCall(MessageAppL2.increaseMessagesCounter, 1) - ); - } - - /// @notice Increases the counter inside the MessageAppL2 contract deployed on Kakarot from this contract only. - /// @dev Must be called with a value sufficient to pay for the L1 message fee. - /// @param l2AppAddress The address of the L2 contract to trigger. - function increaseL2AppCounterFromCounterPartOnly(address l2AppAddress) external payable { - _l1KakarotMessaging.sendMessageToL2{value: msg.value}( - l2AppAddress, 0, abi.encodeCall(MessageAppL2.increaseMessageCounterFromL1Contract, 1) - ); - } - - /// @notice Manually consumes a message that was received from L2. - /// @param fromAddress L2 address sending the message. - /// @param payload Payload of the message used to verify the hash. - /// @dev A message "received" means that the message hash is registered as consumable. - /// One must provide the message content, to let Starknet Core contract verify the hash - /// and validate the message content before being consumed. - /// The L1KakarotMessaging contract must be called with a delegatecall to ensure that - /// the Starknet Core contract considers this contract as the consumer. - function consumeCounterIncrease(address fromAddress, bytes calldata payload) external { - _l1KakarotMessaging.consumeMessageFromL2(fromAddress, payload); - // Decode the uint256 value from the payload - uint256 value = abi.decode(payload, (uint256)); - receivedMessagesCounter += value; - } -} diff --git a/solidity_contracts/src/L1L2Messaging/MessageAppL2.sol b/solidity_contracts/src/L1L2Messaging/MessageAppL2.sol deleted file mode 100644 index 73d8597fc..000000000 --- a/solidity_contracts/src/L1L2Messaging/MessageAppL2.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; - -import {L2KakarotMessaging} from "./L2KakarotMessaging.sol"; -import {AddressAliasHelper} from "./AddressAliasHelper.sol"; - -contract MessageAppL2 { - L2KakarotMessaging public immutable l2KakarotMessaging; - address public immutable l1ContractCounterPart; - uint256 public receivedMessagesCounter; - - constructor(address l2KakarotMessaging_, address l1ContractCounterPart_) { - l2KakarotMessaging = L2KakarotMessaging(l2KakarotMessaging_); - l1ContractCounterPart = l1ContractCounterPart_; - } - - // @notice Sends a message to L1. - // @dev Uses the Cairo Precompiles mechanism to invoke the send_message_to_l1 syscall - function increaseL1AppCounter(address to, uint128 value) external { - l2KakarotMessaging.sendMessageToL1(to, abi.encode(value)); - } - - function increaseMessagesCounter(uint256 amount) external { - receivedMessagesCounter += amount; - } - - function increaseMessageCounterFromL1Contract(uint256 amount) external { - require(AddressAliasHelper.undoL1ToL2Alias(msg.sender) == l1ContractCounterPart, "ONLY_COUNTERPART_CONTRACT"); - receivedMessagesCounter += amount; - } -} diff --git a/solidity_contracts/src/NoDelegateCall/L2KakarotMessagingHack.sol b/solidity_contracts/src/NoDelegateCall/L2KakarotMessagingHack.sol deleted file mode 100644 index e5b4200b9..000000000 --- a/solidity_contracts/src/NoDelegateCall/L2KakarotMessagingHack.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.27; - -import {L2KakarotMessaging} from "../L1L2Messaging/L2KakarotMessaging.sol"; - -contract L2MessagingHack { - L2KakarotMessaging public immutable target; - - constructor(address _target) { - target = L2KakarotMessaging(_target); - } - - function trySendMessageToL1(address to, bytes calldata data) external returns (bool success) { - // Try to send message through delegatecall - (success,) = - address(target).delegatecall(abi.encodeWithSelector(L2KakarotMessaging.sendMessageToL1.selector, to, data)); - } -} diff --git a/solidity_contracts/tests/L1KakarotMessage.t.sol b/solidity_contracts/tests/L1KakarotMessage.t.sol deleted file mode 100644 index a610ae0d2..000000000 --- a/solidity_contracts/tests/L1KakarotMessage.t.sol +++ /dev/null @@ -1,70 +0,0 @@ -pragma solidity >=0.8.0; - -import "forge-std/Test.sol"; - -import {L1KakarotMessaging} from "../src/L1L2Messaging/L1KakarotMessaging.sol"; -import {StarknetMessagingLocal} from "../src/Starknet/StarknetMessagingLocal.sol"; -import {AddressAliasHelper} from "../src/L1L2Messaging/AddressAliasHelper.sol"; - -contract L1KakarotMessagingTest is Test { - L1KakarotMessaging l1KakarotMessaging; - StarknetMessagingLocal starknetMessagingLocal; - uint256 mockedKakarot = 0xFF1; - - function setUp() public { - starknetMessagingLocal = new StarknetMessagingLocal(); - l1KakarotMessaging = new L1KakarotMessaging(address(starknetMessagingLocal), mockedKakarot); - } - - function getL1ToL2MsgHash(uint256 toAddress, uint256 selector, uint256[] memory payload, uint256 nonce) - internal - view - returns (bytes32) - { - return keccak256( - abi.encodePacked( - uint256(uint160(address(l1KakarotMessaging))), toAddress, nonce, selector, payload.length, payload - ) - ); - } - - function test_sendMessageToL2(address to, uint248 value, bytes memory data) public { - vm.assume(value <= starknetMessagingLocal.getMaxL1MsgFee()); - deal(address(this), 100 ether); - l1KakarotMessaging.sendMessageToL2{value: 0.1 ether}(to, value, data); - - uint256 totalLength = data.length + 4; - uint256[] memory convertedData = new uint256[](totalLength); - convertedData[0] = uint256(uint160(AddressAliasHelper.applyL1ToL2Alias(address(this)))); - convertedData[1] = uint256(uint160(to)); - convertedData[2] = value; - convertedData[3] = data.length; - for (uint256 i = 4; i < totalLength; ++i) { - convertedData[i] = uint256(uint8(data[i - 4])); - } - - bytes32 msgHash = - getL1ToL2MsgHash(mockedKakarot, l1KakarotMessaging.HANDLE_L1_MESSAGE_SELECTOR(), convertedData, 0); - - assertEq(starknetMessagingLocal.l1ToL2Messages(msgHash), 0.1 ether + 1); - } - - function test_consumeMessageFromL2(address fromAddress, bytes memory payload) public { - deal(address(this), 100 ether); - bytes memory fullPayload = abi.encode(address(this), fromAddress, payload); - uint256 totalLength = fullPayload.length; - uint256[] memory convertedPayload = new uint256[](totalLength); - for (uint256 i = 0; i < totalLength; ++i) { - convertedPayload[i] = uint256(uint8(fullPayload[i])); - } - // Ensures the consumeMessageFromL2 function is called with the correct parameters. - vm.mockCall( - address(starknetMessagingLocal), - abi.encodeWithSelector( - starknetMessagingLocal.consumeMessageFromL2.selector, mockedKakarot, convertedPayload - ), - abi.encode(true) - ); - l1KakarotMessaging.consumeMessageFromL2(fromAddress, payload); - } -} diff --git a/tests/end_to_end/L1L2Messaging/test_messaging.py b/tests/end_to_end/L1L2Messaging/test_messaging.py deleted file mode 100644 index f32cf90e1..000000000 --- a/tests/end_to_end/L1L2Messaging/test_messaging.py +++ /dev/null @@ -1,181 +0,0 @@ -import asyncio - -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 get_deployments as get_starknet_deployments -from tests.utils.errors import evm_error - - -@pytest.fixture(scope="session") -def l1_addresses(): - return get_l1_addresses() - - -@pytest.fixture(scope="session") -def starknet_core(l1_addresses): - return get_l1_contract( - "Starknet", "StarknetMessagingLocal", l1_addresses["StarknetCore"] - ) - - -@pytest.fixture(scope="session") -def l1_kakarot_messaging(l1_addresses): - return get_l1_contract( - "L1L2Messaging", "L1KakarotMessaging", l1_addresses["L1KakarotMessaging"] - ) - - -@pytest.fixture(scope="session") -def message_app_l1(kakarot, l1_addresses): - return deploy_on_l1( - "L1L2Messaging", - "MessageAppL1", - starknetMessaging=l1_addresses["StarknetCore"], - l1KakarotMessaging=l1_addresses["L1KakarotMessaging"], - kakarotAddress=kakarot.address, - ) - - -@pytest_asyncio.fixture(scope="session") -async def message_app_l2(message_app_l1): - return await deploy( - "L1L2Messaging", - "MessageAppL2", - l2KakarotMessaging_=to_checksum_address( - get_evm_deployments()["L2KakarotMessaging"]["address"] - ), - l1ContractCounterPart_=message_app_l1.address, - ) - - -@pytest.fixture(scope="function") -def wait_for_l1_messaging(starknet_core): - - async def _factory(): - event_filter_sn_messaging_local = ( - starknet_core.events.MessageHashesAddedFromL2.create_filter( - fromBlock="latest" - ) - ) - while True: - messages = event_filter_sn_messaging_local.get_new_entries() - if messages: - return messages - await asyncio.sleep(1) - - 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_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_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() - assert msg_counter_after == msg_counter_before + increment_value - - async def test_should_fail_unauthorized_message_sender( - self, - message_app_l1, - message_app_l2, - l1_kakarot_messaging, - wait_for_l1_messaging, - ): - increment_value = 8 - await message_app_l2.increaseL1AppCounter( - message_app_l1.address, increment_value - ) - 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( - message_app_l2.address, message_payload - ) - - -@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, 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 - ) - 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, 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 - ) - 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 diff --git a/tests/end_to_end/NoDelegateCall/test_l2_messaging_hack.py b/tests/end_to_end/NoDelegateCall/test_l2_messaging_hack.py deleted file mode 100644 index a73eb6215..000000000 --- a/tests/end_to_end/NoDelegateCall/test_l2_messaging_hack.py +++ /dev/null @@ -1,35 +0,0 @@ -import pytest -import pytest_asyncio -from eth_utils.address import to_checksum_address - -from kakarot_scripts.utils.kakarot import deploy -from kakarot_scripts.utils.kakarot import get_deployments as get_evm_deployments - - -@pytest_asyncio.fixture(scope="function") -async def messaging_hack_contract(owner): - return await deploy( - "NoDelegateCallTesting", - "L2MessagingHack", - _target=to_checksum_address( - get_evm_deployments()["L2KakarotMessaging"]["address"] - ), - caller_eoa=owner.starknet_contract, - ) - - -@pytest.mark.asyncio(scope="module") -class TestL2MessagingHack: - async def test_malicious_message_should_fail_nodelegatecall( - self, - messaging_hack_contract, - ): - malicious_target = "0x1234567890123456789012345678901234567890" - malicious_data = "0xdeadbeef" - - result = await messaging_hack_contract.functions[ - "trySendMessageToL1(address,bytes)" - ](malicious_target, malicious_data) - assert result["success"] == 1 - underlying_call_succeeded = int.from_bytes(bytes(result["response"]), "big") - assert underlying_call_succeeded == 0 diff --git a/tests/utils/constants.py b/tests/utils/constants.py index 0dc54af49..93600322a 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