Skip to content

Commit

Permalink
feat(katana): add STRK fee token (#2536)
Browse files Browse the repository at this point in the history
  • Loading branch information
kariy authored Oct 15, 2024
1 parent cddb99e commit 542df4f
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 12 deletions.
75 changes: 66 additions & 9 deletions crates/katana/primitives/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ impl ChainSpec {
Block { header, body: Vec::new() }
}

// this method will include the the ETH fee token, and the UDC. Declaring and deploying the
// necessary classes and contracts.
// this method will include the the ETH and STRK fee tokens, and the UDC
pub fn state_updates(&self) -> StateUpdatesWithDeclaredClasses {
let mut states = StateUpdatesWithDeclaredClasses::default();

Expand Down Expand Up @@ -95,7 +94,7 @@ impl ChainSpec {
states.state_updates.storage_updates.insert(address, storage);
}

//-- Fee token
//-- Fee tokens

// -- ETH
add_fee_token(
Expand All @@ -108,6 +107,17 @@ impl ChainSpec {
&self.genesis.allocations,
);

// -- STRK
add_fee_token(
&mut states,
"Starknet Token",
"STRK",
18,
DEFAULT_STRK_FEE_TOKEN_ADDRESS,
DEFAULT_LEGACY_ERC20_CLASS_HASH,
&self.genesis.allocations,
);

// -- UDC

states
Expand Down Expand Up @@ -216,9 +226,9 @@ mod tests {
};
use crate::genesis::constant::{
DEFAULT_ACCOUNT_CLASS, DEFAULT_ACCOUNT_CLASS_CASM, DEFAULT_ACCOUNT_CLASS_HASH,
DEFAULT_ACCOUNT_COMPILED_CLASS_HASH, DEFAULT_LEGACY_ERC20_CASM,
DEFAULT_LEGACY_ERC20_COMPILED_CLASS_HASH, DEFAULT_LEGACY_UDC_CASM,
DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH,
DEFAULT_ACCOUNT_CLASS_PUBKEY_STORAGE_SLOT, DEFAULT_ACCOUNT_COMPILED_CLASS_HASH,
DEFAULT_LEGACY_ERC20_CASM, DEFAULT_LEGACY_ERC20_COMPILED_CLASS_HASH,
DEFAULT_LEGACY_UDC_CASM, DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH,
};
use crate::genesis::GenesisClass;
use crate::version::CURRENT_STARKNET_VERSION;
Expand Down Expand Up @@ -401,6 +411,14 @@ mod tests {
Some(&DEFAULT_LEGACY_ERC20_CLASS_HASH),
"The ETH fee token contract should be created"
);
assert_eq!(
actual_state_updates
.state_updates
.deployed_contracts
.get(&DEFAULT_STRK_FEE_TOKEN_ADDRESS),
Some(&DEFAULT_LEGACY_ERC20_CLASS_HASH),
"The STRK fee token contract should be created"
);

assert_eq!(
actual_state_updates.state_updates.declared_classes.get(&DEFAULT_LEGACY_UDC_CLASS_HASH),
Expand Down Expand Up @@ -473,8 +491,9 @@ mod tests {

assert_eq!(
actual_state_updates.state_updates.deployed_contracts.len(),
5,
"5 contracts should be created: ETH fee token, universal deployer, and 3 allocations"
6,
"6 contracts should be created: STRK fee token, ETH fee token, universal deployer, \
and 3 allocations"
);

let alloc_1_addr = allocations[0].0;
Expand Down Expand Up @@ -566,9 +585,33 @@ mod tests {
Some(&total_supply_high)
);

// check STRK fee token contract storage

let strk_name = cairo_short_string_to_felt("Starknet Token").unwrap();
let strk_symbol = cairo_short_string_to_felt("STRK").unwrap();
let strk_decimals = Felt::from(18);

let strk_fee_token_storage = actual_state_updates
.state_updates
.storage_updates
.get(&DEFAULT_STRK_FEE_TOKEN_ADDRESS)
.unwrap();

assert_eq!(strk_fee_token_storage.get(&ERC20_NAME_STORAGE_SLOT), Some(&strk_name));
assert_eq!(strk_fee_token_storage.get(&ERC20_SYMBOL_STORAGE_SLOT), Some(&strk_symbol));
assert_eq!(strk_fee_token_storage.get(&ERC20_DECIMAL_STORAGE_SLOT), Some(&strk_decimals));
assert_eq!(
strk_fee_token_storage.get(&ERC20_TOTAL_SUPPLY_STORAGE_SLOT),
Some(&total_supply_low)
);
assert_eq!(
strk_fee_token_storage.get(&(ERC20_TOTAL_SUPPLY_STORAGE_SLOT + Felt::ONE)),
Some(&total_supply_high)
);

let mut allocs_total_supply = U256::ZERO;

// check for balance in both ETH
// check for balance in both ETH and STRK
for (address, alloc) in &allocations {
if let Some(balance) = alloc.balance() {
let (low, high) = split_u256(balance);
Expand All @@ -584,6 +627,9 @@ mod tests {
assert_eq!(eth_fee_token_storage.get(&low_bal_storage_var), Some(&low));
assert_eq!(eth_fee_token_storage.get(&high_bal_storage_var), Some(&high));

assert_eq!(strk_fee_token_storage.get(&low_bal_storage_var), Some(&low));
assert_eq!(strk_fee_token_storage.get(&high_bal_storage_var), Some(&high));

allocs_total_supply += balance;
}
}
Expand All @@ -602,5 +648,16 @@ mod tests {
Some(&actual_total_supply_high),
"ETH total supply must be calculated from allocations balances correctly"
);

assert_eq!(
strk_fee_token_storage.get(&ERC20_TOTAL_SUPPLY_STORAGE_SLOT),
Some(&actual_total_supply_low),
"STRK total supply must be calculated from allocations balances correctly"
);
assert_eq!(
strk_fee_token_storage.get(&(ERC20_TOTAL_SUPPLY_STORAGE_SLOT + Felt::ONE)),
Some(&actual_total_supply_high),
"STRK total supply must be calculated from allocations balances correctly"
);
}
}
37 changes: 34 additions & 3 deletions crates/katana/rpc/rpc/tests/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use katana_node::config::SequencingConfig;
use katana_primitives::event::ContinuationToken;
use katana_primitives::genesis::constant::{
DEFAULT_ACCOUNT_CLASS_HASH, DEFAULT_ETH_FEE_TOKEN_ADDRESS, DEFAULT_PREFUNDED_ACCOUNT_BALANCE,
DEFAULT_UDC_ADDRESS,
DEFAULT_STRK_FEE_TOKEN_ADDRESS, DEFAULT_UDC_ADDRESS,
};
use katana_rpc_api::dev::DevApiClient;
use starknet::accounts::{
Expand All @@ -25,8 +25,8 @@ use starknet::accounts::{
use starknet::core::types::contract::legacy::LegacyContractClass;
use starknet::core::types::{
BlockId, BlockTag, Call, DeclareTransactionReceipt, DeployAccountTransactionReceipt,
EventFilter, EventsPage, ExecutionResult, Felt, StarknetError, TransactionFinalityStatus,
TransactionReceipt, TransactionTrace,
EventFilter, EventsPage, ExecutionResult, Felt, StarknetError, TransactionExecutionStatus,
TransactionFinalityStatus, TransactionReceipt, TransactionTrace,
};
use starknet::core::utils::get_contract_address;
use starknet::macros::{felt, selector};
Expand Down Expand Up @@ -894,3 +894,34 @@ async fn block_traces() -> Result<()> {

Ok(())
}

// Test that the v3 transactions are working as expected. The expectation is that the v3 transaction
// will be using STRK fee token as its gas fee. So, the STRK fee token must exist in the chain in
// order for this to pass.
#[tokio::test]
async fn v3_transactions() -> Result<()> {
let config =
get_default_test_config(SequencingConfig { no_mining: true, ..Default::default() });
let sequencer = TestSequencer::start(config).await;

let provider = sequencer.provider();
let account = sequencer.account();

// craft a raw v3 transaction, should probably use abigen for simplicity
let to = DEFAULT_STRK_FEE_TOKEN_ADDRESS.into();
let selector = selector!("transfer");
let calldata = vec![felt!("0x1"), felt!("0x1"), Felt::ZERO];

let res = account
.execute_v3(vec![Call { to, selector, calldata }])
.gas(100000000000)
.send()
.await
.inspect_err(|e| println!("transaction failed: {e:?}"))?;

let receipt = dojo_utils::TransactionWaiter::new(res.transaction_hash, &provider).await?;
let status = receipt.receipt.execution_result().status();
assert_eq!(status, TransactionExecutionStatus::Succeeded);

Ok(())
}

0 comments on commit 542df4f

Please sign in to comment.