Skip to content

Commit

Permalink
Merge branch 'main' into tests/create
Browse files Browse the repository at this point in the history
  • Loading branch information
Eikix authored Nov 29, 2023
2 parents 6d93a24 + 7dfa34b commit 7c7c4eb
Show file tree
Hide file tree
Showing 24 changed files with 508 additions and 162 deletions.
Binary file modified bun.lockb
Binary file not shown.
25 changes: 25 additions & 0 deletions crates/evm/src/context.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use evm::errors::EVMError;
use evm::memory::{Memory, MemoryTrait};
use evm::model::Address;
use evm::model::Event;
Expand Down Expand Up @@ -139,6 +140,7 @@ struct ExecutionContext {
// Return data of a child context.
return_data: Span<u8>,
parent_ctx: Nullable<ExecutionContext>,
gas_used: u128,
}


Expand Down Expand Up @@ -184,6 +186,7 @@ impl ExecutionContextImpl of ExecutionContextTrait {
call_ctx: BoxTrait::new(call_ctx),
return_data,
parent_ctx,
gas_used: Default::default(),
}
}

Expand Down Expand Up @@ -229,6 +232,28 @@ impl ExecutionContextImpl of ExecutionContextTrait {
self.status = Status::Stopped;
}

#[inline(always)]
fn gas_used(self: @ExecutionContext) -> u128 {
*self.gas_used
}

#[inline(always)]
fn increment_gas_used_unchecked(ref self: ExecutionContext, value: u128) {
self.gas_used += value;
}

/// Increments the gas_used field of the current execution context by the value amount.
/// # Error : returns `EVMError::OutOfGas` if gas_used + new_gas >= limit
#[inline(always)]
fn increment_gas_used_checked(ref self: ExecutionContext, value: u128) -> Result<(), EVMError> {
let new_gas_used = self.gas_used() + value;
if (new_gas_used >= self.call_ctx().gas_limit()) {
return Result::Err(EVMError::OutOfGas);
}
self.gas_used = new_gas_used;
Result::Ok(())
}

/// Revert the current execution context.
///
/// When the execution context is reverted, no more instructions can be executed
Expand Down
11 changes: 11 additions & 0 deletions crates/evm/src/errors.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::fmt::{Debug, Formatter, Error, Display};

// STACK
const STACK_OVERFLOW: felt252 = 'KKT: StackOverflow';
const STACK_UNDERFLOW: felt252 = 'KKT: StackUnderflow';
Expand Down Expand Up @@ -60,6 +62,7 @@ enum EVMError {
InvalidMachineState: felt252,
DeployError: felt252,
OriginError: felt252,
OutOfGas,
}

#[generate_trait]
Expand All @@ -80,6 +83,14 @@ impl EVMErrorImpl of EVMErrorTrait {
EVMError::InvalidMachineState(error_message) => error_message.into(),
EVMError::DeployError(error_message) => error_message,
EVMError::OriginError(error_message) => error_message,
EVMError::OutOfGas => 'OutOfGas'.into(),
}
}
}

impl DebugEVMError of Debug<EVMError> {
fn fmt(self: @EVMError, ref f: Formatter) -> Result<(), Error> {
let error_message = (*self).to_string();
Display::fmt(@error_message, ref f)
}
}
45 changes: 45 additions & 0 deletions crates/evm/src/gas.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! Gas costs for EVM operations
//! Code is based on alloy project
//! Source: <https://github.com/bluealloy/revm/blob/main/crates/interpreter/src/gas/constants.rs>

pub const ZERO: u128 = 0;
pub const BASE: u128 = 2;
pub const VERYLOW: u128 = 3;
pub const LOW: u128 = 5;
pub const MID: u128 = 8;
pub const HIGH: u128 = 10;
pub const JUMPDEST: u128 = 1;
pub const SELFDESTRUCT: u128 = 5000;
pub const CREATE: u128 = 32000;
pub const CALLVALUE: u128 = 9000;
pub const NEWACCOUNT: u128 = 25000;
pub const EXP: u128 = 10;
pub const MEMORY: u128 = 3;
pub const LOG: u128 = 375;
pub const LOGDATA: u128 = 8;
pub const LOGTOPIC: u128 = 375;
pub const KECCAK256: u128 = 30;
pub const KECCAK256WORD: u128 = 6;
pub const COPY: u128 = 3;
pub const BLOCKHASH: u128 = 20;
pub const CODEDEPOSIT: u128 = 200;

pub const SSTORE_SET: u128 = 20000;
pub const SSTORE_RESET: u128 = 5000;
pub const REFUND_SSTORE_CLEARS: u128 = 15000;

pub const TRANSACTION_ZERO_DATA: u128 = 4;
pub const TRANSACTION_NON_ZERO_DATA_INIT: u128 = 16;
pub const TRANSACTION_NON_ZERO_DATA_FRONTIER: u128 = 68;

// Berlin EIP-2929 constants
pub const ACCESS_LIST_ADDRESS: u128 = 2400;
pub const ACCESS_LIST_STORAGE_KEY: u128 = 1900;
pub const COLD_SLOAD_COST: u128 = 2100;
pub const COLD_ACCOUNT_ACCESS_COST: u128 = 2600;
pub const WARM_STORAGE_READ_COST: u128 = 100;

/// EIP-3860 : Limit and meter initcode
pub const INITCODE_WORD_COST: u128 = 2;

pub const CALL_STIPEND: u128 = 2300;
20 changes: 20 additions & 0 deletions crates/evm/src/instructions/block_information.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use contracts::kakarot_core::{KakarotCore, IKakarotCore};
use evm::errors::{
EVMError, BLOCK_HASH_SYSCALL_FAILED, EXECUTION_INFO_SYSCALL_FAILED, TYPE_CONVERSION_ERROR
};

use evm::gas;
use evm::machine::{Machine, MachineTrait};
use evm::model::Account;
use evm::model::account::{AccountTrait};
Expand All @@ -25,6 +27,8 @@ impl BlockInformation of BlockInformationTrait {
/// Get the hash of one of the 256 most recent complete blocks.
/// # Specification: https://www.evm.codes/#40?fork=shanghai
fn exec_blockhash(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::BLOCKHASH)?;

let block_number = self.stack.pop_u64()?;
let current_block = get_block_number();

Expand Down Expand Up @@ -52,6 +56,8 @@ impl BlockInformation of BlockInformationTrait {
/// Get the block's beneficiary address.
/// # Specification: https://www.evm.codes/#41?fork=shanghai
fn exec_coinbase(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::BASE)?;

let execution_info = get_execution_info_syscall()
.map_err(EVMError::SyscallFailed(EXECUTION_INFO_SYSCALL_FAILED))?
.unbox();
Expand All @@ -67,19 +73,25 @@ impl BlockInformation of BlockInformationTrait {
/// Get the block’s timestamp
/// # Specification: https://www.evm.codes/#42?fork=shanghai
fn exec_timestamp(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::BASE)?;

self.stack.push(get_block_timestamp().into())
}

/// 0x43 - NUMBER
/// Get the block number.
/// # Specification: https://www.evm.codes/#43?fork=shanghai
fn exec_number(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::BASE)?;

self.stack.push(get_block_number().into())
}

/// 0x44 - PREVRANDAO
/// # Specification: https://www.evm.codes/#44?fork=shanghai
fn exec_prevrandao(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::BASE)?;

// PREVRANDAO does not exist in Starknet
// PREVRANDAO used to be DIFFICULTY, which returns 0 for non-POW chains
self.stack.push(0x00)
Expand All @@ -89,13 +101,17 @@ impl BlockInformation of BlockInformationTrait {
/// Get gas limit
/// # Specification: https://www.evm.codes/#45?fork=shanghai
fn exec_gaslimit(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::BASE)?;

self.stack.push(self.gas_limit().into())
}

/// 0x46 - CHAINID
/// Get the chain ID.
/// # Specification: https://www.evm.codes/#46?fork=shanghai
fn exec_chainid(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::BASE)?;

let kakarot_state = KakarotCore::unsafe_new_contract_state();
let chain_id = kakarot_state.chain_id();
self.stack.push(chain_id.into())
Expand All @@ -105,6 +121,8 @@ impl BlockInformation of BlockInformationTrait {
/// Get balance of currently executing contract
/// # Specification: https://www.evm.codes/#47?fork=shanghai
fn exec_selfbalance(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::LOW)?;

let evm_address = self.address().evm;

let balance = self.state.get_account(evm_address).balance;
Expand All @@ -116,6 +134,8 @@ impl BlockInformation of BlockInformationTrait {
/// Get base fee.
/// # Specification: https://www.evm.codes/#48?fork=shanghai
fn exec_basefee(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::BASE)?;

// Get the current base fee. (Kakarot doesn't use EIP 1559 so basefee
// doesn't really exists there so we just use the gas price)
self.stack.push(self.gas_price().into())
Expand Down
17 changes: 16 additions & 1 deletion crates/evm/src/instructions/comparison_operations.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use evm::errors::EVMError;
use evm::errors::STACK_UNDERFLOW;
use evm::gas;
// Internal imports
use evm::machine::Machine;
use evm::machine::{Machine, MachineTrait};
use evm::stack::StackTrait;
use integer::BoundedInt;
use utils::constants::{POW_2_127};
Expand All @@ -14,6 +15,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x10 - LT
/// # Specification: https://www.evm.codes/#10?fork=shanghai
fn exec_lt(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let a = *popped[0];
let b = *popped[1];
Expand All @@ -24,6 +26,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x11 - GT
/// # Specification: https://www.evm.codes/#11?fork=shanghai
fn exec_gt(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let a = *popped[0];
let b = *popped[1];
Expand All @@ -35,6 +38,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x12 - SLT
/// # Specification: https://www.evm.codes/#12?fork=shanghai
fn exec_slt(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let a: i256 = self.stack.pop_i256()?;
let b: i256 = self.stack.pop_i256()?;
let result: u256 = (a < b).into();
Expand All @@ -44,6 +48,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x13 - SGT
/// # Specification: https://www.evm.codes/#13?fork=shanghai
fn exec_sgt(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let a: i256 = self.stack.pop_i256()?;
let b: i256 = self.stack.pop_i256()?;
let result: u256 = (a > b).into();
Expand All @@ -54,6 +59,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x14 - EQ
/// # Specification: https://www.evm.codes/#14?fork=shanghai
fn exec_eq(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let a = *popped[0];
let b = *popped[1];
Expand All @@ -64,6 +70,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x15 - ISZERO
/// # Specification: https://www.evm.codes/#15?fork=shanghai
fn exec_iszero(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop()?;
let result: u256 = (popped == 0).into();
self.stack.push(result)
Expand All @@ -72,6 +79,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x16 - AND
/// # Specification: https://www.evm.codes/#16?fork=shanghai
fn exec_and(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let a = *popped[0];
let b = *popped[1];
Expand All @@ -82,6 +90,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x17 - OR
/// # Specification: https://www.evm.codes/#17?fork=shanghai
fn exec_or(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let a = *popped[0];
let b = *popped[1];
Expand All @@ -92,6 +101,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x18 - XOR operation
/// # Specification: https://www.evm.codes/#18?fork=shanghai
fn exec_xor(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let a = *popped[0];
let b = *popped[1];
Expand All @@ -103,6 +113,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// Bitwise NOT operation
/// # Specification: https://www.evm.codes/#19?fork=shanghai
fn exec_not(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let a = self.stack.pop()?;
let result = ~a;
self.stack.push(result)
Expand All @@ -112,6 +123,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// # Specification: https://www.evm.codes/#1a?fork=shanghai
/// Retrieve single byte located at the byte offset of value, starting from the most significant byte.
fn exec_byte(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let i = *popped[0];
let x = *popped[1];
Expand All @@ -129,6 +141,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x1B - SHL
/// # Specification: https://www.evm.codes/#1b?fork=shanghai
fn exec_shl(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let shift = *popped[0];
let val = *popped[1];
Expand All @@ -145,6 +158,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x1C - SHR
/// # Specification: https://www.evm.codes/#1c?fork=shanghai
fn exec_shr(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let popped = self.stack.pop_n(2)?;
let shift = *popped[0];
let value = *popped[1];
Expand All @@ -156,6 +170,7 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait {
/// 0x1D - SAR
/// # Specification: https://www.evm.codes/#1d?fork=shanghai
fn exec_sar(ref self: Machine) -> Result<(), EVMError> {
self.increment_gas_used_checked(gas::VERYLOW)?;
let shift: u256 = self.stack.pop()?;
let value: i256 = self.stack.pop_i256()?;

Expand Down
4 changes: 3 additions & 1 deletion crates/evm/src/instructions/duplication_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ use evm::machine::Machine;
mod internal {
use evm::context::{ExecutionContext, ExecutionContextTrait,};
use evm::errors::EVMError;
use evm::machine::Machine;
use evm::gas;
use evm::machine::{Machine, MachineTrait};
use evm::stack::StackTrait;

/// Generic DUP operation
#[inline(always)]
fn exec_dup_i(ref machine: Machine, i: u8) -> Result<(), EVMError> {
machine.increment_gas_used_checked(gas::VERYLOW)?;
let item = machine.stack.peek_at((i - 1).into())?;
machine.stack.push(item)
}
Expand Down
Loading

0 comments on commit 7c7c4eb

Please sign in to comment.