Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feat/selfbalance #434

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion crates/contracts/src/tests/test_kakarot_core.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use contracts::tests::test_upgradeable::{
IMockContractUpgradeableDispatcherTrait
};
use contracts::tests::utils;
use debug::PrintTrait;
use eoa::externally_owned_account::ExternallyOwnedAccount;
use evm::tests::test_utils;
use starknet::{get_caller_address, testing, contract_address_const, ContractAddress, ClassHash};
Expand Down
1 change: 0 additions & 1 deletion crates/contracts/src/tests/test_upgradeable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use MockContractUpgradeableV0::HasComponentImpl_upgradeable_component;
use contracts::components::upgradeable::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait};
use contracts::components::upgradeable::{upgradeable_component};
use contracts::tests::utils;
use debug::PrintTrait;
use serde::Serde;
use starknet::{deploy_syscall, ClassHash, ContractAddress, testing};

Expand Down
38 changes: 38 additions & 0 deletions crates/evm/src/balance.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use contracts::kakarot_core::interface::{IKakarotCore};
use contracts::kakarot_core::{ContractAccountStorage, KakarotCore};
use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait};
use starknet::EthAddress;


/// Returns the balance in native token for a given EVM account (EOA or CA)
/// This is equivalent to checking the balance in native coin, i.e. ETHER of an account in Ethereum
fn balance(evm_address: EthAddress) -> u256 {
// Get access to Kakarot State locally
let kakarot_state = KakarotCore::unsafe_new_contract_state();

let eoa_starknet_address = kakarot_state.eoa_starknet_address(evm_address);

// Case 1: EOA is deployed
// BALANCE is the EOA's native_token.balanceOf(eoa_starknet_address)
if !eoa_starknet_address.is_zero() {
let native_token_address = kakarot_state.native_token();
// TODO: make sure this part of the codebase is upgradable
// As native_token might become a snake_case implementation
// instead of camelCase
let native_token = IERC20CamelDispatcher { contract_address: native_token_address };
return native_token.balanceOf(eoa_starknet_address);
}

// Case 2: EOA is not deployed and CA is deployed
// We check if a contract account is initialized at evm_address
// A good condition to check is nonce > 0, as deploying a contract account
// will set its nonce to 1
let ca_storage = kakarot_state.contract_account_storage(evm_address);
if ca_storage.nonce != 0 {
return ca_storage.balance;
}

// Case 3: No EOA nor CA are deployed at `evm_address`
// Return 0
0
}
7 changes: 6 additions & 1 deletion crates/evm/src/instructions/block_information.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use evm::balance::balance;
//! Block Information.

use evm::errors::EVMError;
Expand Down Expand Up @@ -65,7 +66,11 @@ 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> {
Result::Err(EVMError::NotImplemented)
let evm_address = self.evm_address();

let balance = balance(evm_address);

self.stack.push(balance)
}

/// 0x48 - BASEFEE
Expand Down
30 changes: 3 additions & 27 deletions crates/evm/src/instructions/environmental_information.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use contracts::kakarot_core::interface::{IKakarotCore};
use contracts::kakarot_core::{ContractAccountStorage, KakarotCore};
use core::hash::{HashStateExTrait, HashStateTrait};
use evm::balance::balance;
use evm::context::ExecutionContextTrait;
use evm::errors::{EVMError, RETURNDATA_OUT_OF_BOUNDS_ERROR, READ_SYSCALL_FAILED};
use evm::machine::{Machine, MachineCurrentContextTrait};
Expand Down Expand Up @@ -28,34 +29,9 @@ impl EnvironmentInformationImpl of EnvironmentInformationTrait {
fn exec_balance(ref self: Machine) -> Result<(), EVMError> {
let evm_address = self.stack.pop_eth_address()?;

// Get access to Kakarot State locally
let kakarot_state = KakarotCore::unsafe_new_contract_state();
let balance = balance(evm_address);

let eoa_starknet_address = kakarot_state.eoa_starknet_address(evm_address);

// Case 1: EOA is deployed
// BALANCE is the EOA's native_token.balanceOf(eoa_starknet_address)
if !eoa_starknet_address.is_zero() {
let native_token_address = kakarot_state.native_token();
// TODO: make sure this part of the codebase is upgradable
// As native_token might become a snake_case implementation
// instead of camelCase
let native_token = IERC20CamelDispatcher { contract_address: native_token_address };
return self.stack.push(native_token.balanceOf(eoa_starknet_address));
}

// Case 2: EOA is not deployed and CA is deployed
// We check if a contract account is initialized at evm_address
// A good condition to check is nonce > 0, as deploying a contract account
// will set its nonce to 1
let ca_storage = kakarot_state.contract_account_storage(evm_address);
if ca_storage.nonce != 0 {
return self.stack.push(ca_storage.balance);
}

// Case 3: No EOA nor CA are deployed at `evm_address`
// Return 0
return self.stack.push(0);
return self.stack.push(balance);
}

/// 0x32 - ORIGIN
Expand Down
2 changes: 2 additions & 0 deletions crates/evm/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Balance utils
mod balance;
// Context module
mod context;

Expand Down
1 change: 0 additions & 1 deletion crates/evm/src/stack.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

//! let value = stack.pop()?;
//! ```
use debug::PrintTrait;
use evm::errors::{EVMError, STACK_OVERFLOW, STACK_UNDERFLOW, TYPE_CONVERSION_ERROR};
use nullable::{nullable_from_box, NullableTrait};
use starknet::{StorageBaseAddress, EthAddress};
Expand Down
2 changes: 2 additions & 0 deletions crates/evm/src/tests.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#[cfg(test)]
mod test_balance;
#[cfg(test)]
mod test_execution_context;

#[cfg(test)]
Expand Down
60 changes: 60 additions & 0 deletions crates/evm/src/tests/test_balance.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use contracts::kakarot_core::interface::IExtendedKakarotCoreDispatcherTrait;
use contracts::tests::utils::{
deploy_kakarot_core, deploy_native_token, fund_account_with_native_token
};
use evm::balance::balance;
use evm::tests::test_utils::{evm_address};
use openzeppelin::token::erc20::interface::IERC20CamelDispatcherTrait;
use starknet::testing::set_contract_address;

#[test]
#[available_gas(5000000)]
fn test_balance_eoa() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);
let eoa = kakarot_core.deploy_eoa(evm_address());

fund_account_with_native_token(eoa, native_token);

// When
set_contract_address(kakarot_core.contract_address);
let balance = balance(evm_address());

// Then
assert(balance == native_token.balanceOf(eoa), 'wrong balance');
}

#[test]
#[available_gas(5000000)]
fn test_balance_zero() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);

// When
set_contract_address(kakarot_core.contract_address);
let balance = balance(evm_address());

// Then
assert(balance == 0x00, 'wrong balance');
}

// TODO: implement balance once contracts accounts can be deployed
#[ignore]
#[test]
#[available_gas(5000000)]
fn test_balance_contract_account() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);
// TODO: deploy contract account
// and fund it

// When
set_contract_address(kakarot_core.contract_address);
let balance = balance(evm_address());

// Then
panic_with_felt252('Not implemented yet');
}
1 change: 0 additions & 1 deletion crates/evm/src/tests/test_execution_context.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use core::nullable::{NullableTrait, null};
use debug::PrintTrait;
use evm::context::{
CallContext, CallContextTrait, ExecutionContext, ExecutionContextTrait, DefaultOptionSpanU8
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
use contracts::kakarot_core::interface::IExtendedKakarotCoreDispatcherTrait;
use contracts::tests::utils::{
deploy_kakarot_core, deploy_native_token, fund_account_with_native_token
};
use evm::instructions::BlockInformationTrait;
use evm::stack::StackTrait;
use evm::tests::test_utils::setup_machine;
use starknet::testing::{set_block_timestamp, set_block_number};
use evm::tests::test_utils::{setup_machine, evm_address};
use openzeppelin::token::erc20::interface::IERC20CamelDispatcherTrait;
use starknet::testing::{set_block_timestamp, set_block_number, set_contract_address};
use utils::constants::CHAIN_ID;

#[test]
Expand Down Expand Up @@ -49,6 +54,71 @@ fn test_gaslimit() {
assert(machine.stack.peek().unwrap() == 0xffffff, 'stack top should be 0xffffff');
}

// *************************************************************************
// 0x47: SELFBALANCE
// *************************************************************************
#[test]
#[available_gas(5000000)]
fn test_exec_selfbalance_eoa() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);
let eoa = kakarot_core.deploy_eoa(evm_address());

fund_account_with_native_token(eoa, native_token);

// And
let mut machine = setup_machine();

// When
set_contract_address(kakarot_core.contract_address);
machine.exec_selfbalance();

// Then
assert(machine.stack.peek().unwrap() == native_token.balanceOf(eoa), 'wrong balance');
}

#[test]
#[available_gas(5000000)]
fn test_exec_selfbalance_zero() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);

// And
let mut machine = setup_machine();

// When
set_contract_address(kakarot_core.contract_address);
machine.exec_selfbalance();

// Then
assert(machine.stack.peek().unwrap() == 0x00, 'wrong balance');
}

// TODO: implement balance once contracts accounts can be deployed
#[ignore]
#[test]
#[available_gas(5000000)]
fn test_exec_selfbalance_contract_account() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);
// TODO: deploy contract account
// and fund it

// And
let mut machine = setup_machine();

// When
set_contract_address(kakarot_core.contract_address);
machine.exec_selfbalance();

// Then
panic_with_felt252('Not implemented yet');
}


#[test]
#[available_gas(20000000)]
fn test_basefee() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use debug::PrintTrait;
use evm::instructions::ComparisonAndBitwiseOperationsTrait;
use evm::stack::StackTrait;
use evm::tests::test_utils::setup_machine;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use debug::PrintTrait;
use evm::instructions::DuplicationOperationsTrait;
use evm::stack::Stack;
use evm::stack::StackTrait;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use array::{ArrayTrait};
use contracts::kakarot_core::interface::IExtendedKakarotCoreDispatcherTrait;
use contracts::tests::utils::{
deploy_kakarot_core, deploy_native_token, fund_account_with_native_token
};
use debug::U256PrintImpl;
use evm::errors::{EVMError, TYPE_CONVERSION_ERROR, RETURNDATA_OUT_OF_BOUNDS_ERROR};
use evm::instructions::EnvironmentInformationTrait;
use evm::machine::{Machine, MachineCurrentContextTrait};
Expand Down Expand Up @@ -53,7 +51,7 @@ fn test_address_nested_call() { // A (EOA) -(calls)-> B (smart contract) -(calls
// *************************************************************************
#[test]
#[available_gas(5000000)]
fn test_balance_eoa() {
fn test_exec_balance_eoa() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);
Expand All @@ -70,13 +68,12 @@ fn test_balance_eoa() {
machine.exec_balance();

// Then
machine.stack.peek().unwrap().print();
assert(machine.stack.peek().unwrap() == native_token.balanceOf(eoa), 'wrong balance');
}

#[test]
#[available_gas(5000000)]
fn test_balance_zero() {
fn test_exec_balance_zero() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);
Expand All @@ -90,15 +87,14 @@ fn test_balance_zero() {
machine.exec_balance();

// Then
machine.stack.peek().unwrap().print();
assert(machine.stack.peek().unwrap() == 0x00, 'wrong balance');
}

// TODO: implement balance once contracts accounts can be deployed
#[ignore]
#[test]
#[available_gas(5000000)]
fn test_balance_contract_account() {
fn test_exec_balance_contract_account() {
// Given
let native_token = deploy_native_token();
let kakarot_core = deploy_kakarot_core(native_token.contract_address);
Expand All @@ -114,7 +110,6 @@ fn test_balance_contract_account() {
machine.exec_balance();

// Then
machine.stack.peek().unwrap().print();
panic_with_felt252('Not implemented yet');
}

Expand Down Expand Up @@ -714,3 +709,4 @@ fn test_returndata_copy(dest_offset: u32, offset: u32, mut size: u32) {
};
assert(results.span() == return_data.slice(offset, size), 'wrong data value');
}

4 changes: 2 additions & 2 deletions crates/evm/src/tests/test_memory.cairo
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use evm::memory::{MemoryTrait, InternalMemoryTrait, MemoryPrintTrait};
use evm::memory::{MemoryTrait, InternalMemoryTrait};
use integer::BoundedInt;
use utils::constants::{POW_2_8, POW_2_56, POW_2_64, POW_2_120};
use utils::{math::Exponentiation, math::WrappingExponentiation, helpers, helpers::SpanExtTrait};

mod internal {
use evm::memory::{MemoryTrait, InternalMemoryTrait, MemoryPrintTrait};
use evm::memory::{MemoryTrait, InternalMemoryTrait};
use utils::{math::Exponentiation, helpers};

fn load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n(
Expand Down
1 change: 0 additions & 1 deletion crates/utils/src/helpers.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use debug::PrintTrait;
use starknet::{EthAddress, EthAddressIntoFelt252};
use cmp::min;
use utils::constants::{
Expand Down
1 change: 0 additions & 1 deletion crates/utils/src/tests/test_helpers.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use utils::helpers::{
SpanExtension, SpanExtTrait, ArrayExtension, ArrayExtTrait, U256Trait, BytesSerde
};
use utils::helpers::{ByteArrayExTrait};
use debug::PrintTrait;

#[test]
#[available_gas(2000000000)]
Expand Down