Skip to content

Commit

Permalink
Merge branch 'main' into feat/decodetx
Browse files Browse the repository at this point in the history
  • Loading branch information
Quentash committed Oct 18, 2023
2 parents df4e404 + 9d8f6ec commit a7296c6
Show file tree
Hide file tree
Showing 41 changed files with 1,326 additions and 218 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,15 @@
[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" }
utils = { path = "../utils" }
alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandria.git", rev = "3356bf0c5c1a089167d7d3c28d543e195325e596" }

[tool.fmt]
sort-module-level-items = true
File renamed without changes.
39 changes: 39 additions & 0 deletions crates/contracts/src/components/upgradeable.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use starknet::{replace_class_syscall, ClassHash};

#[starknet::interface]
trait IUpgradeable<TContractState> {
fn upgrade_contract(ref self: TContractState, new_class_hash: ClassHash);
}


#[starknet::component]
mod upgradeable_component {
use starknet::ClassHash;
use starknet::info::get_caller_address;

#[storage]
struct Storage {}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
ContractUpgraded: ContractUpgraded
}

#[derive(Drop, starknet::Event)]
struct ContractUpgraded {
new_class_hash: ClassHash
}

#[embeddable_as(Upgradeable)]
impl UpgradeableImpl<
TContractState, +HasComponent<TContractState>
> of super::IUpgradeable<ComponentState<TContractState>> {
fn upgrade_contract(
ref self: ComponentState<TContractState>, new_class_hash: starknet::ClassHash
) {
starknet::replace_class_syscall(new_class_hash);
self.emit(ContractUpgraded { new_class_hash: new_class_hash });
}
}
}
48 changes: 48 additions & 0 deletions crates/contracts/src/contract_account.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Contract Account related functions, including bytecode storage

use alexandria_storage::list::{List, ListTrait};
use hash::{HashStateTrait, HashStateExTrait};
use poseidon::PoseidonTrait;
use starknet::{
StorageBaseAddress, storage_base_address_from_felt252, Store, EthAddress, SyscallResult,
storage_write_syscall, storage_address_from_base, storage_read_syscall,
storage_address_from_base_and_offset
};
use utils::helpers::{ByteArrayExTrait};
use utils::storage::{compute_storage_base_address};
use utils::traits::{StorageBaseAddressIntoFelt252, StoreBytes31};

/// Stores the EVM bytecode of a contract account in Kakarot Core's contract storage. The bytecode is first packed
/// into a ByteArray and then stored in the contract storage.
/// # Arguments
/// * `evm_address` - The EVM address of the contract account
/// * `bytecode` - The bytecode to store
fn store_bytecode(evm_address: EthAddress, bytecode: Span<u8>) {
let packed_bytecode: ByteArray = ByteArrayExTrait::from_bytes(bytecode);
// data_address is h(h(sn_keccak("contract_account_bytecode")), evm_address)
let data_address = compute_storage_base_address(
selector!("contract_account_bytecode"), array![evm_address.into()].span()
);
// We start storing the full 31-byte words of bytecode data at address
// `data_address`. The `pending_word` and `pending_word_len` are stored at
// address `data_address-2` and `data_address-1` respectively.
//TODO(eni) replace with ListTrait::new() once merged in alexandria
let mut stored_list: List<bytes31> = List {
address_domain: 0, base: data_address, len: 0, storage_size: Store::<bytes31>::size()
};
let pending_word_addr: felt252 = data_address.into() - 2;
let pending_word_len_addr: felt252 = pending_word_addr + 1;

// Store the `ByteArray` in the contract storage.
Store::<
felt252
>::write(0, storage_base_address_from_felt252(pending_word_addr), packed_bytecode.pending_word);
Store::<
usize
>::write(
0,
storage_base_address_from_felt252(pending_word_len_addr),
packed_bytecode.pending_word_len
);
stored_list.from_span(packed_bytecode.data.span());
}
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);
}

Loading

0 comments on commit a7296c6

Please sign in to comment.