diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index fe91f5b54..2cc056926 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -32,18 +32,18 @@ lint: - actionlint@1.6.26 - bandit@1.7.5 - black@23.9.1 - - checkov@3.0.37 + - checkov@3.0.40 - git-diff-check - isort@5.12.0 - markdownlint@0.37.0 - oxipng@9.0.0 - prettier@3.1.0 - - ruff@0.1.5 + - ruff@0.1.6 - shellcheck@0.9.0 - shfmt@3.6.0 - taplo@0.8.1 - trivy@0.47.0 - - trufflehog@3.62.1 + - trufflehog@3.63.0 - yamllint@1.33.0 actions: disabled: diff --git a/crates/contracts/src/kakarot_core/interface.cairo b/crates/contracts/src/kakarot_core/interface.cairo index 9e253ba57..722e6d314 100644 --- a/crates/contracts/src/kakarot_core/interface.cairo +++ b/crates/contracts/src/kakarot_core/interface.cairo @@ -76,7 +76,7 @@ trait IKakarotCore { /// Executes an EVM transaction and possibly modifies the state fn eth_send_transaction( ref self: TContractState, - to: EthAddress, + to: Option, gas_limit: u128, gas_price: u128, value: u256, @@ -177,7 +177,7 @@ trait IExtendedKakarotCore { /// Executes an EVM transaction and possibly modifies the state fn eth_send_transaction( ref self: TContractState, - to: EthAddress, + to: Option, gas_limit: u128, gas_price: u128, value: u256, diff --git a/crates/contracts/src/kakarot_core/kakarot.cairo b/crates/contracts/src/kakarot_core/kakarot.cairo index 04f4bdc08..0876f496a 100644 --- a/crates/contracts/src/kakarot_core/kakarot.cairo +++ b/crates/contracts/src/kakarot_core/kakarot.cairo @@ -19,6 +19,7 @@ mod KakarotCore { use contracts::components::ownable::{ownable_component}; use contracts::components::upgradeable::{IUpgradeable, upgradeable_component}; use contracts::contract_account::{IContractAccountDispatcher, IContractAccountDispatcherTrait}; + use contracts::eoa::{IExternallyOwnedAccountDispatcher, IExternallyOwnedAccountDispatcherTrait}; use contracts::kakarot_core::interface::IKakarotCore; use contracts::kakarot_core::interface; use core::starknet::SyscallResultTrait; @@ -30,8 +31,10 @@ mod KakarotCore { use evm::model::contract_account::{ContractAccountTrait}; use evm::model::eoa::{EOATrait}; use evm::model::{ExecutionResult, Address, AddressTrait}; + use evm::state::StateTrait; use starknet::{ - EthAddress, ContractAddress, ClassHash, get_tx_info, get_contract_address, deploy_syscall + EthAddress, ContractAddress, ClassHash, get_tx_info, get_contract_address, deploy_syscall, + get_caller_address }; use super::{INVOKE_ETH_CALL_FORBIDDEN}; use super::{StoredAccountType}; @@ -263,13 +266,39 @@ mod KakarotCore { fn eth_send_transaction( ref self: ContractState, - to: EthAddress, + to: Option, gas_limit: u128, gas_price: u128, value: u256, data: Span ) -> Span { - array![].span() + let starknet_caller_address = get_caller_address(); + let account = IExternallyOwnedAccountDispatcher { + contract_address: starknet_caller_address + }; + let from = Address { evm: account.evm_address(), starknet: starknet_caller_address }; + + // Invariant: + // We want to make sure the caller is part of the Kakarot address_registry + // and is an EOA. Contracts are added to the registry ONLY if there are + // part of the Kakarot system and thus deployed by the main Kakarot contract + // itself. + let (caller_account_type, caller_starknet_address) = self + .address_registry(from.evm) + .expect('Fetching EOA failed'); + assert(caller_account_type == AccountType::EOA, 'Caller is not an EOA'); + + let mut result = self.handle_call(:from, :to, :gas_limit, :gas_price, :value, :data); + match result { + Result::Ok(result) => { + let mut state = result.state; + state.commit_state(); + result.return_data + }, + // TODO: Return the error message as Bytes in the response + // Eliminate all paths of possible panic in logic with relations to the EVM itself. + Result::Err(err) => panic_with_felt252(err.to_string()), + } } fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { diff --git a/crates/contracts/src/tests/test_kakarot_core.cairo b/crates/contracts/src/tests/test_kakarot_core.cairo index ad065e941..42abb57e5 100644 --- a/crates/contracts/src/tests/test_kakarot_core.cairo +++ b/crates/contracts/src/tests/test_kakarot_core.cairo @@ -2,6 +2,7 @@ use contracts::contract_account::ContractAccount::TEST_CLASS_HASH as ContractAcc use contracts::contract_account::{IContractAccountDispatcher, IContractAccountDispatcherTrait}; use contracts::eoa::ExternallyOwnedAccount; use contracts::kakarot_core::interface::IExtendedKakarotCoreDispatcherTrait; +use contracts::kakarot_core::interface::IKakarotCore; use contracts::kakarot_core::kakarot::StoredAccountType; use contracts::kakarot_core::{ interface::IExtendedKakarotCoreDispatcherImpl, KakarotCore, KakarotCore::{KakarotCoreInternal}, @@ -254,7 +255,7 @@ fn test_kakarot_contract_account_false_positive_jumpdest() { #[test] #[available_gas(2000000000000)] -fn test_eth_call() { +fn test_eth_send_transaction() { // Given let (native_token, kakarot_core) = contract_utils::setup_contracts_for_testing(); @@ -270,16 +271,54 @@ fn test_eth_call() { let gas_limit = test_utils::gas_limit(); let gas_price = test_utils::gas_price(); let value = 0; + // selector: function inc() + let data = array![0x37, 0x13, 0x03, 0xc0].span(); + + // When + testing::set_contract_address(eoa); + let return_data = kakarot_core.eth_send_transaction(:to, :gas_limit, :gas_price, :value, :data); + + // Then // selector: function get() let data = array![0x6d, 0x4c, 0xe6, 0x3c].span(); // When + let return_data = kakarot_core + .eth_call(from: evm_address, :to, :gas_limit, :gas_price, :value, :data); + + // Then + assert(return_data == u256_to_bytes_array(1).span(), 'wrong result'); +} +#[test] +#[available_gas(2000000000000)] +fn test_eth_call() { + // Given + let (native_token, kakarot_core) = contract_utils::setup_contracts_for_testing(); + + let evm_address = test_utils::evm_address(); + let eoa = kakarot_core.deploy_eoa(evm_address); + + let account = ContractAccountTrait::deploy( + test_utils::other_evm_address(), counter_evm_bytecode() + ) + .unwrap(); + let counter = IContractAccountDispatcher { contract_address: account.starknet }; + counter.set_storage_at(0, 1); + + let to = Option::Some(test_utils::other_evm_address()); + let gas_limit = test_utils::gas_limit(); + let gas_price = test_utils::gas_price(); + let value = 0; + // selector: function get() + let data = array![0x6d, 0x4c, 0xe6, 0x3c].span(); + + // When let return_data = kakarot_core .eth_call(from: evm_address, :to, :gas_limit, :gas_price, :value, :data); // Then - assert(return_data == u256_to_bytes_array(0).span(), 'wrong result'); + assert(return_data == u256_to_bytes_array(1).span(), 'wrong result'); } @@ -288,6 +327,7 @@ fn test_eth_call() { fn test_handle_call() { // Given let (native_token, kakarot_core) = contract_utils::setup_contracts_for_testing(); + let mut kakarot_core = KakarotCore::unsafe_new_contract_state(); let evm_address = test_utils::evm_address(); let eoa = kakarot_core.deploy_eoa(evm_address); @@ -304,7 +344,6 @@ fn test_handle_call() { let data = array![0x6d, 0x4c, 0xe6, 0x3c].span(); // When - let mut kakarot_core = KakarotCore::unsafe_new_contract_state(); let result = kakarot_core .handle_call(