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: update starknet address computation method #862

Merged
merged 3 commits into from
Aug 22, 2024
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
16 changes: 4 additions & 12 deletions crates/contracts/src/account_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ use core::starknet::{ContractAddress, EthAddress, ClassHash};
#[starknet::interface]
pub trait IAccount<TContractState> {
fn initialize(
ref self: TContractState,
kakarot_address: ContractAddress,
evm_address: EthAddress,
implementation_class: ClassHash
ref self: TContractState, evm_address: EthAddress, implementation_class: ClassHash
);
fn get_implementation(self: @TContractState) -> ClassHash;
fn get_evm_address(self: @TContractState) -> EthAddress;
Expand Down Expand Up @@ -74,10 +71,8 @@ pub mod AccountContract {

// Add ownable component
component!(path: ownable_component, storage: ownable, event: OwnableEvent);

#[abi(embed_v0)]
impl OwnableImpl = ownable_component::Ownable<ContractState>;

impl OwnableInternal = ownable_component::InternalImpl<ContractState>;


Expand Down Expand Up @@ -120,19 +115,16 @@ pub mod AccountContract {
#[abi(embed_v0)]
impl Account of super::IAccount<ContractState> {
fn initialize(
ref self: ContractState,
kakarot_address: ContractAddress,
evm_address: EthAddress,
implementation_class: ClassHash
ref self: ContractState, evm_address: EthAddress, implementation_class: ClassHash
) {
assert(!self.Account_is_initialized.read(), 'Account already initialized');
self.Account_is_initialized.write(true);
self.ownable.initializer(kakarot_address);

self.Account_evm_address.write(evm_address);
self.Account_implementation.write(implementation_class);

let kakarot_address = self.ownable.owner();
let kakarot = IKakarotCoreDispatcher { contract_address: kakarot_address };

let native_token = kakarot.get_native_token();
// To internally perform value transfer of the network's native
// token (which conforms to the ERC20 standard), we need to give the
Expand Down
5 changes: 2 additions & 3 deletions crates/contracts/src/test_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,13 @@ pub(crate) fn deploy_contract_account(evm_address: EthAddress, bytecode: Span<u8
}

fn deploy_eoa(eoa_address: EthAddress) -> IAccountDispatcher {
let kakarot_address = get_contract_address();
let calldata: Span<felt252> = [kakarot_address.into(), eoa_address.into()].span();
let calldata: Span<felt252> = [1, eoa_address.into()].span();

let (starknet_address, _) = deploy_syscall(
UninitializedAccount::TEST_CLASS_HASH.try_into().unwrap(),
eoa_address.into(),
calldata,
true
deploy_from_zero: false
)
.expect('failed to deploy EOA');

Expand Down
43 changes: 34 additions & 9 deletions crates/contracts/src/uninitialized_account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,49 @@ trait IAccount<TContractState> {

#[starknet::contract]
pub mod UninitializedAccount {
use contracts::components::ownable::IOwnable;
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::replace_class_syscall;
use core::starknet::syscalls::{library_call_syscall, replace_class_syscall};
use core::starknet::{ContractAddress, EthAddress, ClassHash, get_caller_address};
use super::{IAccountLibraryDispatcher, IAccountDispatcherTrait};

// Add ownable component
component!(path: ownable_component, storage: ownable, event: OwnableEvent);
#[abi(embed_v0)]
impl OwnableImpl = ownable_component::Ownable<ContractState>;
impl OwnableInternal = ownable_component::InternalImpl<ContractState>;

#[storage]
struct Storage {}
struct Storage {
#[substorage(v0)]
ownable: ownable_component::Storage,
}

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

#[constructor]
fn constructor(
ref self: ContractState, kakarot_address: ContractAddress, evm_address: EthAddress
) {
let implementation_class = IKakarotCoreDispatcher { contract_address: kakarot_address }
fn constructor(ref self: ContractState, mut calldata: Array<felt252>) {
let owner_address: ContractAddress = get_caller_address();
self.ownable.initializer(owner_address);
let implementation_class = IKakarotCoreDispatcher { contract_address: owner_address }
.get_account_contract_class_hash();

IAccountLibraryDispatcher { class_hash: implementation_class }
.initialize(kakarot_address, evm_address, implementation_class);
//TODO: Difference from KakarotZero in that the account contract takes the class
//implementation to write it in storage,
// as it is not a transparent proxy in Cairo1
calldata.append(implementation_class.into());
library_call_syscall(
class_hash: implementation_class,
function_selector: selector!("initialize"),
calldata: calldata.span()
)
.unwrap_syscall();

replace_class_syscall(implementation_class).unwrap_syscall();
}
Expand Down
8 changes: 5 additions & 3 deletions crates/evm/src/backend/starknet_backend.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ fn deploy(evm_address: EthAddress) -> Result<Address, EVMError> {

let mut kakarot_state = KakarotCore::unsafe_new_contract_state();
let uninitialized_account_class_hash = kakarot_state.uninitialized_account_class_hash();
let kakarot_address = get_contract_address();
let calldata: Span<felt252> = [kakarot_address.into(), evm_address.into()].span();
let calldata: Span<felt252> = [1, evm_address.into()].span();

let (starknet_address, _) = deploy_syscall(
uninitialized_account_class_hash, evm_address.into(), calldata, true
uninitialized_account_class_hash,
contract_address_salt: evm_address.into(),
calldata: calldata,
deploy_from_zero: false
)
.unwrap_syscall();

Expand Down
8 changes: 4 additions & 4 deletions crates/utils/src/helpers.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -761,22 +761,22 @@ pub impl ResultExImpl<T, E, +Drop<T>, +Drop<E>> of ResultExTrait<T, E> {
pub fn compute_starknet_address(
kakarot_address: ContractAddress, evm_address: EthAddress, class_hash: ClassHash
) -> ContractAddress {
// Deployer is always 0
// Deployer is always Kakarot (current contract)
// pedersen(a1, a2, a3) is defined as:
// pedersen(pedersen(pedersen(a1, a2), a3), len([a1, a2, a3]))
// https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/cairo/common/hash_state.py#L6
// https://github.com/xJonathanLEI/starknet-rs/blob/master/starknet-core/src/crypto.rs#L49
// Constructor Calldata For an Account, the constructor calldata is:
// [kakarot_address, evm_address]
// [1, evm_address]
let constructor_calldata_hash = PedersenTrait::new(0)
.update_with(kakarot_address)
.update_with(1)
.update_with(evm_address)
.update(2)
.finalize();

let hash = PedersenTrait::new(0)
.update_with(CONTRACT_ADDRESS_PREFIX)
.update_with(0)
.update_with(kakarot_address)
.update_with(evm_address)
.update_with(class_hash)
.update_with(constructor_calldata_hash)
Expand Down
Loading