diff --git a/crates/contracts/src/account_contract.cairo b/crates/contracts/src/account_contract.cairo index 0bb162056..9391ac4db 100644 --- a/crates/contracts/src/account_contract.cairo +++ b/crates/contracts/src/account_contract.cairo @@ -46,13 +46,6 @@ pub trait IAccount { #[starknet::contract(account)] pub mod AccountContract { - use contracts::components::ownable::IOwnable; - use contracts::components::ownable::ownable_component::InternalTrait; - use contracts::components::ownable::ownable_component; - use contracts::errors::KAKAROT_REENTRANCY; - use contracts::kakarot_core::eth_rpc::{IEthRPCDispatcher, IEthRPCDispatcherTrait}; - use contracts::kakarot_core::interface::{IKakarotCoreDispatcher, IKakarotCoreDispatcherTrait}; - use contracts::storage::StorageBytecode; use core::cmp::min; use core::num::traits::Bounded; use core::num::traits::zero::Zero; @@ -66,6 +59,13 @@ pub mod AccountContract { use core::starknet::{ EthAddress, ClassHash, get_caller_address, get_tx_info, get_block_timestamp }; + use crate::components::ownable::IOwnable; + use crate::components::ownable::ownable_component::InternalTrait; + use crate::components::ownable::ownable_component; + use crate::errors::KAKAROT_REENTRANCY; + use crate::kakarot_core::eth_rpc::{IEthRPCDispatcher, IEthRPCDispatcherTrait}; + use crate::kakarot_core::interface::{IKakarotCoreDispatcher, IKakarotCoreDispatcherTrait}; + use crate::storage::StorageBytecode; use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use super::OutsideExecution; use utils::eth_transaction::transaction::TransactionUnsignedTrait; diff --git a/crates/contracts/src/kakarot_core/eth_rpc.cairo b/crates/contracts/src/kakarot_core/eth_rpc.cairo index c07468b75..ac92d540e 100644 --- a/crates/contracts/src/kakarot_core/eth_rpc.cairo +++ b/crates/contracts/src/kakarot_core/eth_rpc.cairo @@ -1,9 +1,9 @@ -use contracts::account_contract::{IAccountDispatcher, IAccountDispatcherTrait}; -use contracts::kakarot_core::interface::IKakarotCore; -use contracts::kakarot_core::kakarot::{KakarotCore, KakarotCore::{KakarotCoreState}}; use core::num::traits::Zero; use core::starknet::get_tx_info; use core::starknet::{EthAddress, get_caller_address}; +use crate::account_contract::{IAccountDispatcher, IAccountDispatcherTrait}; +use crate::kakarot_core::interface::IKakarotCore; +use crate::kakarot_core::kakarot::{KakarotCore, KakarotCore::{KakarotCoreState}}; use evm::backend::starknet_backend; use evm::backend::validation::validate_eth_tx; use evm::model::{TransactionResult, Address}; @@ -216,8 +216,8 @@ fn is_view(self: @KakarotCore::ContractState) -> bool { #[cfg(test)] mod tests { - use contracts::kakarot_core::KakarotCore; - use contracts::kakarot_core::eth_rpc::IEthRPC; + use crate::kakarot_core::KakarotCore; + use crate::kakarot_core::eth_rpc::IEthRPC; use snforge_std::{start_cheat_chain_id_global, stop_cheat_chain_id_global}; use utils::constants::POW_2_53; @@ -264,4 +264,3 @@ mod tests { tear_down(); } } - diff --git a/crates/contracts/src/kakarot_core/kakarot.cairo b/crates/contracts/src/kakarot_core/kakarot.cairo index 9518afd14..30a297417 100644 --- a/crates/contracts/src/kakarot_core/kakarot.cairo +++ b/crates/contracts/src/kakarot_core/kakarot.cairo @@ -3,10 +3,6 @@ const INVOKE_ETH_CALL_FORBIDDEN: felt252 = 'KKT: Cannot invoke eth_call'; #[starknet::contract] pub mod KakarotCore { - use contracts::components::ownable::{ownable_component}; - use contracts::components::upgradeable::{IUpgradeable, upgradeable_component}; - use contracts::kakarot_core::eth_rpc; - use contracts::kakarot_core::interface::IKakarotCore; use core::num::traits::Zero; use core::starknet::event::EventEmitter; use core::starknet::storage::{ @@ -14,6 +10,10 @@ pub mod KakarotCore { StoragePointerWriteAccess }; use core::starknet::{EthAddress, ContractAddress, ClassHash, get_contract_address}; + use crate::components::ownable::{ownable_component}; + use crate::components::upgradeable::{IUpgradeable, upgradeable_component}; + use crate::kakarot_core::eth_rpc; + use crate::kakarot_core::interface::IKakarotCore; use evm::backend::starknet_backend; use utils::helpers::compute_starknet_address; diff --git a/crates/contracts/src/mocks/cairo1_helpers_fixture.cairo b/crates/contracts/src/mocks/cairo1_helpers_fixture.cairo index bd5ef60a4..1a00d76b5 100644 --- a/crates/contracts/src/mocks/cairo1_helpers_fixture.cairo +++ b/crates/contracts/src/mocks/cairo1_helpers_fixture.cairo @@ -1,6 +1,6 @@ #[starknet::contract] pub mod Cairo1HelpersFixture { - use contracts::cairo1_helpers::embeddable_impls; + use crate::cairo1_helpers::embeddable_impls; const VERSION: felt252 = 2; diff --git a/crates/contracts/src/storage.cairo b/crates/contracts/src/storage.cairo index 4ff139dfe..c2501e69d 100644 --- a/crates/contracts/src/storage.cairo +++ b/crates/contracts/src/storage.cairo @@ -1,4 +1,3 @@ -use contracts::account_contract::AccountContract::unsafe_new_contract_state as account_contract_state; use core::ops::DerefMut; use core::ops::SnapshotDeref; use core::starknet::storage::{ @@ -7,6 +6,7 @@ use core::starknet::storage::{ use core::starknet::storage_access::StorageBaseAddress; use core::starknet::syscalls::{storage_read_syscall, storage_write_syscall}; use core::starknet::{SyscallResult, Store, StorageAddress}; +use crate::account_contract::AccountContract::unsafe_new_contract_state as account_contract_state; use utils::utils::{pack_bytes, load_packed_bytes}; /// A wrapper type for the bytecode storage. Packing / unpacking is done transparently inside the @@ -87,8 +87,8 @@ impl StoreBytecode of Store { #[cfg(test)] mod tests { - use contracts::account_contract::AccountContract::unsafe_new_contract_state as account_contract_state; use core::starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; + use crate::account_contract::AccountContract::unsafe_new_contract_state as account_contract_state; use starknet::storage_access::Store; use starknet::storage_access::{ StorageBaseAddress, StorageAddress, storage_base_address_from_felt252 diff --git a/crates/contracts/src/test_contracts/test_upgradeable.cairo b/crates/contracts/src/test_contracts/test_upgradeable.cairo index 6ff3ce473..22cf19587 100644 --- a/crates/contracts/src/test_contracts/test_upgradeable.cairo +++ b/crates/contracts/src/test_contracts/test_upgradeable.cairo @@ -1,4 +1,4 @@ -use contracts::components::upgradeable::{upgradeable_component}; +use crate::components::upgradeable::{upgradeable_component}; use upgradeable_component::{UpgradeableImpl}; @@ -9,7 +9,7 @@ pub trait IMockContractUpgradeable { #[starknet::contract] pub mod MockContractUpgradeableV0 { - use contracts::components::upgradeable::{upgradeable_component}; + use crate::components::upgradeable::{upgradeable_component}; use super::IMockContractUpgradeable; component!(path: upgradeable_component, storage: upgradeable, event: UpgradeableEvent); @@ -38,7 +38,7 @@ pub mod MockContractUpgradeableV0 { #[starknet::contract] pub mod MockContractUpgradeableV1 { - use contracts::components::upgradeable::{upgradeable_component}; + use crate::components::upgradeable::{upgradeable_component}; use super::IMockContractUpgradeable; component!(path: upgradeable_component, storage: upgradeable, event: upgradeableEvent); @@ -64,8 +64,8 @@ pub mod MockContractUpgradeableV1 { #[cfg(test)] mod tests { - use contracts::components::upgradeable::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait}; use core::starknet::syscalls::{deploy_syscall}; + use crate::components::upgradeable::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait}; use snforge_std::{declare, DeclareResultTrait}; use starknet::{ClassHash}; use super::{IMockContractUpgradeableDispatcher, IMockContractUpgradeableDispatcherTrait}; diff --git a/crates/contracts/src/test_utils.cairo b/crates/contracts/src/test_utils.cairo index 933184115..d412068a2 100644 --- a/crates/contracts/src/test_utils.cairo +++ b/crates/contracts/src/test_utils.cairo @@ -1,10 +1,10 @@ -use contracts::account_contract::{IAccountDispatcher, IAccountDispatcherTrait}; -use contracts::kakarot_core::{ - interface::IExtendedKakarotCoreDispatcher, interface::IExtendedKakarotCoreDispatcherTrait -}; use core::result::ResultTrait; use core::starknet::syscalls::deploy_syscall; use core::starknet::{EthAddress, ContractAddress}; +use crate::account_contract::{IAccountDispatcher, IAccountDispatcherTrait}; +use crate::kakarot_core::{ + interface::IExtendedKakarotCoreDispatcher, interface::IExtendedKakarotCoreDispatcherTrait +}; use evm::model::{Address}; use evm::test_utils::{other_starknet_address, sequencer_evm_address, chain_id}; diff --git a/crates/contracts/src/uninitialized_account.cairo b/crates/contracts/src/uninitialized_account.cairo index d3516461e..46c4ea9e0 100644 --- a/crates/contracts/src/uninitialized_account.cairo +++ b/crates/contracts/src/uninitialized_account.cairo @@ -19,12 +19,12 @@ trait IAccount { #[starknet::contract] pub mod UninitializedAccount { - use contracts::components::ownable::ownable_component::InternalTrait; - use contracts::components::ownable::ownable_component; - use contracts::kakarot_core::interface::{IKakarotCoreDispatcher, IKakarotCoreDispatcherTrait}; use core::starknet::SyscallResultTrait; use core::starknet::syscalls::{library_call_syscall, replace_class_syscall}; use core::starknet::{ContractAddress, get_caller_address}; + use crate::components::ownable::ownable_component::InternalTrait; + use crate::components::ownable::ownable_component; + use crate::kakarot_core::interface::{IKakarotCoreDispatcher, IKakarotCoreDispatcherTrait}; // Add ownable component component!(path: ownable_component, storage: ownable, event: OwnableEvent); diff --git a/crates/evm/src/backend/starknet_backend.cairo b/crates/evm/src/backend/starknet_backend.cairo index 4382d5525..c5cba92c7 100644 --- a/crates/evm/src/backend/starknet_backend.cairo +++ b/crates/evm/src/backend/starknet_backend.cairo @@ -7,10 +7,10 @@ use core::starknet::storage::StoragePointerReadAccess; use core::starknet::syscalls::{deploy_syscall}; use core::starknet::syscalls::{emit_event_syscall}; use core::starknet::{EthAddress, get_block_info, SyscallResultTrait}; -use evm::errors::{ensure, EVMError}; -use evm::model::{Address, AddressTrait, Environment, Account, AccountTrait}; -use evm::model::{Transfer}; -use evm::state::{State, StateTrait}; +use crate::errors::{ensure, EVMError}; +use crate::model::{Address, AddressTrait, Environment, Account, AccountTrait}; +use crate::model::{Transfer}; +use crate::state::{State, StateTrait}; use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use utils::constants::BURN_ADDRESS; use utils::constants; @@ -247,14 +247,14 @@ fn commit_storage(ref self: State) -> Result<(), EVMError> { #[cfg(test)] mod tests { use core::starknet::ClassHash; - use evm::backend::starknet_backend; - use evm::model::Address; - use evm::model::account::Account; - use evm::state::{State, StateTrait}; - use evm::test_utils::{ + use crate::backend::starknet_backend; + use crate::model::Address; + use crate::model::account::Account; + use crate::state::{State, StateTrait}; + use crate::test_utils::{ setup_test_environment, uninitialized_account, account_contract, register_account }; - use evm::test_utils::{evm_address}; + use crate::test_utils::{evm_address}; use snforge_std::{test_address, start_mock_call, get_class_hash}; use snforge_utils::snforge_utils::{assert_not_called, assert_called}; use super::commit_storage; diff --git a/crates/evm/src/backend/validation.cairo b/crates/evm/src/backend/validation.cairo index 8384c6290..17b8da15c 100644 --- a/crates/evm/src/backend/validation.cairo +++ b/crates/evm/src/backend/validation.cairo @@ -4,7 +4,7 @@ use contracts::kakarot_core::eth_rpc::IEthRPC; use core::ops::SnapshotDeref; use core::starknet::storage::{StoragePointerReadAccess}; use core::starknet::{get_caller_address}; -use evm::gas; +use crate::gas; use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use starknet::storage::StorageTrait; use utils::eth_transaction::check_gas_fee; diff --git a/crates/evm/src/call_helpers.cairo b/crates/evm/src/call_helpers.cairo index df0d2a24a..61e67031d 100644 --- a/crates/evm/src/call_helpers.cairo +++ b/crates/evm/src/call_helpers.cairo @@ -4,13 +4,13 @@ use contracts::kakarot_core::interface::IKakarotCore; use core::cmp::min; use core::starknet::EthAddress; -use evm::errors::EVMError; -use evm::interpreter::EVMTrait; -use evm::memory::MemoryTrait; -use evm::model::vm::{VM, VMTrait}; -use evm::model::{Address, Message, ExecutionResultStatus}; -use evm::stack::StackTrait; -use evm::state::StateTrait; +use crate::errors::EVMError; +use crate::interpreter::EVMTrait; +use crate::memory::MemoryTrait; +use crate::model::vm::{VM, VMTrait}; +use crate::model::{Address, Message, ExecutionResultStatus}; +use crate::stack::StackTrait; +use crate::state::StateTrait; use utils::constants; use utils::set::SetTrait; use utils::traits::{BoolIntoNumeric, U256TryIntoResult}; diff --git a/crates/evm/src/create_helpers.cairo b/crates/evm/src/create_helpers.cairo index 010995f99..e324e17b7 100644 --- a/crates/evm/src/create_helpers.cairo +++ b/crates/evm/src/create_helpers.cairo @@ -1,16 +1,16 @@ use core::num::traits::Bounded; use core::num::traits::Zero; use core::starknet::EthAddress; -use evm::errors::{ensure, EVMError}; -use evm::gas; -use evm::interpreter::EVMTrait; -use evm::memory::MemoryTrait; -use evm::model::Message; -use evm::model::account::{Account, AccountTrait}; -use evm::model::vm::{VM, VMTrait}; -use evm::model::{ExecutionResult, ExecutionResultTrait, ExecutionResultStatus}; -use evm::stack::StackTrait; -use evm::state::StateTrait; +use crate::errors::{ensure, EVMError}; +use crate::gas; +use crate::interpreter::EVMTrait; +use crate::memory::MemoryTrait; +use crate::model::Message; +use crate::model::account::{Account, AccountTrait}; +use crate::model::vm::{VM, VMTrait}; +use crate::model::{ExecutionResult, ExecutionResultTrait, ExecutionResultStatus}; +use crate::stack::StackTrait; +use crate::state::StateTrait; use utils::address::{compute_contract_address, compute_create2_contract_address}; use utils::constants; use utils::helpers::ceil32; diff --git a/crates/evm/src/gas.cairo b/crates/evm/src/gas.cairo index 8d257c9b0..0a479e47c 100644 --- a/crates/evm/src/gas.cairo +++ b/crates/evm/src/gas.cairo @@ -1,6 +1,6 @@ use core::cmp::min; use core::num::traits::CheckedAdd; -use evm::errors::EVMError; +use crate::errors::EVMError; use utils::eth_transaction::common::TxKindTrait; use utils::eth_transaction::eip2930::{AccessListItem}; use utils::eth_transaction::transaction::{Transaction, TransactionTrait}; @@ -275,11 +275,11 @@ pub fn calculate_intrinsic_gas_cost(tx: @Transaction) -> u64 { mod tests { use core::starknet::EthAddress; - use evm::gas::{ + use crate::gas::{ calculate_intrinsic_gas_cost, calculate_memory_gas_cost, ACCESS_LIST_ADDRESS, ACCESS_LIST_STORAGE_KEY }; - use evm::test_utils::evm_address; + use crate::test_utils::evm_address; use utils::eth_transaction::eip2930::{AccessListItem, TxEip2930}; use utils::eth_transaction::legacy::TxLegacy; use utils::eth_transaction::transaction::Transaction; diff --git a/crates/evm/src/instructions/block_information.cairo b/crates/evm/src/instructions/block_information.cairo index bb5a3991e..f5e61db79 100644 --- a/crates/evm/src/instructions/block_information.cairo +++ b/crates/evm/src/instructions/block_information.cairo @@ -3,12 +3,12 @@ use core::starknet::SyscallResultTrait; use core::starknet::syscalls::get_block_hash_syscall; -use evm::errors::EVMError; +use crate::errors::EVMError; -use evm::gas; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; -use evm::state::StateTrait; +use crate::gas; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; +use crate::state::StateTrait; use utils::constants::MIN_BASE_FEE_PER_BLOB_GAS; use utils::traits::{EthAddressTryIntoResultContractAddress, EthAddressIntoU256}; @@ -140,12 +140,12 @@ pub impl BlockInformation of BlockInformationTrait { #[cfg(test)] mod tests { use core::result::ResultTrait; - use evm::instructions::BlockInformationTrait; - use evm::model::account::Account; - use evm::model::vm::VMTrait; - use evm::stack::StackTrait; - use evm::state::StateTrait; - use evm::test_utils::{VMBuilderTrait, gas_price, setup_test_environment}; + use crate::instructions::BlockInformationTrait; + use crate::model::account::Account; + use crate::model::vm::VMTrait; + use crate::stack::StackTrait; + use crate::state::StateTrait; + use crate::test_utils::{VMBuilderTrait, gas_price, setup_test_environment}; use snforge_std::{start_cheat_block_number_global, start_cheat_block_timestamp_global}; use utils::constants::EMPTY_KECCAK; use utils::constants; diff --git a/crates/evm/src/instructions/comparison_operations.cairo b/crates/evm/src/instructions/comparison_operations.cairo index 594bc0320..e99f9e079 100644 --- a/crates/evm/src/instructions/comparison_operations.cairo +++ b/crates/evm/src/instructions/comparison_operations.cairo @@ -1,9 +1,9 @@ use core::num::traits::Bounded; -use evm::errors::EVMError; -use evm::gas; -use evm::model::vm::{VM, VMTrait}; +use crate::errors::EVMError; +use crate::gas; +use crate::model::vm::{VM, VMTrait}; // Internal imports -use evm::stack::StackTrait; +use crate::stack::StackTrait; use utils::constants::{POW_2_127}; use utils::i256::i256; use utils::math::{Bitshift, WrappingBitshift}; @@ -198,9 +198,9 @@ pub impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { #[cfg(test)] mod tests { use core::num::traits::Bounded; - use evm::instructions::ComparisonAndBitwiseOperationsTrait; - use evm::stack::StackTrait; - use evm::test_utils::VMBuilderTrait; + use crate::instructions::ComparisonAndBitwiseOperationsTrait; + use crate::stack::StackTrait; + use crate::test_utils::VMBuilderTrait; #[test] fn test_eq_same_pair() { diff --git a/crates/evm/src/instructions/duplication_operations.cairo b/crates/evm/src/instructions/duplication_operations.cairo index 8aa3024b5..db322d326 100644 --- a/crates/evm/src/instructions/duplication_operations.cairo +++ b/crates/evm/src/instructions/duplication_operations.cairo @@ -1,10 +1,10 @@ //! Duplication Operations. // Internal imports -use evm::errors::EVMError; -use evm::gas; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; +use crate::errors::EVMError; +use crate::gas; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; /// Generic DUP operation #[inline(always)] @@ -115,10 +115,10 @@ pub impl DuplicationOperations of DuplicationOperationsTrait { #[cfg(test)] mod tests { - use evm::instructions::DuplicationOperationsTrait; - use evm::stack::Stack; - use evm::stack::StackTrait; - use evm::test_utils::VMBuilderTrait; + use crate::instructions::DuplicationOperationsTrait; + use crate::stack::Stack; + use crate::stack::StackTrait; + use crate::test_utils::VMBuilderTrait; // ensures all values start from index `from` upto index `to` of stack are `0x0` diff --git a/crates/evm/src/instructions/environmental_information.cairo b/crates/evm/src/instructions/environmental_information.cairo index 7936a6a8a..2661198fa 100644 --- a/crates/evm/src/instructions/environmental_information.cairo +++ b/crates/evm/src/instructions/environmental_information.cairo @@ -1,13 +1,13 @@ use core::num::traits::OverflowingAdd; use core::num::traits::Zero; -use evm::errors::{ensure, EVMError}; -use evm::gas; -use evm::memory::MemoryTrait; -use evm::model::account::{AccountTrait}; -use evm::model::vm::{VM, VMTrait}; -use evm::model::{AddressTrait}; -use evm::stack::StackTrait; -use evm::state::StateTrait; +use crate::errors::{ensure, EVMError}; +use crate::gas; +use crate::memory::MemoryTrait; +use crate::model::account::{AccountTrait}; +use crate::model::vm::{VM, VMTrait}; +use crate::model::{AddressTrait}; +use crate::stack::StackTrait; +use crate::state::StateTrait; use utils::helpers::{ceil32, load_word}; use utils::set::SetTrait; use utils::traits::{EthAddressIntoU256}; @@ -301,15 +301,15 @@ fn copy_bytes_to_memory( mod tests { use contracts::test_data::counter_evm_bytecode; use core::starknet::EthAddress; - use evm::errors::{EVMError, TYPE_CONVERSION_ERROR}; - use evm::instructions::EnvironmentInformationTrait; - use evm::memory::{InternalMemoryTrait, MemoryTrait}; - - use evm::model::vm::VMTrait; - use evm::model::{Account, Address}; - use evm::stack::StackTrait; - use evm::state::StateTrait; - use evm::test_utils::{VMBuilderTrait, origin, callvalue, gas_price}; + use crate::errors::{EVMError, TYPE_CONVERSION_ERROR}; + use crate::instructions::EnvironmentInformationTrait; + use crate::memory::{InternalMemoryTrait, MemoryTrait}; + + use crate::model::vm::VMTrait; + use crate::model::{Account, Address}; + use crate::stack::StackTrait; + use crate::state::StateTrait; + use crate::test_utils::{VMBuilderTrait, origin, callvalue, gas_price}; use snforge_std::test_address; use utils::constants::EMPTY_KECCAK; use utils::helpers::{u256_to_bytes_array, compute_starknet_address}; @@ -319,8 +319,8 @@ mod tests { mod test_internals { - use evm::memory::MemoryTrait; - use evm::test_utils::VMBuilderTrait; + use crate::memory::MemoryTrait; + use crate::test_utils::VMBuilderTrait; use super::super::copy_bytes_to_memory; fn test_copy_bytes_to_memory_helper( diff --git a/crates/evm/src/instructions/exchange_operations.cairo b/crates/evm/src/instructions/exchange_operations.cairo index 4b6f458e3..349e0f3c1 100644 --- a/crates/evm/src/instructions/exchange_operations.cairo +++ b/crates/evm/src/instructions/exchange_operations.cairo @@ -1,9 +1,9 @@ //! Exchange Operations. -use evm::errors::EVMError; -use evm::gas; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; +use crate::errors::EVMError; +use crate::gas; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; /// Place i bytes items on stack. #[inline(always)] @@ -131,9 +131,9 @@ pub impl ExchangeOperations of ExchangeOperationsTrait { #[cfg(test)] mod tests { - use evm::instructions::exchange_operations::ExchangeOperationsTrait; - use evm::stack::StackTrait; - use evm::test_utils::VMBuilderTrait; + use crate::instructions::exchange_operations::ExchangeOperationsTrait; + use crate::stack::StackTrait; + use crate::test_utils::VMBuilderTrait; #[test] diff --git a/crates/evm/src/instructions/logging_operations.cairo b/crates/evm/src/instructions/logging_operations.cairo index 66cb952fa..6e8b1cd4a 100644 --- a/crates/evm/src/instructions/logging_operations.cairo +++ b/crates/evm/src/instructions/logging_operations.cairo @@ -1,12 +1,12 @@ //! Logging Operations. -use evm::errors::{EVMError, ensure}; -use evm::gas; -use evm::memory::MemoryTrait; -use evm::model::Event; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; -use evm::state::StateTrait; +use crate::errors::{EVMError, ensure}; +use crate::gas; +use crate::memory::MemoryTrait; +use crate::model::Event; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; +use crate::state::StateTrait; #[generate_trait] @@ -87,10 +87,10 @@ fn exec_log_i(ref self: VM, topics_len: u8) -> Result<(), EVMError> { mod tests { use core::num::traits::Bounded; use core::result::ResultTrait; - use evm::errors::{EVMError, TYPE_CONVERSION_ERROR}; - use evm::instructions::LoggingOperationsTrait; - use evm::stack::StackTrait; - use evm::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait}; + use crate::errors::{EVMError, TYPE_CONVERSION_ERROR}; + use crate::instructions::LoggingOperationsTrait; + use crate::stack::StackTrait; + use crate::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait}; use utils::helpers::u256_to_bytes_array; #[test] diff --git a/crates/evm/src/instructions/memory_operations.cairo b/crates/evm/src/instructions/memory_operations.cairo index b506815fe..cecc865a6 100644 --- a/crates/evm/src/instructions/memory_operations.cairo +++ b/crates/evm/src/instructions/memory_operations.cairo @@ -1,12 +1,12 @@ use core::cmp::max; -use evm::backend::starknet_backend::fetch_original_storage; +use crate::backend::starknet_backend::fetch_original_storage; //! Stack Memory Storage and Flow Operations. -use evm::errors::{EVMError, ensure}; -use evm::gas; -use evm::memory::MemoryTrait; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; -use evm::state::StateTrait; +use crate::errors::{EVMError, ensure}; +use crate::gas; +use crate::memory::MemoryTrait; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; +use crate::state::StateTrait; use utils::helpers::ceil32; use utils::set::SetTrait; @@ -305,16 +305,16 @@ mod tests { use core::cmp::max; use core::num::traits::Bounded; use core::result::ResultTrait; - use evm::errors::EVMError; - use evm::gas; - use evm::instructions::MemoryOperationTrait; - use evm::memory::MemoryTrait; - use evm::model::Address; - use evm::model::vm::VMTrait; - use evm::model::{Account, AccountTrait}; - use evm::stack::StackTrait; - use evm::state::StateTrait; - use evm::test_utils::{ + use crate::errors::EVMError; + use crate::gas; + use crate::instructions::MemoryOperationTrait; + use crate::memory::MemoryTrait; + use crate::model::Address; + use crate::model::vm::VMTrait; + use crate::model::{Account, AccountTrait}; + use crate::stack::StackTrait; + use crate::state::StateTrait; + use crate::test_utils::{ VMBuilderTrait, MemoryTestUtilsTrait, setup_test_environment, uninitialized_account, native_token }; diff --git a/crates/evm/src/instructions/push_operations.cairo b/crates/evm/src/instructions/push_operations.cairo index ef6bdd8e2..31a53a698 100644 --- a/crates/evm/src/instructions/push_operations.cairo +++ b/crates/evm/src/instructions/push_operations.cairo @@ -1,9 +1,9 @@ //! Push Operations. -use evm::errors::EVMError; -use evm::gas; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; +use crate::errors::EVMError; +use crate::gas; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; use utils::traits::bytes::{FromBytes, U8SpanExTrait}; /// Place i bytes items on stack. @@ -278,11 +278,11 @@ pub impl PushOperations of PushOperationsTrait { #[cfg(test)] mod tests { - use evm::gas; - use evm::instructions::PushOperationsTrait; - use evm::model::vm::VMTrait; - use evm::stack::StackTrait; - use evm::test_utils::{VMBuilderTrait}; + use crate::gas; + use crate::instructions::PushOperationsTrait; + use crate::model::vm::VMTrait; + use crate::stack::StackTrait; + use crate::test_utils::{VMBuilderTrait}; use super::exec_push_i; #[test] diff --git a/crates/evm/src/instructions/sha3.cairo b/crates/evm/src/instructions/sha3.cairo index c0f1e7041..e04e36590 100644 --- a/crates/evm/src/instructions/sha3.cairo +++ b/crates/evm/src/instructions/sha3.cairo @@ -3,11 +3,11 @@ use core::cmp::min; use core::keccak::{cairo_keccak}; // Internal imports -use evm::errors::EVMError; -use evm::gas; -use evm::memory::MemoryTrait; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; +use crate::errors::EVMError; +use crate::gas; +use crate::memory::MemoryTrait; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; use utils::helpers::ceil32; use utils::traits::array::ArrayExtTrait; use utils::traits::integer::U256Trait; @@ -147,11 +147,11 @@ fn prepare_last_input(ref to_hash: Array, value: u256, size: u32) -> u64 { #[cfg(test)] mod tests { - use evm::instructions::Sha3Trait; - use evm::instructions::sha3; - use evm::memory::MemoryTrait; - use evm::stack::StackTrait; - use evm::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait}; + use crate::instructions::Sha3Trait; + use crate::instructions::sha3; + use crate::memory::MemoryTrait; + use crate::stack::StackTrait; + use crate::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait}; #[test] fn test_exec_sha3_size_0_offset_0() { diff --git a/crates/evm/src/instructions/stop_and_arithmetic_operations.cairo b/crates/evm/src/instructions/stop_and_arithmetic_operations.cairo index 42542ea51..70c288c03 100644 --- a/crates/evm/src/instructions/stop_and_arithmetic_operations.cairo +++ b/crates/evm/src/instructions/stop_and_arithmetic_operations.cairo @@ -1,10 +1,10 @@ //! Stop and Arithmetic Operations. use core::integer::{u512_safe_div_rem_by_u256}; use core::num::traits::{OverflowingAdd, OverflowingMul, OverflowingSub}; -use evm::errors::EVMError; -use evm::gas; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; +use crate::errors::EVMError; +use crate::gas; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; use utils::i256::i256; use utils::math::{Exponentiation, WrappingExponentiation, u256_wide_add}; use utils::traits::integer::BytesUsedTrait; @@ -265,10 +265,10 @@ pub impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { mod tests { use core::num::traits::Bounded; use core::result::ResultTrait; - use evm::instructions::StopAndArithmeticOperationsTrait; - use evm::model::vm::VMTrait; - use evm::stack::StackTrait; - use evm::test_utils::VMBuilderTrait; + use crate::instructions::StopAndArithmeticOperationsTrait; + use crate::model::vm::VMTrait; + use crate::stack::StackTrait; + use crate::test_utils::VMBuilderTrait; #[test] diff --git a/crates/evm/src/instructions/system_operations.cairo b/crates/evm/src/instructions/system_operations.cairo index 2fd210559..c15f55bf3 100644 --- a/crates/evm/src/instructions/system_operations.cairo +++ b/crates/evm/src/instructions/system_operations.cairo @@ -1,13 +1,13 @@ -use evm::call_helpers::CallHelpers; -use evm::create_helpers::{CreateHelpers, CreateType}; -use evm::errors::{ensure, EVMError}; -use evm::gas; -use evm::memory::MemoryTrait; -use evm::model::Transfer; -use evm::model::account::{AccountTrait}; -use evm::model::vm::{VM, VMTrait}; -use evm::stack::StackTrait; -use evm::state::StateTrait; +use crate::call_helpers::CallHelpers; +use crate::create_helpers::{CreateHelpers, CreateType}; +use crate::errors::{ensure, EVMError}; +use crate::gas; +use crate::memory::MemoryTrait; +use crate::model::Transfer; +use crate::model::account::{AccountTrait}; +use crate::model::vm::{VM, VMTrait}; +use crate::stack::StackTrait; +use crate::state::StateTrait; use utils::set::SetTrait; #[generate_trait] @@ -371,16 +371,16 @@ mod tests { use core::result::ResultTrait; use core::starknet::EthAddress; use core::traits::TryInto; - use evm::call_helpers::CallHelpersImpl; - use evm::instructions::MemoryOperationTrait; - use evm::instructions::SystemOperationsTrait; - use evm::interpreter::{EVMTrait}; - use evm::model::account::{Account}; - use evm::model::vm::VMTrait; - use evm::model::{AccountTrait, Address}; - use evm::stack::StackTrait; - use evm::state::{StateTrait}; - use evm::test_utils::{ + use crate::call_helpers::CallHelpersImpl; + use crate::instructions::MemoryOperationTrait; + use crate::instructions::SystemOperationsTrait; + use crate::interpreter::{EVMTrait}; + use crate::model::account::{Account}; + use crate::model::vm::VMTrait; + use crate::model::{AccountTrait, Address}; + use crate::stack::StackTrait; + use crate::state::{StateTrait}; + use crate::test_utils::{ VMBuilderTrait, MemoryTestUtilsTrait, native_token, evm_address, setup_test_environment, origin, uninitialized_account }; diff --git a/crates/evm/src/interpreter.cairo b/crates/evm/src/interpreter.cairo index 985079c72..38c2fd9c8 100644 --- a/crates/evm/src/interpreter.cairo +++ b/crates/evm/src/interpreter.cairo @@ -4,26 +4,26 @@ use core::num::traits::{Bounded, Zero}; use core::ops::SnapshotDeref; use core::starknet::EthAddress; use core::starknet::storage::{StoragePointerReadAccess}; -use evm::backend::starknet_backend; -use evm::create_helpers::CreateHelpers; -use evm::errors::{EVMError, EVMErrorTrait}; +use crate::backend::starknet_backend; +use crate::create_helpers::CreateHelpers; +use crate::errors::{EVMError, EVMErrorTrait}; -use evm::instructions::{ +use crate::instructions::{ ExchangeOperationsTrait, LoggingOperationsTrait, StopAndArithmeticOperationsTrait, ComparisonAndBitwiseOperationsTrait, SystemOperationsTrait, BlockInformationTrait, DuplicationOperationsTrait, EnvironmentInformationTrait, PushOperationsTrait, MemoryOperationTrait, Sha3Trait }; -use evm::model::account::{Account, AccountTrait}; -use evm::model::vm::{VM, VMTrait}; -use evm::model::{ +use crate::model::account::{Account, AccountTrait}; +use crate::model::vm::{VM, VMTrait}; +use crate::model::{ Message, Environment, Transfer, ExecutionSummary, ExecutionResult, ExecutionResultTrait, ExecutionResultStatus, AddressTrait, TransactionResult, TransactionResultTrait, Address }; -use evm::precompiles::Precompiles; -use evm::precompiles::eth_precompile_addresses; -use evm::state::StateTrait; +use crate::precompiles::Precompiles; +use crate::precompiles::eth_precompile_addresses; +use crate::state::StateTrait; use utils::address::compute_contract_address; use utils::constants; use utils::eth_transaction::common::TxKind; @@ -1019,9 +1019,9 @@ pub impl EVMImpl of EVMTrait { mod tests { use contracts::kakarot_core::KakarotCore; use core::num::traits::Zero; - use evm::model::{Account, Environment, Message}; - use evm::state::StateTrait; - use evm::test_utils::{dual_origin, test_dual_address}; + use crate::model::{Account, Environment, Message}; + use crate::state::StateTrait; + use crate::test_utils::{dual_origin, test_dual_address}; use super::EVMTrait; use utils::constants::EMPTY_KECCAK; use utils::eth_transaction::common::TxKind; diff --git a/crates/evm/src/memory.cairo b/crates/evm/src/memory.cairo index 40458c324..b24ec7ca7 100644 --- a/crates/evm/src/memory.cairo +++ b/crates/evm/src/memory.cairo @@ -8,10 +8,6 @@ use utils::constants::{ use utils::traits::array::ArrayExtTrait; use utils::{helpers, math::Bitshift}; -// 2**17 -const MEMORY_SEGMENT_SIZE: usize = 131072; - - #[derive(Destruct, Default)] pub struct Memory { items: Felt252Dict, @@ -47,10 +43,6 @@ impl MemoryImpl of MemoryTrait { /// /// If the offset is aligned with the 16-bytes words in memory, the element is stored directly. /// Otherwise, the element is split and stored in multiple words. - /// - /// If we want to store an item at offset Y of the memory relative to the execution context of - /// id i the internal index will be: - /// index = Y + i * MEMORY_SEGMENT_SIZE #[inline(always)] fn store(ref self: Memory, element: u256, offset: usize) { let nonzero_16: NonZero = 16_u32.try_into().unwrap(); @@ -76,9 +68,6 @@ impl MemoryImpl of MemoryTrait { /// Stores a single byte into memory at a specified offset. - /// If we want to store a byte at offset Y of the memory relative to the execution context of id - /// i the internal index will be: - /// index = Y + i * MEMORY_SEGMENT_SIZE /// /// # Arguments /// @@ -89,15 +78,11 @@ impl MemoryImpl of MemoryTrait { fn store_byte(ref self: Memory, value: u8, offset: usize) { let nonzero_16: NonZero = 16_u32.try_into().unwrap(); - // Compute actual offset in Memory, given active_segment of Memory (current Execution - // Context id) - // And Memory Segment Size - // Get offset's memory word index and left-based offset of byte in word. let (chunk_index, left_offset) = u32_safe_divmod(offset, nonzero_16); // As the memory words are in big-endian order, we need to convert our left-based offset - // to a right-based one.a + // to a right-based one. let right_offset = 15 - left_offset; let mask: u128 = 0xFF * helpers::pow2(right_offset.into() * 8); @@ -116,10 +101,6 @@ impl MemoryImpl of MemoryTrait { /// stores the first word using the `store_first_word` function, the aligned words using the /// `store_aligned_words` function, and the last word using the `store_last_word` function. /// - /// If we want to store n bytes at offset Y of the memory relative to the execution context of - /// id i the internal index will be: - /// index = Y + i * MEMORY_SEGMENT_SIZE - /// /// # Arguments /// /// * `self` - A mutable reference to the `Memory` instance to store the bytes in. @@ -174,7 +155,7 @@ impl MemoryImpl of MemoryTrait { /// /// # Arguments /// - /// * `self` - The `Memory` instance to store the bytes in. + /// * `self` - A mutable reference to the `Memory` instance to store the bytes in. /// * `offset` - The offset within memory to store the bytes at. /// * `length` - The length of bytes to store in memory. /// * `source` - A span of bytes to store in memory. @@ -202,6 +183,11 @@ impl MemoryImpl of MemoryTrait { } /// Ensures that the memory is at least `length` bytes long. Expands if necessary. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `Memory` instance. + /// * `length` - The desired minimum length of the memory. #[inline(always)] fn ensure_length(ref self: Memory, length: usize) { if self.size() < length { @@ -212,7 +198,14 @@ impl MemoryImpl of MemoryTrait { } /// Expands memory if necessary, then load 32 bytes from it at the given offset. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `Memory` instance. + /// * `offset` - The offset within memory to load from. + /// /// # Returns + /// /// * `u256` - The loaded value. #[inline(always)] fn load(ref self: Memory, offset: usize) -> u256 { @@ -221,12 +214,26 @@ impl MemoryImpl of MemoryTrait { /// Expands memory if necessary, then load elements_len bytes from the memory at given offset /// inside elements. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `Memory` instance. + /// * `elements_len` - The number of bytes to load. + /// * `elements` - A mutable reference to the array to store the loaded bytes. + /// * `offset` - The offset within memory to load from. #[inline(always)] fn load_n(ref self: Memory, elements_len: usize, ref elements: Array, offset: usize) { self.load_n_internal(elements_len, ref elements, offset); } /// Copies a segment of memory from the source offset to the destination offset. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `Memory` instance. + /// * `size` - The number of bytes to copy. + /// * `source_offset` - The offset to copy from. + /// * `dest_offset` - The offset to copy to. #[inline(always)] fn copy(ref self: Memory, size: usize, source_offset: usize, dest_offset: usize) { let mut data: Array = Default::default(); @@ -281,10 +288,8 @@ pub(crate) impl InternalMemoryMethods of InternalMemoryTrait { /// Stores a span of bytes into a single memory chunk. /// - /// This function computes new word to be stored by multiplying the - /// high part of the current word by the `mask_i` value, adding the loaded bytes multiplied by - /// the `mask_f` - /// value, and adding the low part of the current word. + /// This function computes a new word to be stored by combining the existing word with the new + /// bytes. /// /// # Arguments /// @@ -621,7 +626,7 @@ impl Felt252DictExtensionImpl of Felt252DictExtension { #[cfg(test)] mod tests { use core::num::traits::Bounded; - use evm::memory::{MemoryTrait, InternalMemoryTrait}; + use crate::memory::{MemoryTrait, InternalMemoryTrait}; use utils::constants::{POW_2_8, POW_2_56, POW_2_64, POW_2_120}; use utils::{ math::Exponentiation, math::WrappingExponentiation, helpers, traits::array::SpanExtTrait diff --git a/crates/evm/src/model.cairo b/crates/evm/src/model.cairo index 66954af9a..fb217dfae 100644 --- a/crates/evm/src/model.cairo +++ b/crates/evm/src/model.cairo @@ -5,64 +5,111 @@ pub use vm::{VM, VMTrait}; use contracts::kakarot_core::{KakarotCore, IKakarotCore}; use core::num::traits::{CheckedSub, Zero}; use core::starknet::{EthAddress, ContractAddress}; -use evm::errors::EVMError; -use evm::precompiles::{ +use crate::errors::EVMError; +use crate::precompiles::{ FIRST_ROLLUP_PRECOMPILE_ADDRESS, FIRST_ETHEREUM_PRECOMPILE_ADDRESS, LAST_ETHEREUM_PRECOMPILE_ADDRESS }; -use evm::state::State; +use crate::state::State; use utils::fmt::{TSpanSetDebug}; use utils::set::SpanSet; use utils::traits::{EthAddressDefault, ContractAddressDefault, SpanDefault}; +/// Represents the execution environment for EVM transactions. #[derive(Destruct, Default)] pub struct Environment { + /// The origin address of the transaction. pub origin: Address, + /// The gas price for the transaction. pub gas_price: u128, + /// The chain ID of the network. pub chain_id: u64, + /// The previous RANDAO value. pub prevrandao: u256, + /// The current block number. pub block_number: u64, + /// The gas limit for the current block. pub block_gas_limit: u64, + /// The timestamp of the current block. pub block_timestamp: u64, + /// The address of the coinbase. pub coinbase: EthAddress, + /// The base fee for the current block. pub base_fee: u64, + /// The state of the EVM. pub state: State } + +/// Represents a message call in the EVM. #[derive(Copy, Drop, Default, PartialEq, Debug)] pub struct Message { + /// The address of the caller. pub caller: Address, + /// The target address of the call. pub target: Address, + /// The gas limit for the call. pub gas_limit: u64, + /// The data passed to the call. pub data: Span, + /// The code of the contract being called. pub code: Span, + /// The address of the code being executed. pub code_address: Address, + /// The value sent with the call. pub value: u256, + /// Whether the value should be transferred. pub should_transfer_value: bool, + /// The depth of the call stack. pub depth: usize, + /// Whether the call is read-only. pub read_only: bool, + /// Set of accessed addresses during execution. pub accessed_addresses: SpanSet, + /// Set of accessed storage keys during execution. pub accessed_storage_keys: SpanSet<(EthAddress, u256)>, } +/// Represents the result of an EVM execution. #[derive(Drop, Debug)] pub struct ExecutionResult { + /// The status of the execution result. pub status: ExecutionResultStatus, + /// The return data of the execution. pub return_data: Span, + /// The remaining gas after execution. pub gas_left: u64, + /// Set of accessed addresses during execution. pub accessed_addresses: SpanSet, + /// Set of accessed storage keys during execution. pub accessed_storage_keys: SpanSet<(EthAddress, u256)>, + /// The amount of gas refunded during execution. pub gas_refund: u64, } +/// Represents the status of an EVM execution result. #[derive(Copy, Drop, PartialEq, Debug)] pub enum ExecutionResultStatus { + /// The execution was successful. Success, + /// The execution was reverted. Revert, + /// An exception occurred during execution. Exception, } #[generate_trait] pub impl ExecutionResultImpl of ExecutionResultTrait { + /// Creates an `ExecutionResult` for an exceptional failure. + /// + /// # Arguments + /// + /// * `error` - The error message as a span of bytes. + /// * `accessed_addresses` - Set of accessed addresses during execution. + /// * `accessed_storage_keys` - Set of accessed storage keys during execution. + /// + /// # Returns + /// + /// An `ExecutionResult` with the Exception status and provided data. fn exceptional_failure( error: Span, accessed_addresses: SpanSet, @@ -79,45 +126,87 @@ pub impl ExecutionResultImpl of ExecutionResultTrait { } /// Decrements the gas_left field of the current execution context by the value amount. - /// # Error : returns `EVMError::OutOfGas` if gas_left - value < 0 + /// + /// # Arguments + /// + /// * `value` - The amount of gas to charge. + /// + /// # Returns + /// + /// `Ok(())` if successful, or `Err(EVMError::OutOfGas)` if there's not enough gas. #[inline(always)] fn charge_gas(ref self: ExecutionResult, value: u64) -> Result<(), EVMError> { self.gas_left = self.gas_left.checked_sub(value).ok_or(EVMError::OutOfGas)?; Result::Ok(()) } + /// Checks if the execution result status is Success. + /// + /// # Returns + /// + /// `true` if the status is Success, `false` otherwise. fn is_success(self: @ExecutionResult) -> bool { *self.status == ExecutionResultStatus::Success } + /// Checks if the execution result status is Exception. + /// + /// # Returns + /// + /// `true` if the status is Exception, `false` otherwise. fn is_exception(self: @ExecutionResult) -> bool { *self.status == ExecutionResultStatus::Exception } + /// Checks if the execution result status is Revert. + /// + /// # Returns + /// + /// `true` if the status is Revert, `false` otherwise. fn is_revert(self: @ExecutionResult) -> bool { *self.status == ExecutionResultStatus::Revert } } +/// Represents a summary of an EVM execution. #[derive(Destruct)] pub struct ExecutionSummary { + /// The status of the execution result. pub status: ExecutionResultStatus, + /// The return data of the execution. pub return_data: Span, + /// The remaining gas after execution. pub gas_left: u64, + /// The state of the EVM after execution. pub state: State, + /// The amount of gas refunded during execution. pub gas_refund: u64 } - +/// Represents the result of an EVM transaction. pub struct TransactionResult { + /// Whether the transaction was successful. pub success: bool, + /// The return data of the transaction. pub return_data: Span, + /// The amount of gas used by the transaction. pub gas_used: u64, + /// The state of the EVM after the transaction. pub state: State } #[generate_trait] pub impl TransactionResultImpl of TransactionResultTrait { + /// Creates a `TransactionResult` for an exceptional failure. + /// + /// # Arguments + /// + /// * `error` - The error message as a span of bytes. + /// * `gas_used` - The amount of gas used during the transaction. + /// + /// # Returns + /// + /// A `TransactionResult` with failure status and provided data. fn exceptional_failure(error: Span, gas_used: u64) -> TransactionResult { TransactionResult { success: false, return_data: error, gas_used, state: Default::default() @@ -125,20 +214,24 @@ pub impl TransactionResultImpl of TransactionResultTrait { } } -/// The struct representing an EVM event. +/// Represents an EVM event. #[derive(Drop, Clone, Default, PartialEq)] pub struct Event { + /// The keys of the event. pub keys: Array, + /// The data of the event. pub data: Array, } +/// Represents an address in both EVM and Starknet formats. #[derive(Copy, Drop, PartialEq, Default, Debug)] pub struct Address { + /// The EVM address. pub evm: EthAddress, + /// The Starknet address. pub starknet: ContractAddress, } - impl ZeroAddress of core::num::traits::Zero
{ fn zero() -> Address { Address { evm: Zero::zero(), starknet: Zero::zero(), } @@ -153,13 +246,22 @@ impl ZeroAddress of core::num::traits::Zero
{ #[generate_trait] pub impl AddressImpl of AddressTrait { + /// Checks if the EVM address is deployed. + /// + /// # Returns + /// + /// `true` if the address is deployed, `false` otherwise. fn is_deployed(self: @EthAddress) -> bool { let mut kakarot_state = KakarotCore::unsafe_new_contract_state(); let address = kakarot_state.address_registry(*self); return address.is_non_zero(); } - /// Check whether an address for a call-family opcode is a precompile. + /// Checks if the address is a precompile for a call-family opcode. + /// + /// # Returns + /// + /// `true` if the address is a precompile, `false` otherwise. fn is_precompile(self: EthAddress) -> bool { let self: felt252 = self.into(); return self != 0x00 @@ -169,20 +271,22 @@ pub impl AddressImpl of AddressTrait { } } -/// A struct to save native token transfers to be made when finalizing -/// a tx +/// Represents a native token transfer to be made when finalizing a transaction. #[derive(Copy, Drop, PartialEq, Debug)] pub struct Transfer { + /// The sender of the transfer. pub sender: Address, + /// The recipient of the transfer. pub recipient: Address, + /// The amount of tokens to transfer. pub amount: u256 } #[cfg(test)] mod tests { mod test_is_deployed { - use evm::model::AddressTrait; - use evm::test_utils; + use crate::model::AddressTrait; + use crate::test_utils; use snforge_std::test_address; use utils::helpers::compute_starknet_address; @@ -217,7 +321,7 @@ mod tests { } mod test_is_precompile { use core::starknet::EthAddress; - use evm::model::{AddressTrait}; + use crate::model::{AddressTrait}; #[test] fn test_is_precompile() { // Given diff --git a/crates/evm/src/model/account.cairo b/crates/evm/src/model/account.cairo index 0d407a627..f61590923 100644 --- a/crates/evm/src/model/account.cairo +++ b/crates/evm/src/model/account.cairo @@ -3,8 +3,8 @@ use contracts::kakarot_core::{KakarotCore, IKakarotCore}; use core::dict::{Felt252Dict, Felt252DictTrait}; use core::num::traits::Zero; use core::starknet::{ContractAddress, EthAddress}; -use evm::backend::starknet_backend::fetch_balance; -use evm::model::Address; +use crate::backend::starknet_backend::fetch_balance; +use crate::model::Address; use utils::constants::EMPTY_KECCAK; use utils::traits::bytes::U8SpanExTrait; @@ -276,7 +276,7 @@ pub impl AccountImpl of AccountTrait { #[cfg(test)] mod tests { mod test_has_code_or_nonce { - use evm::model::account::{Account, AccountTrait, Address}; + use crate::model::account::{Account, AccountTrait, Address}; use utils::constants::EMPTY_KECCAK; use utils::traits::bytes::U8SpanExTrait; @@ -329,8 +329,8 @@ mod tests { } mod test_fetch { - use evm::model::account::{Account, AccountTrait, Address}; - use evm::test_utils::{ + use crate::model::account::{Account, AccountTrait, Address}; + use crate::test_utils::{ register_account, setup_test_environment, uninitialized_account, evm_address, native_token, }; @@ -388,8 +388,8 @@ mod tests { } mod test_fetch_or_create { - use evm::model::account::{Account, AccountTrait, Address}; - use evm::test_utils::{ + use crate::model::account::{Account, AccountTrait, Address}; + use crate::test_utils::{ register_account, setup_test_environment, uninitialized_account, evm_address, native_token, }; diff --git a/crates/evm/src/model/vm.cairo b/crates/evm/src/model/vm.cairo index 3067f3efb..d7704918b 100644 --- a/crates/evm/src/model/vm.cairo +++ b/crates/evm/src/model/vm.cairo @@ -2,10 +2,10 @@ use core::cmp::min; use core::dict::{Felt252Dict, Felt252DictTrait}; use core::num::traits::{SaturatingSub, CheckedSub}; use core::starknet::EthAddress; -use evm::errors::EVMError; -use evm::memory::Memory; -use evm::model::{Message, Environment, ExecutionResultStatus, ExecutionResult, AccountTrait}; -use evm::stack::Stack; +use crate::errors::EVMError; +use crate::memory::Memory; +use crate::model::{Message, Environment, ExecutionResultStatus, ExecutionResult, AccountTrait}; +use crate::stack::Stack; use utils::set::{Set, SetTrait, SpanSet, SpanSetTrait}; use utils::traits::{SpanDefault}; @@ -178,10 +178,10 @@ pub impl VMImpl of VMTrait { #[cfg(test)] mod tests { - use evm::errors::EVMError; - use evm::model::Message; - use evm::model::vm::VMTrait; - use evm::test_utils::{tx_gas_limit, VMBuilderTrait}; + use crate::errors::EVMError; + use crate::model::Message; + use crate::model::vm::VMTrait; + use crate::test_utils::{tx_gas_limit, VMBuilderTrait}; #[test] fn test_vm_default() { diff --git a/crates/evm/src/precompiles.cairo b/crates/evm/src/precompiles.cairo index 150917b61..a467a7b60 100644 --- a/crates/evm/src/precompiles.cairo +++ b/crates/evm/src/precompiles.cairo @@ -1,15 +1,9 @@ mod blake2f; - mod ec_operations; - mod ec_recover; - mod identity; - mod modexp; - mod p256verify; - mod sha256; pub use blake2f::Blake2f; @@ -23,17 +17,26 @@ pub use sha256::Sha256; use core::starknet::EthAddress; use core::traits::Into; -use evm::errors::EVMError; -use evm::model::vm::VM; -use evm::model::vm::VMTrait; - +use crate::errors::EVMError; +use crate::model::vm::VM; +use crate::model::vm::VMTrait; use utils::set::{Set, SetTrait}; +/// The starting address for Ethereum precompiles. pub const FIRST_ETHEREUM_PRECOMPILE_ADDRESS: u256 = 0x01; + +/// The ending address for Ethereum precompiles (inclusive). pub const LAST_ETHEREUM_PRECOMPILE_ADDRESS: u256 = 0x0a; + +/// The starting address for Rollup precompiles. pub const FIRST_ROLLUP_PRECOMPILE_ADDRESS: u256 = 0x100; +/// Returns a set of Ethereum precompile addresses. +/// +/// # Returns +/// +/// * `Set` - A set containing all Ethereum precompile addresses. pub fn eth_precompile_addresses() -> Set { let mut precompile_addresses: Array = array![]; //TODO(2.8) use range operator @@ -46,13 +49,40 @@ pub fn eth_precompile_addresses() -> Set { } +/// Trait for implementing precompiles. pub trait Precompile { + /// Returns the address of the precompile. + /// + /// # Returns + /// + /// * `EthAddress` - The address of the precompile. fn address() -> EthAddress; + + /// Executes the precompile with the given input. + /// + /// # Arguments + /// + /// * `input` - A span of bytes representing the input data. + /// + /// # Returns + /// + /// * `Result<(u64, Span), EVMError>` - A tuple containing the gas used and the output data, + /// or an error if the execution failed. fn exec(input: Span) -> Result<(u64, Span), EVMError>; } #[generate_trait] pub impl PrecompilesImpl of Precompiles { + /// Executes a precompile contract based on the current VM state. + /// + /// # Arguments + /// + /// * `ref vm` - A mutable reference to the VM instance. + /// + /// # Returns + /// + /// * `Result<(), EVMError>` - Ok if the precompile execution was successful, or an error if it + /// failed. fn exec_precompile(ref vm: VM) -> Result<(), EVMError> { let precompile_address = vm.message.code_address.evm; let input = vm.message().data; diff --git a/crates/evm/src/precompiles/blake2f.cairo b/crates/evm/src/precompiles/blake2f.cairo index 1de0b0914..94ecdd935 100644 --- a/crates/evm/src/precompiles/blake2f.cairo +++ b/crates/evm/src/precompiles/blake2f.cairo @@ -2,8 +2,8 @@ use core::array::ArrayTrait; use core::option::OptionTrait; use core::starknet::EthAddress; -use evm::errors::{EVMError, ensure}; -use evm::precompiles::Precompile; +use crate::errors::{EVMError, ensure}; +use crate::precompiles::Precompile; use utils::crypto::blake2_compress::compress; use utils::traits::bytes::{FromBytes, ToBytes}; @@ -83,19 +83,19 @@ pub impl Blake2f of Precompile { #[cfg(test)] mod tests { use core::array::SpanTrait; - use evm::errors::EVMError; - use evm::instructions::MemoryOperationTrait; - use evm::instructions::SystemOperationsTrait; - use evm::memory::MemoryTrait; - use evm::precompiles::blake2f::Blake2f; - use evm::stack::StackTrait; - use evm::test_data::test_data_blake2f::{ + use crate::errors::EVMError; + use crate::instructions::MemoryOperationTrait; + use crate::instructions::SystemOperationsTrait; + use crate::memory::MemoryTrait; + use crate::precompiles::blake2f::Blake2f; + use crate::stack::StackTrait; + use crate::test_data::test_data_blake2f::{ blake2_precompile_fail_wrong_length_input_1_test_case, blake2_precompile_fail_wrong_length_input_2_test_case, blake2_precompile_fail_wrong_length_input_3_test_case, blake2_precompile_pass_1_test_case, blake2_precompile_pass_0_test_case, blake2_precompile_pass_2_test_case }; - use evm::test_utils::{VMBuilderTrait, native_token, setup_test_environment}; + use crate::test_utils::{VMBuilderTrait, native_token, setup_test_environment}; use snforge_std::start_mock_call; use utils::traits::bytes::FromBytes; diff --git a/crates/evm/src/precompiles/ec_operations/ec_add.cairo b/crates/evm/src/precompiles/ec_operations/ec_add.cairo index e2dd6967c..fe167792b 100644 --- a/crates/evm/src/precompiles/ec_operations/ec_add.cairo +++ b/crates/evm/src/precompiles/ec_operations/ec_add.cairo @@ -7,11 +7,11 @@ use core::circuit::{ }; use core::option::Option; use core::starknet::{EthAddress}; +use crate::errors::EVMError; +use crate::precompiles::Precompile; use crate::precompiles::ec_operations::{ eq_mod_p, eq_neg_mod_p, is_on_curve, double_ec_point_unchecked, BN254_PRIME_LIMBS, BN254_PRIME }; -use evm::errors::EVMError; -use evm::precompiles::Precompile; use garaga::core::circuit::AddInputResultTrait2; use utils::helpers::{load_word}; use utils::traits::bytes::{ToBytes, U8SpanExTrait}; diff --git a/crates/evm/src/precompiles/ec_operations/ec_mul.cairo b/crates/evm/src/precompiles/ec_operations/ec_mul.cairo index 89f3a3075..6c94d7d97 100644 --- a/crates/evm/src/precompiles/ec_operations/ec_mul.cairo +++ b/crates/evm/src/precompiles/ec_operations/ec_mul.cairo @@ -1,11 +1,11 @@ use core::circuit::u384; use core::option::Option; use core::starknet::{EthAddress}; + +use crate::errors::EVMError; +use crate::precompiles::Precompile; use crate::precompiles::ec_operations::ec_add::ec_safe_add; use crate::precompiles::ec_operations::{is_on_curve, double_ec_point_unchecked, BN254_PRIME}; - -use evm::errors::EVMError; -use evm::precompiles::Precompile; use utils::helpers::{load_word}; use utils::traits::bytes::{ToBytes, U8SpanExTrait}; diff --git a/crates/evm/src/precompiles/ec_recover.cairo b/crates/evm/src/precompiles/ec_recover.cairo index fe1a755b8..cfa2f68f9 100644 --- a/crates/evm/src/precompiles/ec_recover.cairo +++ b/crates/evm/src/precompiles/ec_recover.cairo @@ -4,8 +4,8 @@ use core::starknet::{ SyscallResultTrait }; use core::traits::Into; -use evm::errors::EVMError; -use evm::precompiles::Precompile; +use crate::errors::EVMError; +use crate::precompiles::Precompile; use utils::traits::EthAddressIntoU256; use utils::traits::bytes::{U8SpanExTrait, FromBytes, ToBytes}; use utils::traits::{NumericIntoBool, BoolIntoNumeric}; @@ -78,13 +78,13 @@ pub impl EcRecover of Precompile { #[cfg(test)] mod tests { use core::array::ArrayTrait; - use evm::instructions::SystemOperationsTrait; - use evm::memory::MemoryTrait; + use crate::instructions::SystemOperationsTrait; + use crate::memory::MemoryTrait; - use evm::precompiles::ec_recover::EcRecover; - use evm::stack::StackTrait; - use evm::test_utils::setup_test_environment; - use evm::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait, native_token}; + use crate::precompiles::ec_recover::EcRecover; + use crate::stack::StackTrait; + use crate::test_utils::setup_test_environment; + use crate::test_utils::{VMBuilderTrait, MemoryTestUtilsTrait, native_token}; use snforge_std::start_mock_call; use utils::traits::bytes::{ToBytes, FromBytes}; diff --git a/crates/evm/src/precompiles/identity.cairo b/crates/evm/src/precompiles/identity.cairo index 80064381d..7bd38806e 100644 --- a/crates/evm/src/precompiles/identity.cairo +++ b/crates/evm/src/precompiles/identity.cairo @@ -1,6 +1,6 @@ use core::starknet::EthAddress; -use evm::errors::EVMError; -use evm::precompiles::Precompile; +use crate::errors::EVMError; +use crate::precompiles::Precompile; const BASE_COST: u64 = 15; const COST_PER_WORD: u64 = 3; @@ -22,12 +22,12 @@ pub impl Identity of Precompile { #[cfg(test)] mod tests { use core::result::ResultTrait; - use evm::instructions::SystemOperationsTrait; + use crate::instructions::SystemOperationsTrait; - use evm::memory::MemoryTrait; - use evm::precompiles::identity::Identity; - use evm::stack::StackTrait; - use evm::test_utils::{ + use crate::memory::MemoryTrait; + use crate::precompiles::identity::Identity; + use crate::stack::StackTrait; + use crate::test_utils::{ VMBuilderTrait, MemoryTestUtilsTrait, native_token, setup_test_environment }; use snforge_std::start_mock_call; diff --git a/crates/evm/src/precompiles/modexp.cairo b/crates/evm/src/precompiles/modexp.cairo index 5afb6def2..d2b35b73e 100644 --- a/crates/evm/src/precompiles/modexp.cairo +++ b/crates/evm/src/precompiles/modexp.cairo @@ -9,9 +9,9 @@ use core::option::OptionTrait; use core::starknet::EthAddress; use core::traits::TryInto; -use evm::errors::EVMError; +use crate::errors::EVMError; -use evm::precompiles::Precompile; +use crate::precompiles::Precompile; use utils::crypto::modexp::lib::modexp; use utils::traits::bytes::{U8SpanExTrait, FromBytes}; use utils::traits::integer::BitsUsed; @@ -157,12 +157,12 @@ mod tests { use core::starknet::EthAddress; use core::starknet::testing::set_contract_address; - use evm::instructions::SystemOperationsTrait; + use crate::instructions::SystemOperationsTrait; - use evm::memory::MemoryTrait; - use evm::precompiles::Precompiles; - use evm::stack::StackTrait; - use evm::test_utils::{VMBuilderTrait, native_token, other_starknet_address}; + use crate::memory::MemoryTrait; + use crate::precompiles::Precompiles; + use crate::stack::StackTrait; + use crate::test_utils::{VMBuilderTrait, native_token, other_starknet_address}; use evm_tests::test_precompiles::test_data::test_data_modexp::{ test_modexp_modsize0_returndatasizeFiller_data, test_modexp_create2callPrecompiles_test0_berlin_data, test_modexp_eip198_example_1_data, diff --git a/crates/evm/src/precompiles/p256verify.cairo b/crates/evm/src/precompiles/p256verify.cairo index 4fed39cc2..fd5efe49f 100644 --- a/crates/evm/src/precompiles/p256verify.cairo +++ b/crates/evm/src/precompiles/p256verify.cairo @@ -1,8 +1,8 @@ use core::starknet::SyscallResultTrait; use core::starknet::secp256_trait::{Secp256Trait}; use core::starknet::{EthAddress, secp256r1::{Secp256r1Point}, secp256_trait::is_valid_signature}; -use evm::errors::{EVMError}; -use evm::precompiles::Precompile; +use crate::errors::{EVMError}; +use crate::precompiles::Precompile; use utils::traits::bytes::FromBytes; const P256VERIFY_PRECOMPILE_GAS_COST: u64 = 3450; @@ -105,13 +105,13 @@ pub impl P256Verify of Precompile { #[cfg(test)] mod tests { use core::array::ArrayTrait; - use evm::instructions::SystemOperationsTrait; - use evm::memory::MemoryTrait; + use crate::instructions::SystemOperationsTrait; + use crate::memory::MemoryTrait; - use evm::precompiles::p256verify::P256Verify; - use evm::stack::StackTrait; - use evm::test_utils::{VMBuilderTrait}; - use evm::test_utils::{setup_test_environment, native_token}; + use crate::precompiles::p256verify::P256Verify; + use crate::stack::StackTrait; + use crate::test_utils::{VMBuilderTrait}; + use crate::test_utils::{setup_test_environment, native_token}; use snforge_std::start_mock_call; use utils::traits::bytes::{ToBytes, FromBytes}; diff --git a/crates/evm/src/precompiles/sha256.cairo b/crates/evm/src/precompiles/sha256.cairo index f64f4cb50..af9174531 100644 --- a/crates/evm/src/precompiles/sha256.cairo +++ b/crates/evm/src/precompiles/sha256.cairo @@ -1,7 +1,7 @@ use core::sha256::compute_sha256_u32_array; use core::starknet::EthAddress; -use evm::errors::EVMError; -use evm::precompiles::Precompile; +use crate::errors::EVMError; +use crate::precompiles::Precompile; use utils::math::Bitshift; use utils::traits::bytes::{FromBytes, ToBytes}; @@ -51,12 +51,12 @@ pub impl Sha256 of Precompile { #[cfg(test)] mod tests { use core::result::ResultTrait; - use evm::instructions::SystemOperationsTrait; + use crate::instructions::SystemOperationsTrait; - use evm::memory::MemoryTrait; - use evm::precompiles::sha256::Sha256; - use evm::stack::StackTrait; - use evm::test_utils::{ + use crate::memory::MemoryTrait; + use crate::precompiles::sha256::Sha256; + use crate::stack::StackTrait; + use crate::test_utils::{ VMBuilderTrait, MemoryTestUtilsTrait, native_token, setup_test_environment }; use snforge_std::{start_mock_call}; diff --git a/crates/evm/src/stack.cairo b/crates/evm/src/stack.cairo index 0037b9698..06e7896f7 100644 --- a/crates/evm/src/stack.cairo +++ b/crates/evm/src/stack.cairo @@ -2,7 +2,7 @@ use core::dict::{Felt252Dict, Felt252DictTrait}; //! Stack implementation. //! # Example //! ``` -//! use evm::stack::StackTrait; +//! use crate::stack::StackTrait; //! //! // Create a new stack instance. //! let mut stack = StackTrait::new(); @@ -17,7 +17,7 @@ use core::dict::{Felt252Dict, Felt252DictTrait}; use core::nullable::{NullableTrait}; use core::num::traits::Bounded; use core::starknet::EthAddress; -use evm::errors::{ensure, EVMError}; +use crate::errors::{ensure, EVMError}; use utils::constants; use utils::i256::i256; @@ -59,11 +59,7 @@ impl StackImpl of StackTrait { /// Pushes a new bytes32 word onto the stack. /// - /// When pushing an item to the stack, we will compute - /// an index which corresponds to the index in the dict the item will be stored at. - /// The internal index is computed as follows: - /// - /// index = len(Stack_i) + i * STACK_SEGMENT_SIZE + /// The item is stored at the current length of the stack. /// /// # Errors /// @@ -83,7 +79,7 @@ impl StackImpl of StackTrait { /// /// # Errors /// - /// If the stack is empty, returns with a StackOverflow error. + /// If the stack is empty, returns with a StackUnderflow error. #[inline(always)] fn pop(ref self: Stack) -> Result { ensure(self.len() != 0, EVMError::StackUnderflow)?; @@ -236,7 +232,7 @@ impl StackImpl of StackTrait { } /// Peeks at the item at the given index on the stack. - /// index is 0-based, 0 being the top of the stack. + /// index is 0-based, where 0 is the top of the stack (most recently pushed item). /// /// # Errors /// @@ -252,7 +248,7 @@ impl StackImpl of StackTrait { } /// Swaps the item at the given index with the item on top of the stack. - /// index is 0-based, 0 being the top of the stack (unallocated). + /// index is 0-based, where 0 would mean no swap (top item swapped with itself). #[inline(always)] fn swap_i(ref self: Stack, index: usize) -> Result<(), EVMError> { ensure(index < self.len(), EVMError::StackUnderflow)?; @@ -284,7 +280,7 @@ mod tests { // Core lib imports // Internal imports - use evm::stack::StackTrait; + use crate::stack::StackTrait; use utils::constants; #[test] @@ -325,7 +321,7 @@ mod tests { } mod push { - use evm::errors::{EVMError}; + use crate::errors::{EVMError}; use super::StackTrait; use super::constants; @@ -368,7 +364,7 @@ mod tests { mod pop { use core::num::traits::Bounded; - use evm::errors::EVMError; + use crate::errors::EVMError; use super::StackTrait; use utils::traits::StorageBaseAddressPartialEq; @@ -516,7 +512,7 @@ mod tests { } mod peek { - use evm::errors::{EVMError}; + use crate::errors::{EVMError}; use super::StackTrait; #[test] @@ -580,7 +576,7 @@ mod tests { } mod swap { - use evm::errors::{EVMError}; + use crate::errors::{EVMError}; use super::StackTrait; #[test] diff --git a/crates/evm/src/state.cairo b/crates/evm/src/state.cairo index 26e3e9f34..1dd6fde36 100644 --- a/crates/evm/src/state.cairo +++ b/crates/evm/src/state.cairo @@ -5,11 +5,11 @@ use core::num::traits::{OverflowingAdd, OverflowingSub}; use core::poseidon::PoseidonTrait; use core::starknet::storage_access::{StorageBaseAddress, storage_base_address_from_felt252}; use core::starknet::{EthAddress}; -use evm::backend::starknet_backend::fetch_original_storage; +use crate::backend::starknet_backend::fetch_original_storage; -use evm::errors::{ensure, EVMError, BALANCE_OVERFLOW}; -use evm::model::account::{AccountTrait}; -use evm::model::{Event, Transfer, Account}; +use crate::errors::{ensure, EVMError, BALANCE_OVERFLOW}; +use crate::model::account::{AccountTrait}; +use crate::model::{Event, Transfer, Account}; use utils::set::{Set, SetTrait}; /// The `StateChangeLog` tracks the changes applied to storage during the execution of a @@ -72,7 +72,7 @@ impl StateChangeLogImpl, +Copy> of StateChangeLogTrait { /// /// # Arguments /// - /// * `self` - A reference to a `StateChangeLog` instance. + /// * `self` - A mutable reference to a `StateChangeLog` instance. /// * `key` - The key of the value to write. /// * `value` - The value to write. #[inline(always)] @@ -81,6 +81,15 @@ impl StateChangeLogImpl, +Copy> of StateChangeLogTrait { self.keyset.add(key); } + /// Creates a clone of the current StateChangeLog. + /// + /// # Arguments + /// + /// * `self` - A reference to the `StateChangeLog` instance to clone. + /// + /// # Returns + /// + /// A new `StateChangeLog` instance with the same contents as the original. fn clone(ref self: StateChangeLog) -> StateChangeLog { let mut cloned_changes = Default::default(); let mut keyset_span = self.keyset.to_span(); @@ -116,6 +125,16 @@ pub struct State { #[generate_trait] pub impl StateImpl of StateTrait { + /// Retrieves an account from the state, creating it if it doesn't exist. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `evm_address` - The EVM address of the account to retrieve. + /// + /// # Returns + /// + /// The `Account` associated with the given EVM address. fn get_account(ref self: State, evm_address: EthAddress) -> Account { let maybe_account = self.accounts.read(evm_address.into()); match maybe_account { @@ -128,6 +147,12 @@ pub impl StateImpl of StateTrait { } } + /// Sets an account in the state. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `account` - The `Account` to set. #[inline(always)] fn set_account(ref self: State, account: Account) { let evm_address = account.evm_address(); @@ -135,6 +160,17 @@ pub impl StateImpl of StateTrait { self.accounts.write(evm_address.into(), account) } + /// Reads a value from the state for a given EVM address and key. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `evm_address` - The EVM address of the account. + /// * `key` - The storage key. + /// + /// # Returns + /// + /// The value stored at the given address and key. #[inline(always)] fn read_state(ref self: State, evm_address: EthAddress, key: u256) -> u256 { let internal_key = compute_storage_key(evm_address, key); @@ -148,17 +184,41 @@ pub impl StateImpl of StateTrait { } } + /// Writes a value to the state for a given EVM address and key. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `evm_address` - The EVM address of the account. + /// * `key` - The storage key. + /// * `value` - The value to write. #[inline(always)] fn write_state(ref self: State, evm_address: EthAddress, key: u256, value: u256) { let internal_key = compute_storage_key(evm_address, key); self.accounts_storage.write(internal_key.into(), (evm_address, key, value)); } + /// Adds an event to the state. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `event` - The `Event` to add. #[inline(always)] fn add_event(ref self: State, event: Event) { self.events.append(event) } + /// Adds a transfer to the state and updates account balances. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `transfer` - The `Transfer` to add. + /// + /// # Returns + /// + /// A `Result` indicating success or an `EVMError` if the transfer fails. #[inline(always)] fn add_transfer(ref self: State, transfer: Transfer) -> Result<(), EVMError> { if (transfer.amount == 0 || transfer.sender.evm == transfer.recipient.evm) { @@ -183,6 +243,17 @@ pub impl StateImpl of StateTrait { Result::Ok(()) } + /// Reads a value from transient storage for a given EVM address and key. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `evm_address` - The EVM address of the account. + /// * `key` - The storage key. + /// + /// # Returns + /// + /// The value stored in transient storage at the given address and key. #[inline(always)] fn read_transient_storage(ref self: State, evm_address: EthAddress, key: u256) -> u256 { let internal_key = compute_storage_key(evm_address, key); @@ -193,12 +264,30 @@ pub impl StateImpl of StateTrait { } } + /// Writes a value to transient storage for a given EVM address and key. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `evm_address` - The EVM address of the account. + /// * `key` - The storage key. + /// * `value` - The value to write. #[inline(always)] fn write_transient_storage(ref self: State, evm_address: EthAddress, key: u256, value: u256) { let internal_key = compute_storage_key(evm_address, key); self.transient_account_storage.write(internal_key.into(), (evm_address, key, value)); } + /// Creates a clone of the current State. + /// + /// # Arguments + /// + /// * `self` - A reference to the `State` instance to clone. + /// + /// # Returns + /// + /// A new `State` instance with the same contents as the original. + #[inline(always)] fn clone(ref self: State) -> State { State { accounts: self.accounts.clone(), @@ -209,7 +298,17 @@ pub impl StateImpl of StateTrait { } } - // Check whether is an account is both in the global state and non empty. + /// Checks if an account is both in the global state and non-empty. + /// + /// # Arguments + /// + /// * `self` - A mutable reference to the `State` instance. + /// * `evm_address` - The EVM address of the account to check. + /// + /// # Returns + /// + /// `true` if the account exists and is non-empty, `false` otherwise. + #[inline(always)] fn is_account_alive(ref self: State, evm_address: EthAddress) -> bool { let account = self.get_account(evm_address); return !(account.nonce == 0 && account.code.len() == 0 && account.balance == 0); @@ -220,6 +319,7 @@ pub impl StateImpl of StateTrait { /// The key is computed as follows: /// 1. Compute the hash of the EVM address and the key(low, high) using Poseidon. /// 2. Return the hash +#[inline(always)] pub fn compute_storage_key(evm_address: EthAddress, key: u256) -> felt252 { let hash = PoseidonTrait::new().update_with(evm_address).update_with(key).finalize(); hash @@ -232,6 +332,7 @@ pub fn compute_storage_key(evm_address: EthAddress, key: u256) -> felt252 { /// Note: the storage_base_address_from_felt252 function always works for any felt - and returns the /// number normalized into the range [0, 2^251 - 256). (x % (2^251 - 256)) /// https://github.com/starkware-libs/cairo/issues/4187 +#[inline(always)] pub fn compute_storage_address(key: u256) -> StorageBaseAddress { let hash = PoseidonTrait::new().update_with(key).finalize(); storage_base_address_from_felt252(hash) @@ -239,8 +340,8 @@ pub fn compute_storage_address(key: u256) -> StorageBaseAddress { #[cfg(test)] mod tests { - use evm::state::compute_storage_key; - use evm::test_utils; + use crate::state::compute_storage_key; + use crate::test_utils; #[test] fn test_compute_storage_key() { @@ -272,8 +373,8 @@ mod tests { } mod test_state_changelog { - use evm::state::{StateChangeLog, StateChangeLogTrait}; - use evm::test_utils; + use crate::state::{StateChangeLog, StateChangeLogTrait}; + use crate::test_utils; use utils::set::SetTrait; #[test] @@ -307,10 +408,10 @@ mod tests { mod test_state { use core::starknet::EthAddress; - use evm::model::account::{Account, AccountTrait}; - use evm::model::{Event, Transfer, Address}; - use evm::state::{State, StateTrait}; - use evm::test_utils; + use crate::model::account::{Account, AccountTrait}; + use crate::model::{Event, Transfer, Address}; + use crate::state::{State, StateTrait}; + use crate::test_utils; use snforge_std::{test_address, start_mock_call}; use utils::constants::EMPTY_KECCAK; use utils::helpers::compute_starknet_address; diff --git a/crates/evm/src/test_utils.cairo b/crates/evm/src/test_utils.cairo index 90f0fc510..4726c297d 100644 --- a/crates/evm/src/test_utils.cairo +++ b/crates/evm/src/test_utils.cairo @@ -4,10 +4,10 @@ use core::starknet::storage::{StoragePointerWriteAccess, StoragePathEntry}; use core::starknet::storage_access::{StorageBaseAddress, storage_base_address_from_felt252}; use core::starknet::{ContractAddress, EthAddress, contract_address_const, ClassHash}; use core::traits::TryInto; -use evm::memory::{Memory, MemoryTrait}; +use crate::memory::{Memory, MemoryTrait}; -use evm::model::vm::{VM, VMTrait}; -use evm::model::{Message, Environment, Address, AccountTrait}; +use crate::model::vm::{VM, VMTrait}; +use crate::model::{Message, Environment, Address, AccountTrait}; use snforge_std::start_cheat_chain_id_global; use snforge_std::test_address; use starknet::storage::StorageTraitMut; diff --git a/crates/utils/src/address.cairo b/crates/utils/src/address.cairo index c2d0aba87..97a782c26 100644 --- a/crates/utils/src/address.cairo +++ b/crates/utils/src/address.cairo @@ -1,23 +1,23 @@ use core::array::ArrayTrait; use core::starknet::EthAddress; use core::traits::TryInto; +use crate::rlp::{RLPTrait, RLPItem}; use crate::traits::bytes::{ToBytes, U8SpanExTrait}; +use crate::traits::eth_address::EthAddressExTrait; +use crate::traits::{TryIntoResult}; use evm::errors::EVMError; -use utils::rlp::{RLPTrait, RLPItem}; -use utils::traits::eth_address::EthAddressExTrait; -use utils::traits::{TryIntoResult}; /// Computes the address of the new account that needs to be created. /// /// # Arguments /// -/// * `sender_address`: The address of the account that wants to create the new account. -/// * `sender_nonce`: The transaction count of the account that wants to create the new account. +/// * `sender_address` - The address of the account that wants to create the new account. +/// * `sender_nonce` - The transaction count of the account that wants to create the new account. /// /// # Returns /// -/// The computed address of the new account. +/// The computed address of the new account as an `EthAddress`. pub fn compute_contract_address(sender_address: EthAddress, sender_nonce: u64) -> EthAddress { let mut sender_address: RLPItem = RLPItem::String(sender_address.to_bytes().span()); let sender_nonce: RLPItem = RLPItem::String(sender_nonce.to_be_bytes()); @@ -30,17 +30,18 @@ pub fn compute_contract_address(sender_address: EthAddress, sender_nonce: u64) - /// Computes the address of the new account that needs to be created, which is -/// based on the sender address, salt, and the call data. +/// based on the sender address, salt, and the bytecode. /// -/// # Parameters +/// # Arguments /// -/// * `sender_address`: The address of the account that wants to create the new account. -/// * `salt`: Address generation salt. -/// * `bytecode`: The code of the new account to be created. +/// * `sender_address` - The address of the account that wants to create the new account. +/// * `salt` - Address generation salt. +/// * `bytecode` - The bytecode of the new account to be created. /// /// # Returns /// -/// The computed address of the new account. +/// A `Result` containing the computed address of the new account as an `EthAddress`, +/// or an `EVMError` if the conversion fails. pub fn compute_create2_contract_address( sender_address: EthAddress, salt: u256, bytecode: Span ) -> Result { @@ -68,7 +69,7 @@ pub fn compute_create2_contract_address( mod tests { use contracts::test_data::counter_evm_bytecode; use core::starknet::EthAddress; - use utils::address::{compute_contract_address, compute_create2_contract_address}; + use crate::address::{compute_contract_address, compute_create2_contract_address}; #[test] fn test_compute_create2_contract_address() { diff --git a/crates/utils/src/constants.cairo b/crates/utils/src/constants.cairo index 9b1381d81..78ce66bb3 100644 --- a/crates/utils/src/constants.cairo +++ b/crates/utils/src/constants.cairo @@ -1,4 +1,4 @@ -use utils::traits::{U8IntoEthAddress}; +use crate::traits::{U8IntoEthAddress}; // FELT PRIME // 2^251 + 17 * 2^192 + 1 diff --git a/crates/utils/src/crypto/blake2_compress.cairo b/crates/utils/src/crypto/blake2_compress.cairo index 0cce040c9..4ce2840e4 100644 --- a/crates/utils/src/crypto/blake2_compress.cairo +++ b/crates/utils/src/crypto/blake2_compress.cairo @@ -1,6 +1,6 @@ use alexandria_data_structures::vec::{Felt252Vec, VecTrait}; use core::num::traits::{BitSize, WrappingAdd}; -use utils::math::WrappingBitshift; +use crate::math::WrappingBitshift; const SIGMA_LINE_1: [usize; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; const SIGMA_LINE_2: [usize; 16] = [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3]; diff --git a/crates/utils/src/crypto/modexp/arith.cairo b/crates/utils/src/crypto/modexp/arith.cairo index ef6a7ea82..d82bf2f61 100644 --- a/crates/utils/src/crypto/modexp/arith.cairo +++ b/crates/utils/src/crypto/modexp/arith.cairo @@ -594,18 +594,18 @@ mod tests { use core::num::traits::{WrappingSub, WrappingMul}; use core::result::ResultTrait; use core::traits::Into; - use crate::felt_vec::{Felt252VecTrait}; - use utils::crypto::modexp::arith::{ + use crate::crypto::modexp::arith::{ mod_inv, monsq, monpro, compute_r_mod_n, in_place_shl, in_place_shr, big_wrapping_pow, big_wrapping_mul, big_sq, borrowing_sub, shifted_carrying_mul }; - use utils::crypto::modexp::mpnat::{ + use crate::crypto::modexp::mpnat::{ MPNat, MPNatTrait, WORD_MAX, DOUBLE_WORD_MAX, BASE, Word, WORD_BYTES }; - use utils::crypto::modexp::mpnat::{mp_nat_to_u128}; - use utils::math::{WrappingBitshift, WrappingExponentiation}; - use utils::traits::bytes::ToBytes; + use crate::crypto::modexp::mpnat::{mp_nat_to_u128}; + use crate::felt_vec::{Felt252VecTrait}; + use crate::math::{WrappingBitshift, WrappingExponentiation}; + use crate::traits::bytes::ToBytes; // the tests are taken from // [aurora-engine](https://github.com/aurora-is-near/aurora-engine/blob/1213f2c7c035aa523601fced8f75bef61b4728ab/engine-modexp/src/arith.rs#L401) diff --git a/crates/utils/src/crypto/modexp/lib.cairo b/crates/utils/src/crypto/modexp/lib.cairo index 5325a198e..a904bf8af 100644 --- a/crates/utils/src/crypto/modexp/lib.cairo +++ b/crates/utils/src/crypto/modexp/lib.cairo @@ -1,8 +1,8 @@ // CREDITS: The implementation has been take from // [aurora-engine](https://github.com/aurora-is-near/aurora-engine/tree/develop/engine-modexp) +use crate::crypto::modexp::mpnat::MPNatTrait; use crate::felt_vec::{Felt252VecTrait}; -use utils::crypto::modexp::mpnat::MPNatTrait; /// Computes `(base ^ exp) % modulus`, where all values are given as big-endian /// encoded bytes. diff --git a/crates/utils/src/crypto/modexp/mpnat.cairo b/crates/utils/src/crypto/modexp/mpnat.cairo index 3d13875dd..5f461837f 100644 --- a/crates/utils/src/crypto/modexp/mpnat.cairo +++ b/crates/utils/src/crypto/modexp/mpnat.cairo @@ -7,14 +7,14 @@ use core::num::traits::CheckedMul; use core::option::OptionTrait; use core::result::ResultTrait; use crate::felt_vec::{Felt252VecTrait}; +use crate::math::Bitshift; +use crate::traits::bytes::FromBytes; +use crate::traits::integer::{U64Trait, U128Trait, BitsUsed, ByteSize}; use super::arith::{ big_wrapping_pow, mod_inv, compute_r_mod_n, join_as_double, in_place_shl, in_place_shr, in_place_add, in_place_mul_sub, big_wrapping_mul, monsq, monpro, borrowing_sub, carrying_add }; -use utils::math::Bitshift; -use utils::traits::bytes::FromBytes; -use utils::traits::integer::{U64Trait, U128Trait, BitsUsed, ByteSize}; pub type Word = u64; pub type DoubleWord = u128; @@ -698,10 +698,10 @@ pub fn mp_nat_to_u128(ref x: MPNat) -> u128 { mod tests { use alexandria_data_structures::vec::Felt252VecImpl; use alexandria_data_structures::vec::VecTrait; + use crate::crypto::modexp::mpnat::MPNatTrait; + use crate::math::{Bitshift, WrappingBitshift}; + use crate::traits::bytes::ToBytes; use super::mp_nat_to_u128; - use utils::crypto::modexp::mpnat::MPNatTrait; - use utils::math::{Bitshift, WrappingBitshift}; - use utils::traits::bytes::ToBytes; // the tests are taken from // [aurora-engine](https://github.com/aurora-is-near/aurora-engine/blob/1213f2c7c035aa523601fced8f75bef61b4728ab/engine-modexp/src/mpnat.rs#L825) diff --git a/crates/utils/src/eth_transaction.cairo b/crates/utils/src/eth_transaction.cairo index ffd623c84..f10c40ba3 100644 --- a/crates/utils/src/eth_transaction.cairo +++ b/crates/utils/src/eth_transaction.cairo @@ -4,23 +4,22 @@ pub mod eip2930; pub mod legacy; pub mod transaction; pub mod tx_type; -use core::cmp::min; -use core::num::traits::CheckedAdd; -use core::option::OptionTrait; -use core::starknet::{EthAddress, secp256_trait::Signature,}; use crate::errors::{EthTransactionError, RLPErrorImpl}; use crate::traits::bytes::ByteArrayExt; -#[derive(Drop)] -pub struct TransactionMetadata { - pub address: EthAddress, - pub account_nonce: u64, - pub chain_id: u64, - pub signature: Signature, -} -/// Checks the effective gas price of a transaction as specfified in EIP-1559 with relevant -/// checks. +/// Checks the effective gas price of a transaction as specified in EIP-1559 with relevant checks. +/// +/// # Arguments +/// +/// * `max_fee_per_gas` - The maximum fee per gas the user is willing to pay. +/// * `max_priority_fee_per_gas` - The maximum priority fee per gas the user is willing to pay +/// (optional). +/// * `block_base_fee` - The base fee per gas for the current block. +/// +/// # Returns +/// +/// * `Result<(), EthTransactionError>` - Ok if the gas fee is valid, or an error if not. pub fn check_gas_fee( max_fee_per_gas: u128, max_priority_fee_per_gas: Option, block_base_fee: u128, ) -> Result<(), EthTransactionError> { @@ -40,8 +39,8 @@ pub fn check_gas_fee( #[cfg(test)] mod tests { + use crate::errors::EthTransactionError; use super::check_gas_fee; - use utils::errors::EthTransactionError; #[test] fn test_happy_path() { diff --git a/crates/utils/src/eth_transaction/eip1559.cairo b/crates/utils/src/eth_transaction/eip1559.cairo index 21216806f..eda69f7e8 100644 --- a/crates/utils/src/eth_transaction/eip1559.cairo +++ b/crates/utils/src/eth_transaction/eip1559.cairo @@ -61,6 +61,14 @@ pub struct TxEip1559 { #[generate_trait] pub impl _impl of TxEip1559Trait { /// Returns the effective gas price for the given `base_fee`. + /// + /// # Arguments + /// + /// * `base_fee` - The current network base fee, if available + /// + /// # Returns + /// + /// The effective gas price as a u128 fn effective_gas_price(self: @TxEip1559, base_fee: Option) -> u128 { match base_fee { Option::Some(base_fee) => { @@ -75,6 +83,15 @@ pub impl _impl of TxEip1559Trait { } } + /// Decodes the RLP-encoded fields into a TxEip1559 struct. + /// + /// # Arguments + /// + /// * `data` - A span of RLPItems containing the encoded transaction fields + /// + /// # Returns + /// + /// A Result containing either the decoded TxEip1559 struct or an EthTransactionError fn decode_fields(ref data: Span) -> Result { let boxed_fields = data .multi_pop_front::<9>() diff --git a/crates/utils/src/eth_transaction/eip2930.cairo b/crates/utils/src/eth_transaction/eip2930.cairo index c49eef230..2766720a9 100644 --- a/crates/utils/src/eth_transaction/eip2930.cairo +++ b/crates/utils/src/eth_transaction/eip2930.cairo @@ -72,6 +72,15 @@ pub struct TxEip2930 { #[generate_trait] pub impl _impl of TxEip2930Trait { + /// Decodes the RLP-encoded fields into a TxEip2930 struct. + /// + /// # Arguments + /// + /// * `data` - A span of RLPItems containing the encoded transaction fields + /// + /// # Returns + /// + /// A Result containing either the decoded TxEip2930 struct or an EthTransactionError fn decode_fields(ref data: Span) -> Result { let boxed_fields = data .multi_pop_front::<8>() diff --git a/crates/utils/src/fmt.cairo b/crates/utils/src/fmt.cairo index 3948f2fe9..d343b31cb 100644 --- a/crates/utils/src/fmt.cairo +++ b/crates/utils/src/fmt.cairo @@ -1,5 +1,5 @@ use core::fmt::{Debug, Formatter, Error}; -use utils::set::{SpanSet, SpanSetTrait}; +use crate::set::{SpanSet, SpanSetTrait}; mod display_felt252_based { use core::fmt::{Display, Formatter, Error}; diff --git a/crates/utils/src/helpers.cairo b/crates/utils/src/helpers.cairo index d27ff89e9..d10b7ad6d 100644 --- a/crates/utils/src/helpers.cairo +++ b/crates/utils/src/helpers.cairo @@ -8,12 +8,12 @@ use core::pedersen::PedersenTrait; use core::starknet::{EthAddress, ContractAddress, ClassHash}; use core::traits::TryInto; use core::traits::{DivRem}; +use crate::constants::{CONTRACT_ADDRESS_PREFIX, MAX_ADDRESS}; +use crate::constants::{POW_2, POW_256_1, POW_256_REV}; +use crate::math::{Bitshift, WrappingBitshift}; use crate::traits::array::{ArrayExtTrait}; -use utils::constants::{CONTRACT_ADDRESS_PREFIX, MAX_ADDRESS}; -use utils::constants::{POW_2, POW_256_1, POW_256_REV}; -use utils::math::{Bitshift, WrappingBitshift}; -use utils::traits::{U256TryIntoContractAddress, EthAddressIntoU256, BoolIntoNumeric}; +use crate::traits::{U256TryIntoContractAddress, EthAddressIntoU256, BoolIntoNumeric}; /// Splits a u128 into two u64 parts, representing the high and low parts of the input. /// @@ -95,6 +95,13 @@ pub fn split_u128_le(ref dest: Array, mut value: u128, mut len: usize) { } /// Splits a u256 into `len` bytes, little-endian, and returns the bytes array. +/// +/// # Arguments +/// * `value` - The u256 value to be split. +/// * `len` - The number of bytes to split the value into. +/// +/// # Returns +/// An `Array` containing the little-endian byte representation of the input value. pub fn split_word_le(mut value: u256, mut len: usize) -> Array { let mut dst: Array = ArrayTrait::new(); let low_len = min(len, 16); @@ -105,19 +112,23 @@ pub fn split_word_le(mut value: u256, mut len: usize) -> Array { } /// Splits a u256 into 16 bytes, big-endian, and appends the result to `dst`. +/// +/// # Arguments +/// * `value` - The u256 value to be split. +/// * `dst` - The destination array to append the bytes to. pub fn split_word_128(value: u256, ref dst: Array) { split_word(value, 16, ref dst) } -/// Loads a sequence of bytes into a single u256 in big-endian +/// Loads a sequence of bytes into a single u256 in big-endian order. /// /// # Arguments -/// * `len` - The number of bytes to load -/// * `words` - The bytes to load +/// * `len` - The number of bytes to load. +/// * `words` - The span of bytes to load. /// /// # Returns -/// The packed u256 +/// A `u256` value representing the loaded bytes in big-endian order. pub fn load_word(mut len: usize, words: Span) -> u256 { if len == 0 { return 0; @@ -137,13 +148,13 @@ pub fn load_word(mut len: usize, words: Span) -> u256 { current } -/// Converts a u256 to a bytes array represented by an array of u8 values. +/// Converts a u256 to a bytes array represented by an array of u8 values in big-endian order. /// /// # Arguments -/// * `value` - The value to convert +/// * `value` - The u256 value to convert. /// /// # Returns -/// The bytes array representation of the value. +/// An `Array` representing the big-endian byte representation of the input value. pub fn u256_to_bytes_array(mut value: u256) -> Array { let mut counter = 0; let mut bytes_arr: Array = ArrayTrait::new(); @@ -173,6 +184,15 @@ pub fn u256_to_bytes_array(mut value: u256) -> Array { } +/// Computes the Starknet address for a given Kakarot address, EVM address, and class hash. +/// +/// # Arguments +/// * `kakarot_address` - The Kakarot contract address. +/// * `evm_address` - The Ethereum address. +/// * `class_hash` - The class hash. +/// +/// # Returns +/// A `ContractAddress` representing the computed Starknet address. pub fn compute_starknet_address( kakarot_address: ContractAddress, evm_address: EthAddress, class_hash: ClassHash ) -> ContractAddress { @@ -206,7 +226,7 @@ pub fn compute_starknet_address( #[cfg(test)] mod tests { - use utils::helpers; + use crate::helpers; #[test] fn test_u256_to_bytes_array() { diff --git a/crates/utils/src/i256.cairo b/crates/utils/src/i256.cairo index 7aa9b2faf..9e8bf5dda 100644 --- a/crates/utils/src/i256.cairo +++ b/crates/utils/src/i256.cairo @@ -1,8 +1,10 @@ use core::num::traits::Bounded; -use utils::constants::POW_2_127; +use crate::constants::POW_2_127; +/// Represents a signed 256-bit integer. #[derive(Copy, Drop, PartialEq)] pub struct i256 { + /// The underlying unsigned 256-bit value. pub value: u256, } @@ -71,16 +73,23 @@ pub impl I256Rem of Rem { } } -/// Signed integer division between two integers. Returns the quotient and the remainder. -/// Conforms to EVM specifications - except that the type system enforces div != zero. +/// Performs signed integer division between two integers. +/// +/// This function conforms to EVM specifications, except that the type system enforces div != zero. /// See ethereum yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf, page 29). -/// Note that the remainder may be negative if one of the inputs is negative and that -/// (-2**255) / (-1) = -2**255 because 2*255 is out of range. +/// +/// Note: +/// - The remainder may be negative if one of the inputs is negative. +/// - (-2**255) / (-1) = -2**255 because 2**255 is out of range. +/// /// # Arguments +/// /// * `a` - The dividend. /// * `div` - The divisor, passed as a signed NonZero. +/// /// # Returns -/// * (quotient, reminder) of the signed division of `a` by `div` +/// +/// A tuple containing (quotient, remainder) of the signed division of `a` by `div`. fn i256_signed_div_rem(a: i256, div: NonZero) -> (i256, i256) { let mut div = i256 { value: div.into() }; @@ -125,8 +134,17 @@ fn i256_signed_div_rem(a: i256, div: NonZero) -> (i256, i256) { (i256_neg(quot.into()), rem.into()) } -// Returns the negation of an integer. -// Note that the negation of -2**255 is -2**255. +/// Computes the negation of an i256 integer. +/// +/// Note that the negation of -2**255 is -2**255. +/// +/// # Arguments +/// +/// * `a` - The i256 value to negate. +/// +/// # Returns +/// +/// The negation of the input value. fn i256_neg(a: i256) -> i256 { // If a is 0, adding one to its bitwise NOT will overflow and return 0. if a.value == 0 { @@ -138,7 +156,7 @@ fn i256_neg(a: i256) -> i256 { #[cfg(test)] mod tests { use core::num::traits::Bounded; - use utils::i256::{i256, i256_neg, i256_signed_div_rem}; + use crate::i256::{i256, i256_neg, i256_signed_div_rem}; const MAX_SIGNED_VALUE: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; diff --git a/crates/utils/src/lib.cairo b/crates/utils/src/lib.cairo index 9fdfc6a1f..05a2f2975 100644 --- a/crates/utils/src/lib.cairo +++ b/crates/utils/src/lib.cairo @@ -11,10 +11,6 @@ pub mod math; pub mod rlp; pub mod serialization; pub mod set; - pub mod test_data; - pub mod traits; -//! Utilities for kakarot standard library. - pub mod utils; diff --git a/crates/utils/src/math.cairo b/crates/utils/src/math.cairo index d18498191..6e77fdbc9 100644 --- a/crates/utils/src/math.cairo +++ b/crates/utils/src/math.cairo @@ -7,7 +7,18 @@ use core::traits::{BitAnd}; pub trait Exponentiation { /// Raise a number to a power. + /// + /// # Arguments + /// + /// * `self` - The base number + /// * `exponent` - The exponent to raise the base to + /// + /// # Returns + /// + /// The result of raising `self` to the power of `exponent` + /// /// # Panics + /// /// Panics if the result overflows the type T. fn pow(self: T, exponent: T) -> T; } @@ -54,7 +65,15 @@ pub trait WrappingExponentiation { /// Raise a number to a power modulo MAX (max value of type T). /// Instead of explicitly providing a modulo, we use overflowing functions /// from the core library, which wrap around when overflowing. - /// * `T` - The result of base raised to the power of exp modulo MAX. + /// + /// # Arguments + /// + /// * `self` - The base number + /// * `exponent` - The exponent to raise the base to + /// + /// # Returns + /// + /// The result of base raised to the power of exp modulo MAX. fn wrapping_pow(self: T, exponent: T) -> T; /// Performs exponentiation by repeatedly multiplying the base number with itself. @@ -64,13 +83,15 @@ pub trait WrappingExponentiation { /// The method uses a wrapping strategy to handle overflow, which means if the result /// overflows the type `T`, then higher bits are discarded and the result is wrapped. /// - /// # Parameters - /// - `self`: The base number of type `T`. - /// - `exponent`: The exponent to which the base number is raised, also of type `T`. + /// # Arguments + /// + /// * `self` - The base number of type `T`. + /// * `exponent` - The exponent to which the base number is raised, also of type `T`. /// /// # Returns - /// - Returns the result of raising `self` to the power of `exponent`, of type `T`. - /// The result is wrapped in case of overflow. + /// + /// The result of raising `self` to the power of `exponent`, of type `T`. + /// The result is wrapped in case of overflow. fn wrapping_spow(self: T, exponent: T) -> T; /// Performs exponentiation using the binary exponentiation method. @@ -81,13 +102,15 @@ pub trait WrappingExponentiation { /// a wrapping strategy to handle overflow. This means if intermediate or final results /// overflow the type `T`, then the higher bits are discarded and the result is wrapped. /// - /// # Parameters - /// - `self`: The base number of type `T`. - /// - `exponent`: The exponent to which the base number is raised, also of type `T`. + /// # Arguments + /// + /// * `self` - The base number of type `T`. + /// * `exponent` - The exponent to which the base number is raised, also of type `T`. /// /// # Returns - /// - Returns the result of raising `self` to the power of `exponent`, of type `T`. - /// The result is wrapped in case of overflow. + /// + /// The result of raising `self` to the power of `exponent`, of type `T`. + /// The result is wrapped in case of overflow. fn wrapping_fpow(self: T, exponent: T) -> T; } @@ -165,15 +188,37 @@ pub impl WrappingExponentiationImpl< // === BitShift === pub trait Bitshift { - // Shift a number left by a given number of bits. - // # Panics - // Panics if the shift is greater than 255. - // Panics if the result overflows the type T. + /// Shift a number left by a given number of bits. + /// + /// # Arguments + /// + /// * `self` - The number to shift + /// * `shift` - The number of bits to shift by + /// + /// # Returns + /// + /// The result of shifting `self` left by `shift` bits + /// + /// # Panics + /// + /// Panics if the shift is greater than 255. + /// Panics if the result overflows the type T. fn shl(self: T, shift: T) -> T; - // Shift a number right by a given number of bits. - // # Panics - // Panics if the shift is greater than 255. + /// Shift a number right by a given number of bits. + /// + /// # Arguments + /// + /// * `self` - The number to shift + /// * `shift` - The number of bits to shift by + /// + /// # Returns + /// + /// The result of shifting `self` right by `shift` bits + /// + /// # Panics + /// + /// Panics if the shift is greater than 255. fn shr(self: T, shift: T) -> T; } @@ -213,13 +258,31 @@ impl BitshiftImpl< } pub trait WrappingBitshift { - // Shift a number left by a given number of bits. - // If the shift is greater than 255, the result is 0. - // The bits moved after the 256th one are discarded, the new bits are set to 0. + /// Shift a number left by a given number of bits. + /// If the shift is greater than 255, the result is 0. + /// The bits moved after the 256th one are discarded, the new bits are set to 0. + /// + /// # Arguments + /// + /// * `self` - The number to shift + /// * `shift` - The number of bits to shift by + /// + /// # Returns + /// + /// The result of shifting `self` left by `shift` bits, wrapped if necessary fn wrapping_shl(self: T, shift: T) -> T; - // Shift a number right by a given number of bits. - // If the shift is greater than 255, the result is 0. + /// Shift a number right by a given number of bits. + /// If the shift is greater than 255, the result is 0. + /// + /// # Arguments + /// + /// * `self` - The number to shift + /// * `shift` - The number of bits to shift by + /// + /// # Returns + /// + /// The result of shifting `self` right by `shift` bits, or 0 if shift > 255 fn wrapping_shr(self: T, shift: T) -> T; } @@ -261,6 +324,15 @@ pub impl WrappingBitshiftImpl< /// /// limb3 will always be 0, because the maximum sum of two 256-bit numbers is at most /// 2**257 - 2 which fits in 257 bits. +/// +/// # Arguments +/// +/// * `a` - First 256-bit unsigned integer +/// * `b` - Second 256-bit unsigned integer +/// +/// # Returns +/// +/// A 512-bit unsigned integer representing the sum of `a` and `b` pub fn u256_wide_add(a: u256, b: u256) -> u512 { let (sum, overflow) = a.overflowing_add(b); @@ -282,10 +354,10 @@ pub fn u256_wide_add(a: u256, b: u256) -> u512 { mod tests { use core::integer::{u512}; use core::num::traits::{OverflowingMul, WrappingMul, SaturatingAdd, Bounded}; - use super::OverflowingAdd; - use utils::math::{ + use crate::math::{ Exponentiation, WrappingExponentiation, u256_wide_add, Bitshift, WrappingBitshift, }; + use super::OverflowingAdd; #[test] fn test_wrapping_pow() { diff --git a/crates/utils/src/rlp.cairo b/crates/utils/src/rlp.cairo index 38e507ef0..513fd52a9 100644 --- a/crates/utils/src/rlp.cairo +++ b/crates/utils/src/rlp.cairo @@ -28,13 +28,16 @@ pub impl RLPImpl of RLPTrait { /// its offset in the array as well as its size. /// /// # Arguments - /// * `input` - Array of byte to decode + /// * `input` - Span of bytes to decode + /// /// # Returns - /// * `(RLPType, offset, size)` - A tuple containing the RLPType - /// the offset and the size of the RLPItem to decode + /// * `Result<(RLPType, u32, u32), RLPError>` - A tuple containing the RLPType, + /// the offset, and the size of the RLPItem to decode + /// /// # Errors - /// * RLPError::EmptyInput - if the input is empty - /// * RLPError::InputTooShort - if the input is too short for a given + /// * `RLPError::EmptyInput` - if the input is empty + /// * `RLPError::InputTooShort` - if the input is too short for a given type + /// * `RLPError::InvalidInput` - if the input is invalid fn decode_type(input: Span) -> Result<(RLPType, u32, u32), RLPError> { let input_len = input.len(); if input_len == 0 { @@ -85,13 +88,16 @@ pub impl RLPImpl of RLPTrait { } } - /// RLP encodes a sequence of RLPItem + /// RLP encodes a sequence of RLPItems + /// /// # Arguments - /// * `input` - Span of RLPItem to encode + /// * `input` - Span of RLPItems to encode + /// /// # Returns - /// * `ByteArray - RLP encoded ByteArray - /// # Errors - /// * RLPError::RlpEmptyInput - if the input is empty + /// * `Span` - RLP encoded byte array + /// + /// # Panics + /// * If encoding a long sequence (should not happen in current implementation) fn encode_sequence(mut input: Span) -> Span { let mut joined_encodings: Array = Default::default(); while let Option::Some(item) = input.pop_front() { @@ -121,15 +127,13 @@ pub impl RLPImpl of RLPTrait { } /// RLP encodes a Span, which is the underlying type used to represent - /// string data in Cairo. Since RLP encoding is only used for eth_address - /// computation by calculating the RLP::encode(deployer_address, deployer_nonce) - /// and then hash it, the input is a Span + /// string data in Cairo. + /// /// # Arguments - /// * `input` - ByteArray to encode + /// * `input` - Span to encode + /// /// # Returns - /// * `ByteArray - RLP encoded ByteArray - /// # Errors - /// * RLPError::RlpEmptyInput - if the input is empty + /// * `Span` - RLP encoded byte array fn encode_string(input: Span) -> Span { let len = input.len(); if len == 0 { @@ -157,11 +161,13 @@ pub impl RLPImpl of RLPTrait { /// as described in https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/ /// /// # Arguments - /// * `input` - Array of bytes to decode + /// * `input` - Span of bytes to decode + /// /// # Returns - /// * `Span` - Span of RLPItem + /// * `Result, RLPError>` - Span of RLPItems + /// /// # Errors - /// * RLPError::InputTooShort - if the input is too short for a given + /// * `RLPError::InputTooShort` - if the input is too short for a given type fn decode(input: Span) -> Result, RLPError> { let mut output: Array = Default::default(); let input_len = input.len(); @@ -204,6 +210,13 @@ pub impl RLPImpl of RLPTrait { #[generate_trait] pub impl RLPHelpersImpl of RLPHelpersTrait { + /// Parses a u64 from an RLPItem::String + /// + /// # Returns + /// * `Result` - The parsed u64 value + /// + /// # Errors + /// * `RLPError::NotAString` - if the RLPItem is not a String fn parse_u64_from_string(self: RLPItem) -> Result { match self { RLPItem::String(bytes) => { @@ -218,6 +231,13 @@ pub impl RLPHelpersImpl of RLPHelpersTrait { } } + /// Parses a u128 from an RLPItem::String + /// + /// # Returns + /// * `Result` - The parsed u128 value + /// + /// # Errors + /// * `RLPError::NotAString` - if the RLPItem is not a String fn parse_u128_from_string(self: RLPItem) -> Result { match self { RLPItem::String(bytes) => { @@ -232,6 +252,14 @@ pub impl RLPHelpersImpl of RLPHelpersTrait { } } + /// Tries to parse an EthAddress from an RLPItem::String + /// + /// # Returns + /// * `Result, RLPError>` - The parsed EthAddress, if present + /// + /// # Errors + /// * `RLPError::NotAString` - if the RLPItem is not a String + /// * `RLPError::FailedParsingAddress` - if the address parsing fails fn try_parse_address_from_string(self: RLPItem) -> Result, RLPError> { match self { RLPItem::String(bytes) => { @@ -248,6 +276,13 @@ pub impl RLPHelpersImpl of RLPHelpersTrait { } } + /// Parses a u256 from an RLPItem::String + /// + /// # Returns + /// * `Result` - The parsed u256 value + /// + /// # Errors + /// * `RLPError::NotAString` - if the RLPItem is not a String fn parse_u256_from_string(self: RLPItem) -> Result { match self { RLPItem::String(bytes) => { @@ -262,7 +297,13 @@ pub impl RLPHelpersImpl of RLPHelpersTrait { } } - + /// Parses bytes from an RLPItem::String + /// + /// # Returns + /// * `Result, RLPError>` - The parsed bytes + /// + /// # Errors + /// * `RLPError::NotAString` - if the RLPItem is not a String fn parse_bytes_from_string(self: RLPItem) -> Result, RLPError> { match self { RLPItem::String(bytes) => { Result::Ok(bytes) }, @@ -270,6 +311,14 @@ pub impl RLPHelpersImpl of RLPHelpersTrait { } } + /// Parses storage keys from an RLPItem + /// + /// # Returns + /// * `Result, RLPError>` - The parsed storage keys + /// + /// # Errors + /// * `RLPError::NotAList` - if the RLPItem is not a List + /// * `RLPError::FailedParsingAddress` - if parsing a storage key fails fn parse_storage_keys_from_rlp_item(self: RLPItem) -> Result, RLPError> { match self { RLPItem::String(_) => { return Result::Err(RLPError::NotAList); }, @@ -294,9 +343,15 @@ pub impl RLPHelpersImpl of RLPHelpersTrait { } } - /// The data passed is in form - /// RLPItem::List([RLPItem::List([RLPItem::String(eth_address), RLPItem::List(storage_keys)]), - /// RLPItem::List([RLPItem::String(eth_address), RLPItem::List(storage_keys)])]) + /// Parses an access list from an RLPItem + /// + /// # Returns + /// * `Result, RLPError>` - The parsed access list + /// + /// # Errors + /// * `RLPError::NotAList` - if the RLPItem is not a List + /// * `RLPError::InputTooShort` - if the input is too short + /// * `RLPError::FailedParsingAccessList` - if parsing the access list fails fn parse_access_list(self: RLPItem) -> Result, RLPError> { let mut list_of_accessed_tuples: Span = match self { RLPItem::String(_) => { return Result::Err(RLPError::NotAList); }, @@ -345,16 +400,15 @@ pub impl RLPHelpersImpl of RLPHelpersTrait { result } } - #[cfg(test)] mod tests { use core::array::SpanTrait; use core::option::OptionTrait; use core::result::ResultTrait; + use crate::errors::RLPError; use crate::eth_transaction::eip2930::AccessListItem; - use utils::errors::RLPError; - use utils::rlp::{RLPType, RLPTrait, RLPItem, RLPHelpersTrait}; + use crate::rlp::{RLPType, RLPTrait, RLPItem, RLPHelpersTrait}; // Tests source : // https://github.com/HerodotusDev/cairo-lib/blob/main/src/encoding/tests/test_rlp.cairo diff --git a/crates/utils/src/serialization.cairo b/crates/utils/src/serialization.cairo index 58c17b910..34939f43b 100644 --- a/crates/utils/src/serialization.cairo +++ b/crates/utils/src/serialization.cairo @@ -1,7 +1,18 @@ use core::starknet::secp256_trait::{Signature}; -use utils::eth_transaction::tx_type::TxType; -use utils::traits::BoolIntoNumeric; - +use crate::eth_transaction::tx_type::TxType; +use crate::traits::BoolIntoNumeric; + +/// Deserializes a signature from a span of felt252 values. +/// +/// # Arguments +/// +/// * `signature` - A span of felt252 values representing the signature components. +/// * `chain_id` - The chain ID used for EIP-155 signature recovery. +/// +/// # Returns +/// +/// * `Option` - The deserialized signature if successful, or None if deserialization +/// fails. pub fn deserialize_signature(signature: Span, chain_id: u64) -> Option { let r_low: u128 = (*signature.at(0)).try_into()?; let r_high: u128 = (*signature.at(1)).try_into()?; @@ -28,6 +39,16 @@ pub fn deserialize_signature(signature: Span, chain_id: u64) -> Option< ) } +/// Computes the y-parity value for EIP-155 signature recovery. +/// +/// # Arguments +/// +/// * `v` - The v value from the signature. +/// * `chain_id` - The chain ID used for EIP-155 signature recovery. +/// +/// # Returns +/// +/// * `Option` - The computed y-parity value if valid, or None if invalid. fn compute_y_parity(v: u128, chain_id: u64) -> Option { let y_parity = v - (chain_id.into() * 2 + 35); if (y_parity == 0 || y_parity == 1) { @@ -37,6 +58,17 @@ fn compute_y_parity(v: u128, chain_id: u64) -> Option { return Option::None; } +/// Serializes a transaction signature into an array of felt252 values. +/// +/// # Arguments +/// +/// * `sig` - The signature to serialize. +/// * `tx_type` - The transaction type (Legacy, EIP-2930, or EIP-1559). +/// * `chain_id` - The chain ID used for EIP-155 signature recovery. +/// +/// # Returns +/// +/// * `Array` - The serialized signature as an array of felt252 values. pub fn serialize_transaction_signature( sig: Signature, tx_type: TxType, chain_id: u64 ) -> Array { @@ -53,6 +85,15 @@ pub fn serialize_transaction_signature( res } +/// Deserializes a span of felt252 values into an array of bytes. +/// +/// # Arguments +/// +/// * `self` - A span of felt252 values to deserialize. +/// +/// # Returns +/// +/// * `Option>` - The deserialized bytes if successful, or None if deserialization fails. pub fn deserialize_bytes(self: Span) -> Option> { let mut i = 0; let mut bytes: Array = Default::default(); @@ -76,6 +117,15 @@ pub fn deserialize_bytes(self: Span) -> Option> { } } +/// Serializes a span of bytes into an array of felt252 values. +/// +/// # Arguments +/// +/// * `self` - A span of bytes to serialize. +/// +/// # Returns +/// +/// * `Array` - The serialized bytes as an array of felt252 values. pub fn serialize_bytes(self: Span) -> Array { let mut array: Array = Default::default(); @@ -94,9 +144,9 @@ pub fn serialize_bytes(self: Span) -> Array { #[cfg(test)] mod tests { use core::starknet::secp256_trait::Signature; - use utils::constants::CHAIN_ID; - use utils::eth_transaction::tx_type::TxType; - use utils::serialization::{deserialize_signature, serialize_transaction_signature}; + use crate::constants::CHAIN_ID; + use crate::eth_transaction::tx_type::TxType; + use crate::serialization::{deserialize_signature, serialize_transaction_signature}; #[test] fn test_serialize_transaction_signature() { diff --git a/crates/utils/src/set.cairo b/crates/utils/src/set.cairo index e6d2356a4..1b654bd53 100644 --- a/crates/utils/src/set.cairo +++ b/crates/utils/src/set.cairo @@ -1,5 +1,7 @@ use crate::traits::array::{SpanExtTrait, ArrayExtTrait}; +/// A set implementation using an array as the underlying storage. +/// We are not using dicts because of the Destruct requirements. #[derive(Drop, PartialEq)] pub struct Set { inner: Array @@ -15,26 +17,54 @@ pub impl SetDefault> of Default> { #[generate_trait] pub impl SetImpl, +Copy> of SetTrait { + /// Creates a new, empty Set. + /// + /// # Returns + /// + /// A new, empty Set. #[inline] fn new() -> Set { Set { inner: Default::default() } } + /// Creates a Set from an existing Array. + /// + /// # Arguments + /// + /// * `arr` - The Array to create the Set from. + /// + /// # Returns + /// + /// A new Set containing the elements from the input Array. fn from_array(arr: Array) -> Set { Set { inner: arr } } + /// Adds an item to the Set if it's not already present. + /// + /// # Arguments + /// + /// * `item` - The item to add to the Set. #[inline] fn add<+PartialEq>(ref self: Set, item: T) { self.inner.append_unique(item); } - + /// Extends the Set with elements from another SpanSet. + /// + /// # Arguments + /// + /// * `other` - The SpanSet to extend from. #[inline] fn extend<+PartialEq>(ref self: Set, other: SpanSet) { self.extend_from_span(other.to_span()); } + /// Extends the Set with elements from a Span. + /// + /// # Arguments + /// + /// * `other` - The Span to extend from. #[inline] fn extend_from_span<+PartialEq>(ref self: Set, mut other: Span) { for v in other { @@ -42,26 +72,55 @@ pub impl SetImpl, +Copy> of SetTrait { }; } + /// Checks if the Set contains a specific item. + /// + /// # Arguments + /// + /// * `item` - The item to check for. + /// + /// # Returns + /// + /// `true` if the item is in the Set, `false` otherwise. #[inline] fn contains<+PartialEq>(self: @Set, item: T) -> bool { self.inner.span().contains(item) } + /// Converts the Set to an Array. + /// + /// # Returns + /// + /// An Array containing all elements of the Set. #[inline] fn to_array(self: Set) -> Array { self.inner } + /// Converts the Set to a Span. + /// + /// # Returns + /// + /// A Span view of the Set's elements. #[inline] fn to_span(self: @Set) -> Span { self.inner.span() } + /// Creates a SpanSet from this Set. + /// + /// # Returns + /// + /// A SpanSet view of this Set. #[inline] fn spanset(self: @Set) -> SpanSet { SpanSet { inner: self } } + /// Returns the number of elements in the Set. + /// + /// # Returns + /// + /// The number of elements in the Set. #[inline] fn len(self: @Set) -> usize { self.inner.span().len() @@ -79,12 +138,19 @@ pub impl SetTCloneImpl, +Drop, +PartialEq, +Copy> of Clone } } +/// A read-only view of a Set. #[derive(Copy, Drop, PartialEq)] pub struct SpanSet { inner: @Set } +/// Default implementation for SpanSet. pub impl SpanSetDefault> of Default> { + /// Creates a new, empty SpanSet. + /// + /// # Returns + /// + /// A new, empty SpanSet. #[inline] fn default() -> SpanSet { let set: Set = Default::default(); @@ -92,22 +158,37 @@ pub impl SpanSetDefault> of Default> { } } - -// pub impl SpanSetCopy of Copy>; -// pub impl SpanSetDrop of Drop>; - #[generate_trait] pub impl SpanSetImpl, +Drop> of SpanSetTrait { + /// Checks if the SpanSet contains a specific item. + /// + /// # Arguments + /// + /// * `item` - The item to check for. + /// + /// # Returns + /// + /// `true` if the item is in the SpanSet, `false` otherwise. #[inline] fn contains<+PartialEq>(self: SpanSet, item: T) -> bool { self.inner.contains(item) } + /// Converts the SpanSet to a Span. + /// + /// # Returns + /// + /// A Span view of the SpanSet's elements. #[inline] fn to_span(self: SpanSet) -> Span { self.inner.to_span() } + /// Creates a new Set from this SpanSet. + /// + /// # Returns + /// + /// A new Set with the same elements as this SpanSet. fn clone_set(self: SpanSet) -> Set { let mut response: Array = Default::default(); let mut span = self.to_span(); @@ -117,6 +198,11 @@ pub impl SpanSetImpl, +Drop> of SpanSetTrait { Set { inner: response } } + /// Returns the number of elements in the SpanSet. + /// + /// # Returns + /// + /// The number of elements in the SpanSet. #[inline] fn len(self: SpanSet) -> usize { self.inner.len() @@ -125,7 +211,7 @@ pub impl SpanSetImpl, +Drop> of SpanSetTrait { #[cfg(test)] mod tests { - use utils::set::{Set, SetTrait, SpanSet, SpanSetTrait}; + use crate::set::{Set, SetTrait, SpanSet, SpanSetTrait}; #[test] fn test_add() { diff --git a/crates/utils/src/traits.cairo b/crates/utils/src/traits.cairo index 90827cb51..3cf2fbf2f 100644 --- a/crates/utils/src/traits.cairo +++ b/crates/utils/src/traits.cairo @@ -8,8 +8,8 @@ use core::num::traits::{Zero, One}; use core::starknet::secp256_trait::{Signature}; use core::starknet::storage_access::{StorageBaseAddress, storage_address_from_base}; use core::starknet::{EthAddress, ContractAddress}; +use crate::math::{Bitshift}; use evm::errors::{EVMError, ensure, TYPE_CONVERSION_ERROR}; -use utils::math::{Bitshift}; pub impl DefaultSignature of Default { #[inline(always)] @@ -144,7 +144,7 @@ pub impl U8IntoEthAddress of Into { #[cfg(test)] mod tests { use core::starknet::storage_access::storage_base_address_from_felt252; - use utils::traits::{StorageBaseAddressPartialEq}; + use crate::traits::{StorageBaseAddressPartialEq}; #[test] fn test_eq_storage_base_address() { diff --git a/crates/utils/src/traits/array.cairo b/crates/utils/src/traits/array.cairo index 4001bbd22..44a2bcb62 100644 --- a/crates/utils/src/traits/array.cairo +++ b/crates/utils/src/traits/array.cairo @@ -1,13 +1,26 @@ #[generate_trait] pub impl ArrayExtension> of ArrayExtTrait { - // Concatenates two arrays by adding the elements of arr2 to arr1. + /// Concatenates two arrays by adding the elements of `arr2` to `self`. + /// + /// # Arguments + /// + /// * `self` - The array to append to. + /// * `arr2` - The array to append from. fn concat<+Copy>(ref self: Array, mut arr2: Span) { for elem in arr2 { self.append(*elem); }; } - /// Reverses an array + /// Reverses an array. + /// + /// # Arguments + /// + /// * `self` - The array to reverse. + /// + /// # Returns + /// + /// A new `Array` with the elements in reverse order. fn reverse<+Copy>(self: Span) -> Array { let mut counter = self.len(); let mut dst: Array = ArrayTrait::new(); @@ -18,7 +31,13 @@ pub impl ArrayExtension> of ArrayExtTrait { dst } - // Appends n time value to the Array + /// Appends a value to the array `n` times. + /// + /// # Arguments + /// + /// * `self` - The array to append to. + /// * `value` - The value to append. + /// * `n` - The number of times to append the value. fn append_n<+Copy>(ref self: Array, value: T, mut n: usize) { while n != 0 { self.append(value); @@ -27,7 +46,12 @@ pub impl ArrayExtension> of ArrayExtTrait { }; } - // Appends an item only if it is not already in the array. + /// Appends an item only if it is not already in the array. + /// + /// # Arguments + /// + /// * `self` - The array to append to. + /// * `value` - The value to append if not present. fn append_unique<+Copy, +PartialEq>(ref self: Array, value: T) { if self.span().contains(value) { return (); @@ -35,7 +59,12 @@ pub impl ArrayExtension> of ArrayExtTrait { self.append(value); } - // Concatenates two arrays by adding the elements of arr2 to arr1. + /// Concatenates two arrays by adding the unique elements of `arr2` to `self`. + /// + /// # Arguments + /// + /// * `self` - The array to append to. + /// * `arr2` - The array to append from. fn concat_unique<+Copy, +PartialEq>(ref self: Array, mut arr2: Span) { for elem in arr2 { self.append_unique(*elem) @@ -45,7 +74,16 @@ pub impl ArrayExtension> of ArrayExtTrait { #[generate_trait] pub impl SpanExtension, +Drop> of SpanExtTrait { - // Returns true if the array contains an item. + /// Returns true if the array contains an item. + /// + /// # Arguments + /// + /// * `self` - The array to search. + /// * `value` - The value to search for. + /// + /// # Returns + /// + /// `true` if the value is found, `false` otherwise. fn contains<+PartialEq>(mut self: Span, value: T) -> bool { let mut result = false; for elem in self { @@ -56,7 +94,16 @@ pub impl SpanExtension, +Drop> of SpanExtTrait { result } - // Returns the index of an item in the array. + /// Returns the index of an item in the array. + /// + /// # Arguments + /// + /// * `self` - The array to search. + /// * `value` - The value to search for. + /// + /// # Returns + /// + /// `Option::Some(index)` if the value is found, `Option::None` otherwise. fn index_of<+PartialEq>(mut self: Span, value: T) -> Option { let mut i = 0; let mut result = Option::None; diff --git a/crates/utils/src/traits/bytes.cairo b/crates/utils/src/traits/bytes.cairo index 80dca60f5..c780098f2 100644 --- a/crates/utils/src/traits/bytes.cairo +++ b/crates/utils/src/traits/bytes.cairo @@ -2,13 +2,17 @@ use core::cmp::min; use core::keccak::{cairo_keccak}; use core::num::traits::{Zero, One, Bounded, BitSize, SaturatingAdd}; use core::traits::{BitAnd}; +use crate::constants::{POW_2, POW_256_1, POW_256_REV}; use crate::math::{Bitshift}; use crate::traits::integer::{BytesUsedTrait, ByteSize, U256Trait}; -use utils::constants::{POW_2, POW_256_1, POW_256_REV}; #[generate_trait] pub impl U8SpanExImpl of U8SpanExTrait { - // keccack256 on a bytes message + /// Computes the keccak256 hash of a bytes message + /// # Arguments + /// * `self` - The input bytes as a Span + /// # Returns + /// * The keccak256 hash as a u256 fn compute_keccak256_hash(self: Span) -> u256 { let (mut keccak_input, last_input_word, last_input_num_bytes) = self.to_u64_words(); let hash = cairo_keccak(ref keccak_input, :last_input_word, :last_input_num_bytes) @@ -16,8 +20,16 @@ pub impl U8SpanExImpl of U8SpanExTrait { hash } + /// Transforms a Span into an Array of u64 full words, a pending u64 word and its length in /// bytes + /// # Arguments + /// * `self` - The input bytes as a Span + /// # Returns + /// * A tuple containing: + /// - An Array of full words + /// - A u64 representing the last (potentially partial) word + /// - A usize representing the number of bytes in the last word fn to_u64_words(self: Span) -> (Array, u64, usize) { let nonzero_8: NonZero = 8_u32.try_into().unwrap(); let (full_u64_word_count, last_input_num_bytes) = DivRem::div_rem(self.len(), nonzero_8); @@ -111,30 +123,20 @@ pub impl U8SpanExImpl of U8SpanExTrait { arr.span() } - /// Clones and pads the given span with 0s to the right to the given length, if data is more - /// than the given length, it is truncated from the right side + /// Clones and pads the given span with 0s to the right to the given length + /// If data is more than the given length, it is truncated from the right side + /// # Arguments + /// * `self` - The input bytes as a Span + /// * `len` - The desired length of the padded span + /// # Returns + /// * A Span of length `len` right padded with 0s if the span length is less than `len`, + /// or truncated from the right if the span length is greater than `len` /// # Examples /// ``` - /// let span = [0x01, 0x02, 0x03, 0x04, 0x05].span(); - /// let expected = [0x01, 0x02, 0x03, 0x04, 0x05, 0x0, 0x0, 0x0, 0x0, 0x0].span(); - /// let result = span.pad_right_with_zeroes(10); - /// - /// assert_eq!(result, expected); - /// - /// // Truncates the data if it is more than the given length - /// let span = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a].span(); - /// let expected = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09].span(); - /// let result = span.pad_right_with_zeroes(9); - /// - /// assert_eq!(result, expected); + /// let span = array![1, 2, 3].span(); + /// let padded = span.pad_right_with_zeroes(5); + /// assert_eq!(padded, array![1, 2, 3, 0, 0].span()); /// ``` - /// # Arguments - /// * `len` - The length of the padded span - /// - /// # Returns - /// * A span of length `len` right padded with 0s if the span length is less than `len`, returns - /// a span of length `len` if the span length is greater than `len` then the data is truncated - /// from the right side fn pad_right_with_zeroes(self: Span, len: usize) -> Span { if self.len() >= len { return self.slice(0, len); @@ -155,29 +157,20 @@ pub impl U8SpanExImpl of U8SpanExTrait { } - /// Clones and pads the given span with 0s to the given length, if data is more than the given - /// length, it is truncated from the right side # Examples - /// ``` - /// let span = [0x0, 0x01, 0x02, 0x03, 0x04, 0x05].span(); - /// let expected = [0x0, 0x0, 0x0, 0x0, 0x0, 0x01, 0x02, 0x03, 0x04, 0x05].span(); - /// let result = span.pad_left_with_zeroes(10); - /// - /// assert_eq!(result, expected); - /// - /// // Truncates the data if it is more than the given length - /// let span = [0x0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7, 0x8, 0x9].span(); - /// let expected = [0x0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7, 0x8].span(); - /// let result = span.pad_left_with_zeroes(9); - /// - /// assert_eq!(result, expected); - /// ``` + /// Clones and pads the given span with 0s to the left to the given length + /// If data is more than the given length, it is truncated from the right side /// # Arguments - /// * `len` - The length of the padded span - /// + /// * `self` - The input bytes as a Span + /// * `len` - The desired length of the padded span /// # Returns - /// * A span of length `len` left padded with 0s if the span length is less than `len`, returns - /// a span of length `len` if the span length is greater than `len` then the data is truncated - /// from the right side + /// * A Span of length `len` left padded with 0s if the span length is less than `len`, + /// or truncated from the right if the span length is greater than `len` + /// # Examples + /// ``` + /// let span = array![1, 2, 3].span(); + /// let padded = span.pad_left_with_zeroes(5); + /// assert_eq!(padded, array![0, 0, 1, 2, 3].span()); + /// ``` fn pad_left_with_zeroes(self: Span, len: usize) -> Span { if self.len() >= len { return self.slice(0, len); @@ -437,12 +430,21 @@ pub impl FromBytesImpl< #[generate_trait] pub impl ByteArrayExt of ByteArrayExTrait { + /// Appends a span of bytes to the ByteArray + /// # Arguments + /// * `self` - The ByteArray to append to + /// * `bytes` - The span of bytes to append fn append_span_bytes(ref self: ByteArray, mut bytes: Span) { for val in bytes { self.append_byte(*val); }; } + /// Creates a ByteArray from a span of bytes + /// # Arguments + /// * `bytes` - The span of bytes to convert + /// # Returns + /// * A new ByteArray containing the input bytes fn from_bytes(mut bytes: Span) -> ByteArray { let mut arr: ByteArray = Default::default(); let (nb_full_words, pending_word_len) = DivRem::div_rem( @@ -475,10 +477,20 @@ pub impl ByteArrayExt of ByteArrayExTrait { arr } + /// Checks if the ByteArray is empty + /// # Arguments + /// * `self` - The ByteArray to check + /// # Returns + /// * true if the ByteArray is empty, false otherwise fn is_empty(self: @ByteArray) -> bool { self.len() == 0 } + /// Converts the ByteArray into a span of bytes + /// # Arguments + /// * `self` - The ByteArray to convert + /// # Returns + /// * A Span containing the bytes from the ByteArray fn into_bytes(self: ByteArray) -> Span { let mut output: Array = Default::default(); let len = self.len(); @@ -493,6 +505,13 @@ pub impl ByteArrayExt of ByteArrayExTrait { /// Transforms a ByteArray into an Array of u64 full words, a pending u64 word and its length in /// bytes + /// # Arguments + /// * `self` - The ByteArray to transform + /// # Returns + /// * A tuple containing: + /// - An Array of full words + /// - A u64 representing the last (potentially partial) word + /// - A usize representing the number of bytes in the last word fn to_u64_words(self: ByteArray) -> (Array, u64, usize) { // We pass it by value because we want to take ownership, but we snap it // because `at` takes a snap and if this snap is automatically done by diff --git a/crates/utils/src/traits/eth_address.cairo b/crates/utils/src/traits/eth_address.cairo index 16d022197..c2f260716 100644 --- a/crates/utils/src/traits/eth_address.cairo +++ b/crates/utils/src/traits/eth_address.cairo @@ -4,6 +4,11 @@ use crate::traits::EthAddressIntoU256; #[generate_trait] pub impl EthAddressExImpl of EthAddressExTrait { + /// Converts an EthAddress to an array of bytes. + /// + /// # Returns + /// + /// * `Array` - A 20-byte array representation of the EthAddress. fn to_bytes(self: EthAddress) -> Array { let bytes_used: u256 = 20; let value: u256 = self.into(); @@ -18,12 +23,16 @@ pub impl EthAddressExImpl of EthAddressExTrait { bytes } - /// Packs 20 bytes into a EthAddress + /// Converts a 20-byte array into an EthAddress. + /// /// # Arguments - /// * `input` a Span of len == 20 + /// + /// * `input` - A `Span` of length 20 representing the bytes of an Ethereum address. + /// /// # Returns - /// * Option::Some(EthAddress) if the operation succeeds - /// * Option::None otherwise + /// + /// * `Option` - `Some(EthAddress)` if the conversion succeeds, `None` if the input + /// length is not 20. fn from_bytes(input: Span) -> Option { let len = input.len(); if len != 20 { diff --git a/crates/utils/src/utils.cairo b/crates/utils/src/utils.cairo index 6d3ac14bb..242b45b83 100644 --- a/crates/utils/src/utils.cairo +++ b/crates/utils/src/utils.cairo @@ -57,12 +57,11 @@ pub fn load_packed_bytes(input: Span, bytes_len: u32) -> Array { let (chunk_counts, remainder) = DivRem::div_rem(bytes_len, 31); let mut res: Array = Default::default(); - let mut i = 0; - while i != chunk_counts { - let mut value: u256 = (*input[i]).into(); - unpack_chunk(value, 31, ref res); - i += 1; - }; + for i in 0 + ..chunk_counts { + let mut value: u256 = (*input[i]).into(); + unpack_chunk(value, 31, ref res); + }; if remainder.is_zero() { return res;