diff --git a/crates/katana/rpc/rpc/tests/starknet.rs b/crates/katana/rpc/rpc/tests/starknet.rs index 786d76a9a9..8baf839196 100644 --- a/crates/katana/rpc/rpc/tests/starknet.rs +++ b/crates/katana/rpc/rpc/tests/starknet.rs @@ -3,7 +3,6 @@ use std::fs::{self}; use std::path::PathBuf; use std::sync::Arc; -use std::time::Duration; use anyhow::Result; use assert_matches::assert_matches; @@ -12,9 +11,8 @@ use dojo_test_utils::sequencer::{get_default_test_starknet_config, TestSequencer use indexmap::IndexSet; use katana_core::sequencer::SequencerConfig; use katana_primitives::genesis::constant::{ - DEFAULT_FEE_TOKEN_ADDRESS, DEFAULT_PREFUNDED_ACCOUNT_BALANCE, + DEFAULT_FEE_TOKEN_ADDRESS, DEFAULT_PREFUNDED_ACCOUNT_BALANCE, DEFAULT_UDC_ADDRESS, }; -use katana_rpc_types::receipt::ReceiptBlock; use starknet::accounts::{ Account, AccountError, Call, ConnectedAccount, ExecutionEncoding, SingleOwnerAccount, }; @@ -23,169 +21,121 @@ use starknet::core::types::{ BlockId, BlockTag, DeclareTransactionReceipt, ExecutionResult, Felt, StarknetError, TransactionFinalityStatus, TransactionReceipt, }; -use starknet::core::utils::{get_contract_address, get_selector_from_name}; -use starknet::macros::felt; +use starknet::core::utils::get_contract_address; +use starknet::macros::{felt, selector}; use starknet::providers::{Provider, ProviderError}; use starknet::signers::{LocalWallet, SigningKey}; use tokio::sync::Mutex; mod common; -const WAIT_TX_DELAY_MILLIS: u64 = 1000; - -#[tokio::test(flavor = "multi_thread")] -async fn test_send_declare_and_deploy_contract() { +#[tokio::test] +async fn test_send_declare_and_deploy_contract() -> Result<()> { let sequencer = TestSequencer::start(SequencerConfig::default(), get_default_test_starknet_config()).await; + let account = sequencer.account(); + let provider = sequencer.provider(); let path: PathBuf = PathBuf::from("tests/test_data/cairo1_contract.json"); - let (contract, compiled_class_hash) = - common::prepare_contract_declaration_params(&path).unwrap(); + let (contract, compiled_class_hash) = common::prepare_contract_declaration_params(&path)?; let class_hash = contract.class_hash(); - let res = account.declare_v2(Arc::new(contract), compiled_class_hash).send().await.unwrap(); - - // wait for the tx to be mined - tokio::time::sleep(Duration::from_millis(WAIT_TX_DELAY_MILLIS)).await; - - let receipt = account.provider().get_transaction_receipt(res.transaction_hash).await.unwrap(); + let res = account.declare_v2(contract.into(), compiled_class_hash).send().await?; - match receipt.block { - ReceiptBlock::Block { .. } => { - let TransactionReceipt::Declare(DeclareTransactionReceipt { finality_status, .. }) = - receipt.receipt - else { - panic!("invalid tx receipt") - }; + // check that the tx is executed successfully and return the correct receipt + let receipt = dojo_utils::TransactionWaiter::new(res.transaction_hash, &provider).await?; + assert_matches!(receipt.receipt, TransactionReceipt::Declare(DeclareTransactionReceipt { .. })); - assert_eq!(finality_status, TransactionFinalityStatus::AcceptedOnL2); - } - - _ => panic!("invalid tx receipt"), - } - - assert!(account.provider().get_class(BlockId::Tag(BlockTag::Latest), class_hash).await.is_ok()); - - let constructor_calldata = vec![Felt::from(1_u32), Felt::from(2_u32)]; + // check that the class is actually declared + assert!(provider.get_class(BlockId::Tag(BlockTag::Pending), class_hash).await.is_ok()); + let ctor_args = vec![Felt::ONE, Felt::TWO]; let calldata = [ vec![ - res.class_hash, // class hash - Felt::ZERO, // salt - Felt::ZERO, // unique - Felt::from(constructor_calldata.len()), // constructor calldata len + res.class_hash, // class hash + Felt::ZERO, // salt + Felt::ZERO, // unique + Felt::from(ctor_args.len()), // constructor calldata len ], - constructor_calldata.clone(), + ctor_args.clone(), ] .concat(); - let contract_address = - get_contract_address(Felt::ZERO, res.class_hash, &constructor_calldata, Felt::ZERO); + // pre-compute the contract address of the would-be deployed contract + let address = get_contract_address(Felt::ZERO, res.class_hash, &ctor_args, Felt::ZERO); - account + let res = account .execute_v1(vec![Call { calldata, - // devnet UDC address - to: Felt::from_hex("0x41a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf") - .unwrap(), - selector: get_selector_from_name("deployContract").unwrap(), + to: DEFAULT_UDC_ADDRESS.into(), + selector: selector!("deployContract"), }]) .send() - .await - .unwrap(); + .await?; // wait for the tx to be mined - tokio::time::sleep(Duration::from_millis(WAIT_TX_DELAY_MILLIS)).await; - - assert_eq!( - account - .provider() - .get_class_hash_at(BlockId::Tag(BlockTag::Latest), contract_address) - .await - .unwrap(), - class_hash - ); + dojo_utils::TransactionWaiter::new(res.transaction_hash, &provider).await?; - sequencer.stop().expect("failed to stop sequencer"); + // make sure the contract is deployed + let res = provider.get_class_hash_at(BlockId::Tag(BlockTag::Pending), address).await?; + assert_eq!(res, class_hash); + + Ok(()) } -#[tokio::test(flavor = "multi_thread")] -async fn test_send_declare_and_deploy_legacy_contract() { +#[tokio::test] +async fn test_send_declare_and_deploy_legacy_contract() -> Result<()> { let sequencer = TestSequencer::start(SequencerConfig::default(), get_default_test_starknet_config()).await; + let account = sequencer.account(); + let provider = sequencer.provider(); let path = PathBuf::from("tests/test_data/cairo0_contract.json"); + let contract: LegacyContractClass = serde_json::from_reader(fs::File::open(path)?)?; - let legacy_contract: LegacyContractClass = - serde_json::from_reader(fs::File::open(path).unwrap()).unwrap(); - let contract_class = Arc::new(legacy_contract); + let class_hash = contract.class_hash()?; + let res = account.declare_legacy(contract.into()).send().await?; - let class_hash = contract_class.class_hash().unwrap(); - let res = account.declare_legacy(contract_class).send().await.unwrap(); - // wait for the tx to be mined - tokio::time::sleep(Duration::from_millis(WAIT_TX_DELAY_MILLIS)).await; - - let receipt = account.provider().get_transaction_receipt(res.transaction_hash).await.unwrap(); + let receipt = dojo_utils::TransactionWaiter::new(res.transaction_hash, &provider).await?; + assert_matches!(receipt.receipt, TransactionReceipt::Declare(DeclareTransactionReceipt { .. })); - match receipt.block { - ReceiptBlock::Block { .. } => { - let TransactionReceipt::Declare(DeclareTransactionReceipt { finality_status, .. }) = - receipt.receipt - else { - panic!("invalid tx receipt") - }; - - assert_eq!(finality_status, TransactionFinalityStatus::AcceptedOnL2); - } - - _ => panic!("invalid tx receipt"), - } - - assert!(account.provider().get_class(BlockId::Tag(BlockTag::Latest), class_hash).await.is_ok()); - - let constructor_calldata = vec![Felt::ONE]; + // check that the class is actually declared + assert!(provider.get_class(BlockId::Tag(BlockTag::Pending), class_hash).await.is_ok()); + let ctor_args = vec![Felt::ONE]; let calldata = [ vec![ - res.class_hash, // class hash - Felt::ZERO, // salt - Felt::ZERO, // unique - Felt::from(constructor_calldata.len()), // constructor calldata len + res.class_hash, // class hash + Felt::ZERO, // salt + Felt::ZERO, // unique + Felt::from(ctor_args.len()), // constructor calldata len ], - constructor_calldata.clone(), + ctor_args.clone(), ] .concat(); - let contract_address = - get_contract_address(Felt::ZERO, res.class_hash, &constructor_calldata.clone(), Felt::ZERO); + // pre-compute the contract address of the would-be deployed contract + let address = get_contract_address(Felt::ZERO, res.class_hash, &ctor_args.clone(), Felt::ZERO); - account + let res = account .execute_v1(vec![Call { calldata, - // devnet UDC address - to: Felt::from_hex("0x41a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf") - .unwrap(), - selector: get_selector_from_name("deployContract").unwrap(), + to: DEFAULT_UDC_ADDRESS.into(), + selector: selector!("deployContract"), }]) .send() - .await - .unwrap(); + .await?; // wait for the tx to be mined - tokio::time::sleep(Duration::from_millis(WAIT_TX_DELAY_MILLIS)).await; - - assert_eq!( - account - .provider() - .get_class_hash_at(BlockId::Tag(BlockTag::Latest), contract_address) - .await - .unwrap(), - class_hash - ); + dojo_utils::TransactionWaiter::new(res.transaction_hash, &provider).await?; + + // make sure the contract is deployed + let res = provider.get_class_hash_at(BlockId::Tag(BlockTag::Pending), address).await?; + assert_eq!(res, class_hash); - sequencer.stop().expect("failed to stop sequencer"); + Ok(()) } #[tokio::test]