From b79489f7bea89a3bc9ef6e5d3e19d6f6755eae58 Mon Sep 17 00:00:00 2001 From: Dori Medini Date: Thu, 30 Apr 2026 16:58:37 +0300 Subject: [PATCH] central_systest_blobs: deploy token contract --- .../resources/blob_file_generation | 2 +- .../resources/preconfirmed_block.json | 156 +++++++++++++++--- .../src/cende_blob_regression_test.rs | 131 ++++++++++++++- 3 files changed, 256 insertions(+), 33 deletions(-) diff --git a/crates/central_systest_blobs/resources/blob_file_generation b/crates/central_systest_blobs/resources/blob_file_generation index c7930257dfe..301160a9306 100644 --- a/crates/central_systest_blobs/resources/blob_file_generation +++ b/crates/central_systest_blobs/resources/blob_file_generation @@ -1 +1 @@ -7 \ No newline at end of file +8 \ No newline at end of file diff --git a/crates/central_systest_blobs/resources/preconfirmed_block.json b/crates/central_systest_blobs/resources/preconfirmed_block.json index 683d4d0d346..d2f96c67888 100644 --- a/crates/central_systest_blobs/resources/preconfirmed_block.json +++ b/crates/central_systest_blobs/resources/preconfirmed_block.json @@ -1,5 +1,5 @@ { - "block_number": 2, + "block_number": 3, "pre_confirmed_block": { "l1_da_mode": "CALLDATA", "l1_data_gas_price": { @@ -17,33 +17,79 @@ "sequencer_address": "0x1000", "starknet_version": "0.14.3", "status": "PRE_CONFIRMED", - "timestamp": 1002, + "timestamp": 1003, "transaction_receipts": [ { - "actual_fee": "0xf8a7b", - "events": [], + "actual_fee": "0x64355d", + "events": [ + { + "data": [ + "0x0", + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", + "0xffffffffffffffffffffffffffffffff", + "0x0" + ], + "from_address": "0x6bd1d71a2fb67a567618584ca31da288dbc2e1a8421e4045e05f52c19bfab83", + "keys": [ + "0x99cd8bde557814842a3121e8ddfd433a539b8c9f14bf31ebf108d12e6196e9" + ] + }, + { + "data": [ + "0x3711c9d994faf6055172091cb841fd4831aa743e6f3315163b06a122c841846", + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955" + ], + "from_address": "0x6bd1d71a2fb67a567618584ca31da288dbc2e1a8421e4045e05f52c19bfab83", + "keys": [ + "0x9d4a59b844ac9d98627ddba326ab3707a7d7e105fd03c777569d0f61a91f1e" + ] + }, + { + "data": [ + "0x3711c9d994faf6055172091cb841fd4831aa743e6f3315163b06a122c841846", + "0x0", + "0x3711c9d994faf6055172091cb841fd4831aa743e6f3315163b06a122c841846" + ], + "from_address": "0x6bd1d71a2fb67a567618584ca31da288dbc2e1a8421e4045e05f52c19bfab83", + "keys": [ + "0x2b23b0c08c7b22209aea4100552de1b7876a49f04ee5a4d94f83ad24bc4ec1c" + ] + }, + { + "data": [ + "0x251e864ca2a080f55bce5da2452e8cfcafdbc951a3e7fff5023d558452ec228", + "0x0", + "0x3711c9d994faf6055172091cb841fd4831aa743e6f3315163b06a122c841846" + ], + "from_address": "0x6bd1d71a2fb67a567618584ca31da288dbc2e1a8421e4045e05f52c19bfab83", + "keys": [ + "0x2b23b0c08c7b22209aea4100552de1b7876a49f04ee5a4d94f83ad24bc4ec1c" + ] + } + ], "execution_resources": { "builtin_instance_counter": { - "pedersen_builtin": 12, - "poseidon_builtin": 12, - "range_check_builtin": 93 + "pedersen_builtin": 4, + "poseidon_builtin": 21, + "range_check_builtin": 90 }, "data_availability": { "l1_data_gas": 0, - "l1_gas": 3305, + "l1_gas": 15115, "l2_gas": 0 }, "n_memory_holes": 0, - "n_steps": 4602, + "n_steps": 4442, "total_gas_consumed": { "l1_data_gas": 0, - "l1_gas": 3856, - "l2_gas": 1014635 + "l1_gas": 21176, + "l2_gas": 6546085 } }, "execution_status": "SUCCEEDED", "l2_to_l1_messages": [], - "transaction_hash": "0x3eb7b9db643a241dbb7bb6fcef605d767e2cd3acd626284587afac4507e52de", + "transaction_hash": "0x1d4338e4e7b409a7ebb487b65fdbe6ac72fb5af7c513ac7d1e955445c75526e", "transaction_index": 0 } ], @@ -52,21 +98,61 @@ "declared_classes": [], "deployed_contracts": [ { - "address": "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", - "class_hash": "0x77fcf11f339d18db724aa522729b4c0e4e04aa85a6f104c10b469c020207dc1" + "address": "0x6bd1d71a2fb67a567618584ca31da288dbc2e1a8421e4045e05f52c19bfab83", + "class_hash": "0x15b873cb22fcde9b9af95b5e72b0a00219fa73a393467325ff0407e0fa0c7" } ], "migrated_compiled_classes": [], "nonces": { - "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955": "0x1" + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955": "0x2" }, "old_declared_contracts": [], "replaced_classes": [], "storage_diffs": { - "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955": [ + "0x6bd1d71a2fb67a567618584ca31da288dbc2e1a8421e4045e05f52c19bfab83": [ + { + "key": "0x3fc801c47df4de8d5835f8bfd4d0b8823ba63e5a3f278086901402d680abfc", + "value": "0xa" + }, + { + "key": "0xb6ce5410fca59d078ee9b2a4371a9d684c530d697c64fbef0ae6d5e8f0ac72", + "value": "0x5354524b" + }, + { + "key": "0x110e2f729c9c2b988559994a3daccd838cf52faf88e18101373e67dd061455a", + "value": "0xffffffffffffffffffffffffffffffff" + }, + { + "key": "0x1390569bb0a3a722eb4228e8700301347da081211d5c2ded2db22ef389551ab", + "value": "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955" + }, + { + "key": "0x1f0d4aa99431d246bac9b8e48c33e888245b15e9678f64f9bdfc8823dc8f979", + "value": "0x12" + }, + { + "key": "0x341c1bdfd89f69748aa00b5742b03adbffd79b8e80cab5c50d91cd8c2a79be1", + "value": "0x537461726b4e657420546f6b656e" + }, + { + "key": "0x38bb9518f707d6868da0178f4ac498e320441f8f7e11ff8a35ed4ea8286e693", + "value": "0x4cc2702427a1c4fae71487e57751056b882e8ff488e5d0a128e221502e130fd" + }, + { + "key": "0x51ff9d8e3b9d9153881c6d021c07e41e820360c3abbff54b127a8bc6d613574", + "value": "0x3711c9d994faf6055172091cb841fd4831aa743e6f3315163b06a122c841846" + }, + { + "key": "0x67eebb8a37da29031c921351ac6573033c0e3db1d2f205e01a4339afd272a14", + "value": "0x3711c9d994faf6055172091cb841fd4831aa743e6f3315163b06a122c841846" + }, + { + "key": "0x6fba6554adab51d0272b896b6f41768bd0491e5ad59c39fab38e65767974793", + "value": "0xffffffffffffffffffffffffffffffff" + }, { - "key": "0x3b28019ccfdbd30ffc65951d94bb85c9e2b8434111a000b5afd533ce65f57a4", - "value": "0x411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20" + "key": "0x7fe3b989a8a0b6382b1cd4c7ff6437964c6d78cbe865f9c6f75678414fba139", + "value": "0x1" } ] } @@ -74,15 +160,31 @@ ], "transactions": [ { - "class_hash": "0x77fcf11f339d18db724aa522729b4c0e4e04aa85a6f104c10b469c020207dc1", - "constructor_calldata": [ - "0x411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20" + "account_deployment_data": [], + "calldata": [ + "0x1", + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", + "0x2730079d734ee55315f4f141eaed376bddd8c2133523d223a344c5604e0f7f8", + "0xd", + "0x15b873cb22fcde9b9af95b5e72b0a00219fa73a393467325ff0407e0fa0c7", + "0x0", + "0x9", + "0x537461726b4e657420546f6b656e", + "0x5354524b", + "0x12", + "0xffffffffffffffffffffffffffffffff", + "0x0", + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", + "0xa", + "0x0" ], - "contract_address_salt": "0x0", "fee_data_availability_mode": 0, - "nonce": "0x0", + "nonce": "0x1", "nonce_data_availability_mode": 0, "paymaster_data": [], + "proof_facts": [], "resource_bounds": { "L1_DATA_GAS": { "max_amount": "0x0", @@ -99,12 +201,12 @@ }, "sender_address": "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", "signature": [ - "0x4bf92970c40634da1a0452af752326723ae810809c676aa06fa5ef76e77cc26", - "0x715137c17ff9a873f7d05def6648c93ee7fe0715ad3f21fbb1b59ed76bb1193" + "0x3350c14db6f907c832c5ba9841e154465e577448023b00319ae8547c2d5eef1", + "0x71c8b5707779bd454fd89a7119d36c1d733704badf2cb3624054aaa15c0601f" ], "tip": "0x0", - "transaction_hash": "0x3eb7b9db643a241dbb7bb6fcef605d767e2cd3acd626284587afac4507e52de", - "type": "DEPLOY_ACCOUNT", + "transaction_hash": "0x1d4338e4e7b409a7ebb487b65fdbe6ac72fb5af7c513ac7d1e955445c75526e", + "type": "INVOKE_FUNCTION", "version": "0x3" } ] diff --git a/crates/central_systest_blobs/src/cende_blob_regression_test.rs b/crates/central_systest_blobs/src/cende_blob_regression_test.rs index c714d36566c..8b3dd8349d7 100644 --- a/crates/central_systest_blobs/src/cende_blob_regression_test.rs +++ b/crates/central_systest_blobs/src/cende_blob_regression_test.rs @@ -34,6 +34,7 @@ use blockifier::transaction::account_transaction::AccountTransaction as Blockifi use blockifier::transaction::transaction_execution::Transaction as BlockifierTx; use blockifier::transaction::transactions::ExecutableTransaction; use blockifier_test_utils::cairo_versions::{CairoVersion, RunnableCairo1}; +use blockifier_test_utils::calldata::create_calldata; use blockifier_test_utils::contracts::FeatureContract; use expect_test::expect_file; use google_cloud_storage::client::{Client, ClientConfig}; @@ -53,30 +54,42 @@ use starknet_api::block_hash::block_hash_calculator::{ }; use starknet_api::consensus_transaction::InternalConsensusTransaction; use starknet_api::contract_class::compiled_class_hash::HashVersion; -use starknet_api::core::{ChainId, Nonce, OsChainInfo}; +use starknet_api::core::{ChainId, ContractAddress, Nonce, OsChainInfo}; use starknet_api::data_availability::{DataAvailabilityMode, L1DataAvailabilityMode}; use starknet_api::executable_transaction::{ AccountTransaction as ExecutableAccountTx, DeclareTransaction as ExecutableDeclareTx, DeployAccountTransaction as ExecutableDeployAccountTx, + InvokeTransaction as ExecutableInvokeTx, Transaction as ExecutableTx, }; +use starknet_api::execution_resources::GasAmount; use starknet_api::hash::StateRoots; use starknet_api::rpc_transaction::{ InternalRpcDeclareTransactionV3, InternalRpcDeployAccountTransaction, + InternalRpcInvokeTransactionV3, InternalRpcTransaction, InternalRpcTransactionWithoutTxHash, RpcDeployAccountTransaction, RpcDeployAccountTransactionV3, }; use starknet_api::state::ThinStateDiff; -use starknet_api::test_utils::TEST_SEQUENCER_ADDRESS; +use starknet_api::test_utils::{ + NonceManager, + DEFAULT_STRK_L1_DATA_GAS_PRICE, + DEFAULT_STRK_L1_GAS_PRICE, + DEFAULT_STRK_L2_GAS_PRICE, + TEST_SEQUENCER_ADDRESS, +}; use starknet_api::transaction::fields::{ AccountDeploymentData, AllResourceBounds, + Calldata, ContractAddressSalt, PaymasterData, + ProofFacts, + ResourceBounds, Tip, TransactionSignature, }; @@ -84,6 +97,7 @@ use starknet_api::transaction::{ CalculateContractAddress, DeclareTransaction, DeployAccountTransaction, + InvokeTransaction, TransactionHash, TransactionHasher, TransactionOffsetInBlock, @@ -113,6 +127,22 @@ static CHAIN_ID: LazyLock = const CHAIN_INFO_PATH: &str = "../resources/chain_info.json"; const PRECONFIRMED_BLOCK_PATH: &str = "../resources/preconfirmed_block.json"; +static NON_TRIVIAL_RESOURCE_BOUNDS: LazyLock = + LazyLock::new(|| AllResourceBounds { + l1_gas: ResourceBounds { + max_amount: GasAmount(100_000_000), + max_price_per_unit: DEFAULT_STRK_L1_GAS_PRICE.into(), + }, + l2_gas: ResourceBounds { + max_amount: GasAmount(100_000_000_000_000_000), + max_price_per_unit: DEFAULT_STRK_L2_GAS_PRICE.into(), + }, + l1_data_gas: ResourceBounds { + max_amount: GasAmount(100_000), + max_price_per_unit: DEFAULT_STRK_L1_DATA_GAS_PRICE.into(), + }, + }); + type TxPair = (ExecutableAccountTx, InternalConsensusTransaction); /// ID of the current blobs file. @@ -207,6 +237,7 @@ struct BlobFactory { next_txs: Vec, // Context. + nonce_manager: NonceManager, state: DictStateReader, committer_storage: FactsDb, } @@ -222,6 +253,7 @@ impl BlobFactory { class_manager: MockClassManagerClient::default(), blocks: vec![], next_txs: vec![], + nonce_manager: NonceManager::default(), state: DictStateReader::default(), committer_storage: FactsDb::new(MapStorage::default()), } @@ -380,6 +412,15 @@ impl BlobFactory { TransactionSignature(Arc::new(vec![sig.r, sig.s])) } + fn single_multicall_data( + address: ContractAddress, + function_name: &str, + calldata: &[Felt], + ) -> Calldata { + let single_calldata = create_calldata(address, function_name, calldata); + Calldata(Arc::new([vec![Felt::ONE], single_calldata.0.as_slice().to_vec()].concat())) + } + fn boostrap_declare_tx(&mut self, contract: FeatureContract) { let sender_address = ExecutableDeclareTx::bootstrap_address(); let sierra = contract.get_sierra(); @@ -435,7 +476,7 @@ impl BlobFactory { self.next_txs.push((executable.into(), internal_tx)); } - fn make_free_deploy_account_tx(&mut self, account: FeatureContract) { + fn make_free_deploy_account_tx(&mut self, account: FeatureContract) -> ContractAddress { let class_hash = account.get_sierra().calculate_class_hash(); let public_key = get_public_key(&Self::OPERATOR_PRIVATE_KEY); let constructor_calldata = calldata![public_key]; @@ -463,6 +504,9 @@ impl BlobFactory { let tx_hash = without_hash_unsigned.calculate_transaction_hash(&CHAIN_ID).unwrap(); let signature = Self::sign_tx(tx_hash); + // Bump nonce for next txs. + self.nonce_manager.next(contract_address); + let mut rpc_tx_signed = rpc_tx_unsigned; rpc_tx_signed.signature = signature; let without_hash = InternalRpcTransactionWithoutTxHash::DeployAccount( @@ -482,6 +526,66 @@ impl BlobFactory { tx_hash, }); self.next_txs.push((executable.into(), internal)); + contract_address + } + + fn make_operator_deploy_tx( + &mut self, + operator_address: ContractAddress, + contract_to_deploy: FeatureContract, + constructor_calldata: Calldata, + with_fee_charge: bool, + ) { + let class_hash = contract_to_deploy.get_sierra().calculate_class_hash(); + let contract_address_salt = ContractAddressSalt::default(); + let nonce = self.nonce_manager.next(operator_address); + let resource_bounds = if with_fee_charge { + *NON_TRIVIAL_RESOURCE_BOUNDS + } else { + AllResourceBounds::new_unlimited_gas_no_fee_enforcement() + }; + let calldata = Self::single_multicall_data( + operator_address, + "deploy_contract", + &[ + vec![ + *class_hash, + contract_address_salt.0, + Felt::from(constructor_calldata.0.len()), + ], + constructor_calldata.0.as_slice().to_vec(), + vec![false.into()], // Deploy from zero. + ] + .concat(), + ); + let rpc_tx_unsigned = InternalRpcInvokeTransactionV3 { + sender_address: operator_address, + calldata, + signature: TransactionSignature::default(), + resource_bounds, + tip: Tip::default(), + nonce, + nonce_data_availability_mode: DataAvailabilityMode::L1, + fee_data_availability_mode: DataAvailabilityMode::L1, + account_deployment_data: AccountDeploymentData::default(), + paymaster_data: PaymasterData::default(), + proof_facts: ProofFacts::default(), + }; + let tx_hash = rpc_tx_unsigned + .calculate_transaction_hash(&CHAIN_ID, &TransactionVersion::THREE) + .unwrap(); + let signature = Self::sign_tx(tx_hash); + let mut rpc_tx_signed = rpc_tx_unsigned; + rpc_tx_signed.signature = signature; + let without_hash = InternalRpcTransactionWithoutTxHash::Invoke(rpc_tx_signed.clone()); + let executable = + ExecutableInvokeTx::create(InvokeTransaction::V3(rpc_tx_signed.into()), &CHAIN_ID) + .unwrap(); + let internal = InternalConsensusTransaction::RpcTransaction(InternalRpcTransaction { + tx: without_hash, + tx_hash, + }); + self.next_txs.push((executable.into(), internal)); } // ===================== @@ -676,9 +780,9 @@ async fn test_make_data() { // 1. bootstrap declare of an ERC20 contract. // 2. bootstrap declare of an account with real validate. // 3. deploy account (with zero fees). - // TODO(Dori): the rest of the txs. // 4. deploy ERC20 contract from the account (with zero fees), while minting some tokens to the // sender account. + // TODO(Dori): the rest of the txs. // (from this point - all txs include non-zero fees, and no more bootstrap declares) // 5. declare the test contract. // 6. deploy the test contract. @@ -691,7 +795,24 @@ async fn test_make_data() { blob_factory.close_block().await; blob_factory.boostrap_declare_tx(account_with_real_validate); blob_factory.close_block().await; - blob_factory.make_free_deploy_account_tx(account_with_real_validate); + let operator_address = blob_factory.make_free_deploy_account_tx(account_with_real_validate); + blob_factory.close_block().await; + blob_factory.make_operator_deploy_tx( + operator_address, + erc20_contract, + calldata![ + Felt::from_bytes_be_slice(b"StarkNet Token"), + Felt::from_bytes_be_slice(b"STRK"), + Felt::from(18u8), + u128::MAX.into(), // initial supply lsb + 0.into(), // initial supply msb + **operator_address, // recipient address + **operator_address, // permitted minter + **operator_address, // provisional_governance_admin + 10.into() // upgrade delay + ], + false, // charge fee + ); let (blobs, preconfirmed_block) = blob_factory.finalize().await; expect_file![CHAIN_INFO_PATH].assert_eq(&serde_json::to_string_pretty(&chain_info).unwrap());