Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add eth_chain_id entrypoint #932

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions crates/contracts/src/account_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,8 @@ pub mod AccountContract {
use core::starknet::{
EthAddress, ClassHash, get_caller_address, get_tx_info, get_block_timestamp
};
use core::traits::TryInto;
use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait};
use super::OutsideExecution;
use utils::constants::{POW_2_32};
use utils::eth_transaction::transaction::TransactionUnsignedTrait;
use utils::serialization::{deserialize_signature, deserialize_bytes, serialize_bytes};
use utils::traits::DefaultSignature;
Expand Down Expand Up @@ -241,7 +239,9 @@ pub mod AccountContract {
// EOA Validation
assert(self.Account_bytecode_len.read().is_zero(), 'EOA: cannot have code');

let chain_id: u64 = tx_info.chain_id.try_into().unwrap() % POW_2_32.try_into().unwrap();
let kakarot = IEthRPCDispatcher { contract_address: self.ownable.owner() };

let chain_id: u64 = kakarot.eth_chain_id();
assert(signature.len() == 5, 'EOA: Invalid signature length');
let signature = deserialize_signature(signature, chain_id)
.expect('EOA: invalid signature');
Expand All @@ -257,7 +257,6 @@ pub mod AccountContract {
let address = self.Account_evm_address.read();
verify_eth_signature(unsigned_transaction.hash, signature, address);

let kakarot = IEthRPCDispatcher { contract_address: self.ownable.owner() };
//TODO: refactor this to call eth_send_raw_unsigned_tx. Only the transactions bytes are
//passed.
let (success, return_data, gas_used) = kakarot
Expand Down
57 changes: 56 additions & 1 deletion crates/contracts/src/kakarot_core/eth_rpc.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use evm::backend::starknet_backend;
use evm::backend::validation::validate_eth_tx;
use evm::model::{TransactionResult, Address};
use evm::{EVMTrait};
use utils::constants::POW_2_53;
use utils::eth_transaction::transaction::{TransactionTrait, Transaction};

#[starknet::interface]
Expand Down Expand Up @@ -130,7 +131,9 @@ pub impl EthRPC<
}

fn eth_chain_id(self: @TContractState) -> u64 {
panic!("unimplemented")
let tx_info = get_tx_info().unbox();
bitfalt marked this conversation as resolved.
Show resolved Hide resolved
let tx_chain_id: u64 = tx_info.chain_id.try_into().unwrap();
tx_chain_id % POW_2_53.try_into().unwrap()
}

fn eth_call(
Expand Down Expand Up @@ -210,3 +213,55 @@ fn is_view(self: @KakarotCore::ContractState) -> bool {
}
true
}

#[cfg(test)]
mod tests {
use contracts::kakarot_core::KakarotCore;
use contracts::kakarot_core::eth_rpc::IEthRPC;
use snforge_std::{start_cheat_chain_id_global, stop_cheat_chain_id_global};
use utils::constants::POW_2_53;

fn set_up() -> KakarotCore::ContractState {
// Define the kakarot state to access contract functions
let kakarot_state = KakarotCore::unsafe_new_contract_state();

kakarot_state
}

fn tear_down() {
stop_cheat_chain_id_global();
}


#[test]
fn test_eth_chain_id_returns_input_when_less_than_pow_2_53() {
let kakarot_state = KakarotCore::unsafe_new_contract_state();
// Convert POW_2_53 - 1 to u64 since POW_2_53 is defined as u128
let chain_id: u64 = (POW_2_53 - 1).try_into().unwrap();
start_cheat_chain_id_global(chain_id.into());
assert_eq!(
kakarot_state.eth_chain_id(),
chain_id,
"Should return original chain ID when below 2^53"
);
tear_down();
}

#[test]
fn test_eth_chain_id_returns_modulo_when_greater_than_or_equal_to_pow_2_53() {
// Test with a value equal to 2^53
let kakarot_state = set_up();
let chain_id: u64 = POW_2_53.try_into().unwrap();
start_cheat_chain_id_global(chain_id.into());
assert_eq!(kakarot_state.eth_chain_id(), 0, "Should return 0 when chain ID is 2^53");

// Test with a value greater than 2^53
let chain_id: u64 = (POW_2_53 + 53).try_into().unwrap();
start_cheat_chain_id_global(chain_id.into());
assert_eq!(
kakarot_state.eth_chain_id(), 53, "Should return correct value after modulo operation"
);
tear_down();
}
}

14 changes: 8 additions & 6 deletions crates/evm/src/backend/starknet_backend.cairo
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use contracts::account_contract::{IAccountDispatcher, IAccountDispatcherTrait};
use contracts::kakarot_core::eth_rpc::IEthRPC;
use contracts::kakarot_core::{KakarotCore, KakarotCore::KakarotCoreImpl};
use core::num::traits::zero::Zero;
use core::ops::SnapshotDeref;
use core::starknet::storage::StoragePointerReadAccess;
use core::starknet::syscalls::{deploy_syscall};
use core::starknet::syscalls::{emit_event_syscall};
use core::starknet::{EthAddress, get_tx_info, get_block_info, SyscallResultTrait};
use core::starknet::{EthAddress, get_block_info, SyscallResultTrait};
use evm::errors::{ensure, EVMError, EOA_EXISTS};
use evm::model::{Address, AddressTrait, Environment, Account, AccountTrait};
use evm::model::{Transfer};
Expand Down Expand Up @@ -71,21 +72,22 @@ pub fn get_bytecode(evm_address: EthAddress) -> Span<u8> {

/// Populate an Environment with Starknet syscalls.
pub fn get_env(origin: EthAddress, gas_price: u128) -> Environment {
let kakarot_state = KakarotCore::unsafe_new_contract_state().snapshot_deref();
let kakarot_state = KakarotCore::unsafe_new_contract_state();
let kakarot_storage = kakarot_state.snapshot_deref();
let block_info = get_block_info().unbox();

// tx.gas_price and env.gas_price have the same values here
// - this is not always true in EVM transactions
Environment {
origin: origin,
gas_price,
chain_id: get_tx_info().unbox().chain_id.try_into().unwrap(),
prevrandao: kakarot_state.Kakarot_prev_randao.read(),
chain_id: kakarot_state.eth_chain_id(),
prevrandao: kakarot_storage.Kakarot_prev_randao.read(),
block_number: block_info.block_number,
block_gas_limit: constants::BLOCK_GAS_LIMIT,
block_timestamp: block_info.block_timestamp,
coinbase: kakarot_state.Kakarot_coinbase.read(),
base_fee: kakarot_state.Kakarot_base_fee.read(),
coinbase: kakarot_storage.Kakarot_coinbase.read(),
base_fee: kakarot_storage.Kakarot_base_fee.read(),
state: Default::default(),
}
}
Expand Down
10 changes: 3 additions & 7 deletions crates/evm/src/backend/validation.cairo
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use contracts::account_contract::{IAccountDispatcher, IAccountDispatcherTrait};
use contracts::kakarot_core::KakarotCore;
use contracts::kakarot_core::eth_rpc::IEthRPC;
use core::ops::SnapshotDeref;
use core::starknet::storage::{StoragePointerReadAccess};
use core::starknet::{get_caller_address, get_tx_info};
use core::starknet::{get_caller_address};
use evm::gas;
use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait};
use starknet::storage::StorageTrait;
Expand All @@ -24,12 +25,7 @@ pub fn validate_eth_tx(kakarot_state: @KakarotCore::ContractState, tx: Transacti

// Validate chain_id for post eip155
let tx_chain_id = tx.chain_id();
let kakarot_chain_id: u64 = get_tx_info()
.chain_id
.try_into()
.unwrap() % POW_2_32
.try_into()
.unwrap();
let kakarot_chain_id: u64 = kakarot_state.eth_chain_id();
if (tx_chain_id.is_some()) {
assert(tx_chain_id.unwrap() == kakarot_chain_id, 'Invalid chain id');
}
Expand Down
1 change: 1 addition & 0 deletions crates/utils/src/constants.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ pub const POW_2_24: u128 = 0x1000000;
pub const POW_2_32: u128 = 0x100000000;
pub const POW_2_40: u128 = 0x10000000000;
pub const POW_2_48: u128 = 0x1000000000000;
pub const POW_2_53: u128 = 0x20000000000000;
pub const POW_2_56: u128 = 0x100000000000000;
pub const POW_2_64: u128 = 0x10000000000000000;
pub const POW_2_72: u128 = 0x1000000000000000000;
Expand Down
Loading