Skip to content

Commit

Permalink
Feat/balance (#427)
Browse files Browse the repository at this point in the history
* gc -m "feat: implement eoa balance"

* feat: add test

* feat: update internal of exec_balance

* refactor: refactoring balance to not call

* refactor: delete kakarot_core_native_token

* chore: fmt

* refactor: put openzeppelin into its own crate

* refactor: rename core contracts

* refactor: clean up and implement comments from pr review

* refactor: use contract_address_const more

* Update crates/evm/src/instructions/environmental_information.cairo

Co-authored-by: Mathieu <[email protected]>

* Update crates/evm/src/instructions/environmental_information.cairo

Co-authored-by: Mathieu <[email protected]>

* fix: fix pr comment

---------

Co-authored-by: Mathieu <[email protected]>
  • Loading branch information
Eikix and enitrat committed Oct 17, 2023
1 parent e72a8fd commit 65fbf7d
Show file tree
Hide file tree
Showing 26 changed files with 722 additions and 188 deletions.
2 changes: 1 addition & 1 deletion .trunk/trunk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
version: 0.1
cli:
version: 1.16.2
version: 1.17.0
plugins:
sources:
- id: trunk
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
[package]
name = "core_contracts"
name = "contracts"
version = "0.1.0"

# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html

[dependencies]
starknet.workspace = true
evm = { path = "../evm" }
openzeppelin = { path = "../openzeppelin" }

[tool.fmt]
sort-module-level-items = true
File renamed without changes.
4 changes: 4 additions & 0 deletions crates/contracts/src/kakarot_core.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod interface;
mod kakarot;

use kakarot::{KakarotCore, ContractAccountStorage};
137 changes: 137 additions & 0 deletions crates/contracts/src/kakarot_core/interface.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use contracts::kakarot_core::ContractAccountStorage;
use starknet::{ContractAddress, EthAddress, ClassHash};

#[starknet::interface]
trait IKakarotCore<TContractState> {
/// Sets the native token, this token will be considered the native coin in the Ethereum sense
fn set_native_token(ref self: TContractState, native_token: ContractAddress);

/// Gets the native token used by the Kakarot smart contract
fn native_token(self: @TContractState) -> ContractAddress;

/// Sets the deploy fee for an EOA
/// Currently, the Kakarot RPC can trigger an EOA deployment,
/// and optimistically fund it.
/// Then, the KakarotCore smart contract is able to levy this fee retroactively from the EOA
/// And reimburse the RPC's smart wallet.
fn set_deploy_fee(ref self: TContractState, deploy_fee: u128);

/// Get the deploy fee
fn deploy_fee(self: @TContractState) -> u128;

/// Deterministically computes a Starknet address for an given EVM address
/// The address is computed as the Starknet address corresponding to the deployment of an EOA,
/// Using its EVM address as salt, and KakarotCore as deployer.
fn compute_starknet_address(self: @TContractState, evm_address: EthAddress) -> ContractAddress;

/// Checks into KakarotCore storage if an EOA has been deployed for a
/// particular EVM address and if so, returns its corresponding Starknet Address.
/// Otherwise, returns 0
fn eoa_starknet_address(self: @TContractState, evm_address: EthAddress) -> ContractAddress;

/// Gets the storage associated to a contract account
fn contract_account_storage(
self: @TContractState, evm_address: EthAddress
) -> ContractAccountStorage;

/// Deploys an EOA for a particular EVM address
fn deploy_eoa(ref self: TContractState, evm_address: EthAddress) -> ContractAddress;

/// View entrypoint into the EVM
/// Performs view calls into the blockchain
/// It cannot modify the state of the chain
fn eth_call(
self: @TContractState,
from: EthAddress,
to: EthAddress,
gas_limit: u128,
gas_price: u128,
value: u128,
data: Span<u8>
) -> Span<u8>;

/// Transaction entrypoint into the EVM
/// Executes an EVM transaction and possibly modifies the state
fn eth_send_transaction(
ref self: TContractState,
to: EthAddress,
gas_limit: u128,
gas_price: u128,
value: u128,
data: Span<u8>
) -> Span<u8>;

/// Upgrade the KakarotCore smart contract
/// Using replace_class_syscall
fn upgrade(ref self: TContractState, new_class_hash: ClassHash);
}

#[starknet::interface]
trait IExtendedKakarotCore<TContractState> {
/// Sets the native token, this token will be considered the native coin in the Ethereum sense
fn set_native_token(ref self: TContractState, native_token: ContractAddress);

/// Gets the native token used by the Kakarot smart contract
fn native_token(self: @TContractState) -> ContractAddress;

/// Sets the deploy fee for an EOA
/// Currently, the Kakarot RPC can trigger an EOA deployment,
/// and optimistically fund it.
/// Then, the KakarotCore smart contract is able to levy this fee retroactively from the EOA
/// And reimburse the RPC's smart wallet.
fn set_deploy_fee(ref self: TContractState, deploy_fee: u128);

/// Get the deploy fee
fn deploy_fee(self: @TContractState) -> u128;

/// Deterministically computes a Starknet address for an given EVM address
/// The address is computed as the Starknet address corresponding to the deployment of an EOA,
/// Using its EVM address as salt, and KakarotCore as deployer.
fn compute_starknet_address(self: @TContractState, evm_address: EthAddress) -> ContractAddress;

/// Checks into KakarotCore storage if an EOA has been deployed for a
/// particular EVM address and if so, returns its corresponding Starknet Address
fn eoa_starknet_address(self: @TContractState, evm_address: EthAddress) -> ContractAddress;


/// Gets the storage associated to a contract account
fn contract_account_storage(
self: @TContractState, evm_address: EthAddress
) -> ContractAccountStorage;

/// Deploys an EOA for a particular EVM address
fn deploy_eoa(ref self: TContractState, evm_address: EthAddress) -> ContractAddress;

/// View entrypoint into the EVM
/// Performs view calls into the blockchain
/// It cannot modify the state of the chain
fn eth_call(
self: @TContractState,
from: EthAddress,
to: EthAddress,
gas_limit: u128,
gas_price: u128,
value: u128,
data: Span<u8>
) -> Span<u8>;

/// Transaction entrypoint into the EVM
/// Executes an EVM transaction and possibly modifies the state
fn eth_send_transaction(
ref self: TContractState,
to: EthAddress,
gas_limit: u128,
gas_price: u128,
value: u128,
data: Span<u8>
) -> Span<u8>;

/// Upgrade the KakarotCore smart contract
/// Using replace_class_syscall
fn upgrade(ref self: TContractState, new_class_hash: ClassHash);

fn owner(self: @TContractState) -> ContractAddress;
fn transfer_ownership(ref self: TContractState, new_owner: ContractAddress);
fn renounce_ownership(ref self: TContractState);
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,34 @@ use starknet::{ContractAddress, EthAddress, ClassHash};

const INVOKE_ETH_CALL_FORBIDDEN: felt252 = 'KKT: Cannot invoke eth_call';

#[starknet::interface]
trait IKakarotCore<TContractState> {
/// Sets the native token, this token will be considered the native coin in the Ethereum sense
fn set_native_token(ref self: TContractState, native_token: ContractAddress);

/// Gets the native token used by the Kakarot smart contract
fn native_token(self: @TContractState) -> ContractAddress;

/// Sets the deploy fee for an EOA
/// Currently, the Kakarot RPC can trigger an EOA deployment,
/// and optimistically fund it.
/// Then, the KakarotCore smart contract is able to levy this fee retroactively from the EOA
/// And reimburse the RPC's smart wallet.
fn set_deploy_fee(ref self: TContractState, deploy_fee: u128);

/// Get the deploy fee
fn deploy_fee(self: @TContractState) -> u128;

/// Deterministically computes a Starknet address for an given EVM address
/// The address is computed as the Starknet address corresponding to the deployment of an EOA,
/// Using its EVM address as salt, and KakarotCore as deployer.
fn compute_starknet_address(self: @TContractState, evm_address: EthAddress) -> ContractAddress;

/// Checks into KakarotCore storage if an EOA has been deployed for a
/// particular EVM address and if so, returns its corresponding Starknet Address.
/// Otherwise, returns 0
fn get_eoa_starknet_address(self: @TContractState, evm_address: EthAddress) -> ContractAddress;

/// Deploys an EOA for a particular EVM address
fn deploy_eoa(ref self: TContractState, evm_address: EthAddress) -> ContractAddress;

/// View entrypoint into the EVM
/// Performs view calls into the blockchain
/// It cannot modify the state of the chain
fn eth_call(
self: @TContractState,
from: EthAddress,
to: EthAddress,
gas_limit: u128,
gas_price: u128,
value: u128,
data: Span<u8>
) -> Span<u8>;

/// Transaction entrypoint into the EVM
/// Executes an EVM transaction and possibly modifies the state
fn eth_send_transaction(
ref self: TContractState,
to: EthAddress,
gas_limit: u128,
gas_price: u128,
value: u128,
data: Span<u8>
) -> Span<u8>;

/// Upgrade the KakarotCore smart contract
/// Using replace_class_syscall
fn upgrade(ref self: TContractState, new_class_hash: ClassHash);

#[derive(Copy, Drop, Serde, starknet::Store)]
struct ContractAccountStorage {
nonce: u64,
balance: u256,
// TODO: add bytecode as a field for ContractAccountStorage
// bytecode: List

//TODO: add valid jumps as a field for ContractAccountStorage
// valid_jumps: LegacyMap<usize, bool>
}


#[starknet::contract]
mod KakarotCore {
use contracts::components::ownable::ownable_component::InternalTrait;
use contracts::components::ownable::{ownable_component};
use contracts::kakarot_core::interface::IKakarotCore;
use contracts::kakarot_core::interface;
use core::hash::{HashStateExTrait, HashStateTrait};
use core::pedersen::{HashState, PedersenTrait};
use core::starknet::SyscallResultTrait;
use core::zeroable::Zeroable;
use core_contracts::components::ownable::ownable_component::InternalTrait;
use core_contracts::components::ownable::{ownable_component};
use evm::errors::EVMError;
use evm::storage::ContractAccountStorage;
use starknet::{
EthAddress, ContractAddress, ClassHash, get_tx_info, get_contract_address, deploy_syscall
};
use super::ContractAccountStorage;
use super::INVOKE_ETH_CALL_FORBIDDEN;
use utils::constants::{CONTRACT_ADDRESS_PREFIX, MAX_ADDRESS};
use utils::traits::U256TryIntoContractAddress;
Expand All @@ -90,20 +44,19 @@ mod KakarotCore {
#[storage]
struct Storage {
/// Kakarot storage for accounts: Externally Owned Accounts (EOA) and Contract Accounts (CA)
/// EOAs:
/// Map their EVM address and their Starknet address
/// - starknet_address: the deterministic starknet address (31 bytes) computed given an EVM address (20 bytes)
///
/// CAs:
/// Map EVM address of a CA and the corresponding Kakarot Core storage ->
/// - nonce (note that this nonce is not the same as the Starknet protocol nonce)
/// - current balance in native token (CAs can use this balance as an allowance to spend native Starknet token through Kakarot Core)
/// - bytecode of the CA
/// Storage of CAs in EVM is defined as a mapping of key (bytes32) - value (bytes32) pairs
///
/// EOAs:
/// Map their EVM address and their Starknet address
/// - starknet_address: the deterministic starknet address (31 bytes) computed given an EVM address (20 bytes)
contract_account_storage: LegacyMap::<EthAddress, ContractAccountStorage>,
eoa_address_registry: LegacyMap::<EthAddress, ContractAddress>,
eoa_class_hash: ClassHash,
/// Storage of CAs in EVM is defined as a mapping of key (bytes32) - value (bytes32) pairs
contract_account_storage: LegacyMap<(EthAddress, u256), u256>,
contract_account_registry: LegacyMap::<EthAddress, ContractAccountStorage>,
// Utility storage
native_token: ContractAddress,
deploy_fee: u128,
Expand Down Expand Up @@ -145,7 +98,7 @@ mod KakarotCore {
}

#[external(v0)]
impl KakarotCoreImpl of super::IKakarotCore<ContractState> {
impl KakarotCoreImpl of interface::IKakarotCore<ContractState> {
fn set_native_token(ref self: ContractState, native_token: ContractAddress) {
self.ownable.assert_only_owner();
self.native_token.write(native_token);
Expand Down Expand Up @@ -213,12 +166,17 @@ mod KakarotCore {
/// Checks into KakarotCore storage if an EOA has been deployed for a
/// particular EVM address and if so, returns its corresponding Starknet Address
/// Otherwise, returns 0
fn get_eoa_starknet_address(
self: @ContractState, evm_address: EthAddress
) -> ContractAddress {
fn eoa_starknet_address(self: @ContractState, evm_address: EthAddress) -> ContractAddress {
self.eoa_address_registry.read(evm_address)
}

/// Gets the storage associated to a contract account
fn contract_account_storage(
self: @ContractState, evm_address: EthAddress
) -> ContractAccountStorage {
self.contract_account_storage.read(evm_address)
}

/// Deploys an EOA for a particular EVM address
fn deploy_eoa(ref self: ContractState, evm_address: EthAddress) -> ContractAddress {
// First let's check that the EOA is not already deployed
Expand Down Expand Up @@ -312,67 +270,3 @@ mod KakarotCore {
}
}


#[starknet::interface]
trait IExtendedKakarotCore<TContractState> {
/// Sets the native token, this token will be considered the native coin in the Ethereum sense
fn set_native_token(ref self: TContractState, native_token: ContractAddress);

/// Gets the native token used by the Kakarot smart contract
fn native_token(self: @TContractState) -> ContractAddress;

/// Sets the deploy fee for an EOA
/// Currently, the Kakarot RPC can trigger an EOA deployment,
/// and optimistically fund it.
/// Then, the KakarotCore smart contract is able to levy this fee retroactively from the EOA
/// And reimburse the RPC's smart wallet.
fn set_deploy_fee(ref self: TContractState, deploy_fee: u128);

/// Get the deploy fee
fn deploy_fee(self: @TContractState) -> u128;

/// Deterministically computes a Starknet address for an given EVM address
/// The address is computed as the Starknet address corresponding to the deployment of an EOA,
/// Using its EVM address as salt, and KakarotCore as deployer.
fn compute_starknet_address(self: @TContractState, evm_address: EthAddress) -> ContractAddress;

/// Checks into KakarotCore storage if an EOA has been deployed for a
/// particular EVM address and if so, returns its corresponding Starknet Address
fn get_eoa_starknet_address(self: @TContractState, evm_address: EthAddress) -> ContractAddress;

/// Deploys an EOA for a particular EVM address
fn deploy_eoa(ref self: TContractState, evm_address: EthAddress) -> ContractAddress;

/// View entrypoint into the EVM
/// Performs view calls into the blockchain
/// It cannot modify the state of the chain
fn eth_call(
self: @TContractState,
from: EthAddress,
to: EthAddress,
gas_limit: u128,
gas_price: u128,
value: u128,
data: Span<u8>
) -> Span<u8>;

/// Transaction entrypoint into the EVM
/// Executes an EVM transaction and possibly modifies the state
fn eth_send_transaction(
ref self: TContractState,
to: EthAddress,
gas_limit: u128,
gas_price: u128,
value: u128,
data: Span<u8>
) -> Span<u8>;

/// Upgrade the KakarotCore smart contract
/// Using replace_class_syscall
fn upgrade(ref self: TContractState, new_class_hash: ClassHash);

fn owner(self: @TContractState) -> ContractAddress;
fn transfer_ownership(ref self: TContractState, new_owner: ContractAddress);
fn renounce_ownership(ref self: TContractState);
}

File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 65fbf7d

Please sign in to comment.