Skip to content

Commit

Permalink
fix: access list deserializing (#933)
Browse files Browse the repository at this point in the history
* fix: access list deserializing"

* add test for access list pasing
  • Loading branch information
enitrat authored Sep 13, 2024
1 parent eeac8bb commit 51b0fdf
Show file tree
Hide file tree
Showing 11 changed files with 301 additions and 152 deletions.
48 changes: 16 additions & 32 deletions crates/contracts/src/kakarot_core/kakarot.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod KakarotCore {
use contracts::components::ownable::{ownable_component};
use contracts::components::upgradeable::{IUpgradeable, upgradeable_component};
use contracts::kakarot_core::interface::IKakarotCore;
use core::num::traits::{Zero, CheckedSub};
use core::num::traits::Zero;
use core::starknet::event::EventEmitter;
use core::starknet::storage::{
Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess,
Expand All @@ -19,12 +19,8 @@ pub mod KakarotCore {
};
use evm::backend::starknet_backend;
use evm::backend::validation::validate_eth_tx;
use evm::errors::{EVMError, ensure, EVMErrorTrait,};
use evm::gas;
use evm::model::account::AccountTrait;
use evm::model::{
Message, TransactionResult, TransactionResultTrait, ExecutionSummaryTrait, Address
};
use evm::model::{Message, TransactionResult, ExecutionSummaryTrait, Address};
use evm::precompiles::eth_precompile_addresses;
use evm::state::StateTrait;
use evm::{EVMTrait};
Expand Down Expand Up @@ -158,14 +154,16 @@ pub mod KakarotCore {

let origin = Address { evm: origin, starknet: self.compute_starknet_address(origin) };

let TransactionResult { success, return_data, gas_used, state: _ } = self
.process_transaction(origin, tx, tx.effective_gas_price(Option::None));
let TransactionResult { success, return_data, gas_used, state: _state } = self
.process_transaction(origin, tx, tx.effective_gas_price(Option::None), 0);

(success, return_data, gas_used)
}

fn eth_send_transaction(ref self: ContractState, tx: Transaction) -> (bool, Span<u8>, u64) {
let gas_price = validate_eth_tx(@self, tx);
fn eth_send_transaction(
ref self: ContractState, mut tx: Transaction
) -> (bool, Span<u8>, u64) {
let (gas_price, intrinsic_gas) = validate_eth_tx(@self, tx);

let starknet_caller_address = get_caller_address();
let account = IAccountDispatcher { contract_address: starknet_caller_address };
Expand All @@ -174,7 +172,7 @@ pub mod KakarotCore {
};

let TransactionResult { success, return_data, gas_used, mut state } = self
.process_transaction(origin, tx, gas_price);
.process_transaction(origin, tx, gas_price, intrinsic_gas);
starknet_backend::commit(ref state).expect('Committing state failed');
(success, return_data, gas_used)
}
Expand Down Expand Up @@ -271,34 +269,20 @@ pub mod KakarotCore {


fn process_transaction(
self: @ContractState, origin: Address, tx: Transaction, gas_price: u128
self: @ContractState,
origin: Address,
tx: Transaction,
gas_price: u128,
intrinsic_gas: u64
) -> TransactionResult {
let gas_limit = tx.gas_limit();
// Charge the cost of intrinsic gas - which has been verified to be <= gas_limit.
let gas_left = tx.gas_limit() - intrinsic_gas;
let mut env = starknet_backend::get_env(origin.evm, gas_price);

// TX Gas
let gas_fee = gas_limit.into() * gas_price;
let mut sender_account = env.state.get_account(origin.evm);
let sender_balance = sender_account.balance();
sender_account.set_nonce(sender_account.nonce() + 1);
env.state.set_account(sender_account);
match ensure(
sender_balance >= gas_fee.into() + tx.value(), EVMError::InsufficientBalance
) {
Result::Ok(_) => {},
Result::Err(err) => {
return TransactionResultTrait::exceptional_failure(err.to_bytes(), gas_limit);
}
};

let gas_left = match gas_limit.checked_sub(gas::calculate_intrinsic_gas_cost(@tx)) {
Option::Some(gas_left) => gas_left,
Option::None => {
return TransactionResultTrait::exceptional_failure(
EVMError::OutOfGas.to_bytes(), gas_limit
);
}
};
// Handle deploy/non-deploy transaction cases
let (to, is_deploy_tx, code, code_address, calldata) = match tx.kind() {
TxKind::Create => {
Expand Down
3 changes: 2 additions & 1 deletion crates/contracts/tests/test_kakarot_core.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,8 @@ fn test_process_transaction() {
.process_transaction(
origin: Address { evm: eoa_evm_address, starknet: eoa_starknet_address },
tx: Transaction::Legacy(tx),
:gas_price
:gas_price,
intrinsic_gas: 0
);
let return_data = result.return_data;

Expand Down
16 changes: 13 additions & 3 deletions crates/evm/src/backend/validation.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@ use contracts::kakarot_core::KakarotCore;
use core::ops::SnapshotDeref;
use core::starknet::storage::{StoragePointerReadAccess};
use core::starknet::{get_caller_address, get_tx_info};
use evm::gas;
use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait};
use starknet::storage::StorageTrait;
use utils::constants::POW_2_32;
use utils::eth_transaction::get_effective_gas_price;
use utils::eth_transaction::transaction::{Transaction, TransactionTrait};

pub fn validate_eth_tx(kakarot_state: @KakarotCore::ContractState, tx: Transaction) -> u128 {
/// Validates the ethereum transaction by checking adherence to Ethereum rules regarding
/// Gas logic, nonce, chainId and required balance.
/// Returns
/// - Effective gas price of the transaction
/// - Intrinsic Gas Cost of the transcation
pub fn validate_eth_tx(kakarot_state: @KakarotCore::ContractState, tx: Transaction) -> (u128, u64) {
let kakarot_storage = kakarot_state.snapshot_deref().storage();
// Validate transaction

Expand All @@ -32,12 +38,16 @@ pub fn validate_eth_tx(kakarot_state: @KakarotCore::ContractState, tx: Transacti
assert(account.get_nonce() == tx.nonce(), 'Invalid nonce');

// Validate gas
assert(tx.gas_limit() <= kakarot_state.get_block_gas_limit(), 'Tx gas > Block gas');
let gas_limit = tx.gas_limit();
assert(gas_limit <= kakarot_state.get_block_gas_limit(), 'Tx gas > Block gas');
let block_base_fee = kakarot_storage.Kakarot_base_fee.read();
let effective_gas_price = get_effective_gas_price(
Option::Some(tx.max_fee_per_gas()), tx.max_priority_fee_per_gas(), block_base_fee.into()
);
assert!(effective_gas_price.is_ok(), "{:?}", effective_gas_price.unwrap_err());
// Intrinsic Gas
let intrinsic_gas = gas::calculate_intrinsic_gas_cost(@tx);
assert(gas_limit > intrinsic_gas, 'Intrinsic gas > gas limit');

// Validate balance
let balance = IERC20CamelDispatcher {
Expand All @@ -47,5 +57,5 @@ pub fn validate_eth_tx(kakarot_state: @KakarotCore::ContractState, tx: Transacti
let max_gas_fee = tx.gas_limit().into() * tx.max_fee_per_gas();
let tx_cost = tx.value() + max_gas_fee.into();
assert(tx_cost <= balance, 'Not enough ETH');
effective_gas_price.unwrap()
(effective_gas_price.unwrap(), intrinsic_gas)
}
1 change: 0 additions & 1 deletion crates/evm/src/instructions/memory_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,6 @@ mod tests {
native_token
};
use snforge_std::{test_address, start_mock_call};
use utils::constants::EMPTY_KECCAK;
use utils::helpers::U8SpanExTrait;
use utils::helpers::compute_starknet_address;

Expand Down
2 changes: 1 addition & 1 deletion crates/evm/src/instructions/system_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,7 @@ mod tests {
0xf4,
0x00
].span();
let code_hash = bytecode.compute_keccak256_hash();
let _code_hash = bytecode.compute_keccak256_hash();
let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build();
let eoa_account = Account {
address: vm.message().target,
Expand Down
39 changes: 14 additions & 25 deletions crates/utils/src/errors.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ pub enum RLPError {
EmptyInput,
InputTooShort,
InvalidInput,
Custom: felt252
Custom: felt252,
NotAString,
FailedParsingU128,
FailedParsingU256,
FailedParsingAddress,
FailedParsingAccessList,
NotAList
}


Expand All @@ -17,7 +23,13 @@ pub impl RLPErrorIntoU256 of Into<RLPError, u256> {
RLPError::EmptyInput => 'input is null'.into(),
RLPError::InputTooShort => 'input too short'.into(),
RLPError::InvalidInput => 'rlp input not conform'.into(),
RLPError::Custom(msg) => msg.into()
RLPError::Custom(msg) => msg.into(),
RLPError::NotAString => 'rlp input is not a string'.into(),
RLPError::FailedParsingU128 => 'rlp failed parsing u128'.into(),
RLPError::FailedParsingU256 => 'rlp failed parsing u256'.into(),
RLPError::FailedParsingAddress => 'rlp failed parsing address'.into(),
RLPError::FailedParsingAccessList => 'rlp failed parsing access_list'.into(),
RLPError::NotAList => 'rlp input is not a list'.into()
}
}
}
Expand All @@ -32,35 +44,12 @@ pub impl RLPErrorImpl<T> of RLPErrorTrait<T> {
}
}


#[derive(Drop, Copy, PartialEq, Debug)]
pub enum RLPHelpersError {
NotAString,
FailedParsingU128,
FailedParsingU256,
FailedParsingAddress,
FailedParsingAccessList,
NotAList
}

#[generate_trait]
pub impl RLPHelpersErrorImpl<T> of RLPHelpersErrorTrait<T> {
fn map_err(self: Result<T, RLPHelpersError>) -> Result<T, EthTransactionError> {
match self {
Result::Ok(val) => Result::Ok(val),
Result::Err(error) => { Result::Err(EthTransactionError::RlpHelpersError(error)) }
}
}
}


#[derive(Drop, Copy, PartialEq, Debug)]
pub enum EthTransactionError {
RLPError: RLPError,
ExpectedRLPItemToBeList,
ExpectedRLPItemToBeString,
TransactionTypeError,
RlpHelpersError: RLPHelpersError,
// the usize represents the encountered length of payload
TopLevelRlpListWrongLength: usize,
// the usize represents the encountered length of payload
Expand Down
2 changes: 1 addition & 1 deletion crates/utils/src/eth_transaction.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::cmp::min;
use core::num::traits::{CheckedAdd, Zero};
use core::option::OptionTrait;
use core::starknet::{EthAddress, secp256_trait::Signature,};
use utils::errors::{EthTransactionError, RLPErrorImpl, RLPHelpersErrorImpl};
use utils::errors::{EthTransactionError, RLPErrorImpl};

use utils::helpers::ByteArrayExt;

Expand Down
2 changes: 1 addition & 1 deletion crates/utils/src/eth_transaction/eip1559.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::num::traits::SaturatingSub;
use crate::errors::{EthTransactionError, RLPError, RLPHelpersErrorTrait};
use crate::errors::{EthTransactionError, RLPError, RLPErrorTrait};
use crate::eth_transaction::common::TxKind;
use crate::eth_transaction::eip2930::AccessListItem;
use crate::rlp::{RLPItem, RLPHelpersTrait};
Expand Down
2 changes: 1 addition & 1 deletion crates/utils/src/eth_transaction/eip2930.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::starknet::EthAddress;
use crate::errors::{EthTransactionError, RLPError, RLPHelpersErrorTrait};
use crate::errors::{EthTransactionError, RLPError, RLPErrorTrait};
use crate::eth_transaction::common::TxKind;
use crate::rlp::{RLPItem, RLPHelpersTrait};
use crate::traits::SpanDefault;
Expand Down
2 changes: 1 addition & 1 deletion crates/utils/src/eth_transaction/transaction.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::starknet::EthAddress;
use crate::errors::{RLPError, EthTransactionError, RLPErrorTrait, RLPHelpersErrorTrait};
use crate::errors::{RLPError, EthTransactionError, RLPErrorTrait};
use crate::eth_transaction::common::{TxKind, TxKindTrait};
use crate::eth_transaction::eip1559::{TxEip1559, TxEip1559Trait};
use crate::eth_transaction::eip2930::{AccessListItem, TxEip2930, TxEip2930Trait};
Expand Down
Loading

0 comments on commit 51b0fdf

Please sign in to comment.