From ae194eab17ca7d906ba15454f8709a2d6b2e1914 Mon Sep 17 00:00:00 2001 From: 0xK2 <65908739+thomas192@users.noreply.github.com> Date: Tue, 12 Mar 2024 22:35:11 +0000 Subject: [PATCH] feat: allow freezing blobstreamx (#113) * Added frozen functionality --------- Co-authored-by: Brandon R <54774639+b-j-roberts@users.noreply.github.com> --- src/blobstreamx.cairo | 18 ++- src/interfaces.cairo | 9 +- src/succinctx/tests/test_fee_vault.cairo | 143 +++++++++++------------ src/tests/common.cairo | 23 ++-- src/tests/test_blobstreamx.cairo | 17 ++- src/tests/test_ownable.cairo | 7 +- src/tests/test_upgradeable.cairo | 11 +- 7 files changed, 129 insertions(+), 99 deletions(-) diff --git a/src/blobstreamx.cairo b/src/blobstreamx.cairo index 847cfb0..716b13c 100644 --- a/src/blobstreamx.cairo +++ b/src/blobstreamx.cairo @@ -33,6 +33,7 @@ mod blobstreamx { block_height_to_header_hash: LegacyMap::, header_range_function_id: u256, next_header_function_id: u256, + frozen: bool, #[substorage(v0)] ownable: OwnableComponent::Storage, #[substorage(v0)] @@ -100,7 +101,8 @@ mod blobstreamx { } mod Errors { - const DataCommitmentNotFound: felt252 = 'bad data commitment for range'; + const DataCommitmentNotFound: felt252 = 'Bad data commitment for range'; + const ContractFrozen: felt252 = 'Contract is frozen'; } #[constructor] @@ -121,6 +123,7 @@ mod blobstreamx { self.block_height_to_header_hash.write(height, header); self.header_range_function_id.write(header_range_function_id); self.next_header_function_id.write(next_header_function_id); + self.frozen.write(false); } #[abi(embed_v0)] @@ -136,6 +139,8 @@ mod blobstreamx { fn verify_attestation( self: @ContractState, proof_nonce: u64, root: DataRoot, proof: BinaryMerkleProof ) -> bool { + assert(!self.frozen.read(), Errors::ContractFrozen); + if (proof_nonce >= self.state_proof_nonce.read()) { return false; } @@ -198,6 +203,13 @@ mod blobstreamx { self.ownable.assert_only_owner(); self.next_header_function_id.write(_function_id); } + fn get_frozen(self: @ContractState) -> bool { + self.frozen.read() + } + fn set_frozen(ref self: ContractState, _frozen: bool) { + self.ownable.assert_only_owner(); + self.frozen.write(_frozen); + } /// Request a header_range proof for the next header hash and a data commitment for the block range [latest_block, _target_block). /// Used to skip from the latest block to the target block. @@ -251,6 +263,8 @@ mod blobstreamx { /// /// * `_target_block` - The end block of the header range request fn commit_header_range(ref self: ContractState, _target_block: u64) { + assert(!self.frozen.read(), Errors::ContractFrozen); + let latest_block = self.get_latest_block(); let trusted_header = self.block_height_to_header_hash.read(latest_block); assert(trusted_header != 0, TendermintXErrors::TrustedHeaderNotFound); @@ -330,6 +344,8 @@ mod blobstreamx { /// /// * `_trusted_block` - The latest block when the request was made. fn commit_next_header(ref self: ContractState, _trusted_block: u64) { + assert(!self.frozen.read(), Errors::ContractFrozen); + let trusted_header = self.block_height_to_header_hash.read(_trusted_block); assert(trusted_header != 0, TendermintXErrors::TrustedHeaderNotFound); diff --git a/src/interfaces.cairo b/src/interfaces.cairo index d531a05..38995ce 100644 --- a/src/interfaces.cairo +++ b/src/interfaces.cairo @@ -47,18 +47,21 @@ trait IBlobstreamX { /// Max num of blocks that can be skipped in a single request /// ref: https://github.com/celestiaorg/celestia-core/blob/main/pkg/consts/consts.go#L43-L44 fn data_commitment_max(self: @TContractState) -> u64; - // Address of the gateway contract + // Address of the gateway contract. fn set_gateway(ref self: TContractState, new_gateway: ContractAddress); fn get_gateway(self: @TContractState) -> ContractAddress; // Nonce for proof events. Must be incremented sequentially fn get_state_proof_nonce(self: @TContractState) -> u64; - // Header range function id + // Header range function id. fn get_header_range_id(self: @TContractState) -> u256; fn set_header_range_id(ref self: TContractState, _function_id: u256); // Next header function id. fn get_next_header_id(self: @TContractState) -> u256; fn set_next_header_id(ref self: TContractState, _function_id: u256); - // Prove the validity of the header at the target block and a data commitment for the block range [latestBlock, _targetBlock) + // Contract freezing state. + fn get_frozen(self: @TContractState) -> bool; + fn set_frozen(ref self: TContractState, _frozen: bool); + // Prove the validity of the header at the target block and a data commitment for the block range [latestBlock, _targetBlock). fn request_header_range(ref self: TContractState, _target_block: u64); // Commits the new header at targetBlock and the data commitment for the block range [trustedBlock, targetBlock). fn commit_header_range(ref self: TContractState, _target_block: u64); diff --git a/src/succinctx/tests/test_fee_vault.cairo b/src/succinctx/tests/test_fee_vault.cairo index a5d95bb..cf8220e 100644 --- a/src/succinctx/tests/test_fee_vault.cairo +++ b/src/succinctx/tests/test_fee_vault.cairo @@ -5,9 +5,8 @@ use blobstream_sn::succinctx::function_registry::erc20_mock::{ use blobstream_sn::succinctx::interfaces::{IFeeVaultDispatcher, IFeeVaultDispatcherTrait}; use debug::PrintTrait; use openzeppelin::tests::utils::constants::{OWNER, NEW_OWNER, SPENDER}; -use snforge_std::{ - declare, ContractClassTrait, start_prank, stop_prank, CheatTarget, spy_events, SpyOn, EventSpy -}; +use snforge_std as snf; +use snforge_std::{ContractClassTrait, CheatTarget, SpyOn, EventSpy}; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::get_caller_address; @@ -15,10 +14,10 @@ const TOTAL_SUPPPLY: u256 = 0x100000000000000000000000000000001; fn setup_contracts() -> (IMockERC20Dispatcher, IFeeVaultDispatcher) { - let token_class = declare('MockERC20'); + let token_class = snf::declare('MockERC20'); let token_calldata = array!['FeeToken', 'FT']; let token_address = token_class.deploy(@token_calldata).unwrap(); - let fee_vault_class = declare('succinct_fee_vault'); + let fee_vault_class = snf::declare('succinct_fee_vault'); let fee_calldata = array![token_address.into(), OWNER().into()]; let fee_vault_address = fee_vault_class.deploy(@fee_calldata).unwrap(); ( @@ -31,22 +30,22 @@ fn setup_contracts() -> (IMockERC20Dispatcher, IFeeVaultDispatcher) { fn fee_vault_set_native_currency_address() { let (_, fee_vault) = setup_contracts(); let new_currency_address = contract_address_const::<0x12345>(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.set_native_currency(new_currency_address); assert( fee_vault.get_native_currency() == new_currency_address, 'wrong initial native currency' ); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] #[should_panic(expected: ('Invalid token',))] fn fee_vault_set_native_currency_address_fails_null_address() { let (_, fee_vault) = setup_contracts(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); let new_currency_address = contract_address_const::<0>(); fee_vault.set_native_currency(new_currency_address); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] @@ -60,7 +59,7 @@ fn test_vault_set_native_currency_fails_not_owner() { #[test] fn fee_vault_deductor_operations() { let (_, fee_vault) = setup_contracts(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); // Adding a new deductor fee_vault.add_deductor(SPENDER()); assert(fee_vault.is_deductor(SPENDER()), 'deductors not updated'); @@ -95,33 +94,33 @@ fn fee_vault_remove_deductor_fails_if_not_owner() { fn fee_vault_deposit_native() { let (erc20, fee_vault) = setup_contracts(); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); let fee = starknet::info::get_tx_info().unbox().max_fee.into(); erc20.approve(fee_vault.contract_address, fee); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit_native(SPENDER()); assert( fee_vault.get_account_balance(SPENDER(), erc20.contract_address) == fee, 'balances not updated' ); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] fn fee_vault_deposit() { let (erc20, fee_vault) = setup_contracts(); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x10000); assert( fee_vault.get_account_balance(SPENDER(), erc20.contract_address) == 0x10000, 'balances deposit not updated' ); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] @@ -143,27 +142,27 @@ fn fee_vault_deposit_fails_if_null_token() { fn fee_vault_deposit_fails_if_insufficent_allowance() { let (erc20, fee_vault) = setup_contracts(); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x10000); assert( fee_vault.get_account_balance(SPENDER(), erc20.contract_address) == 0x10000, 'balances deposit not updated' ); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] fn fee_vault_deduct_native() { let (erc20, fee_vault) = setup_contracts(); let fee = starknet::info::get_tx_info().unbox().max_fee.into(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.add_deductor(SPENDER()); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit_native(SPENDER()); assert( fee_vault.get_account_balance(SPENDER(), erc20.contract_address) == fee, @@ -174,27 +173,27 @@ fn fee_vault_deduct_native() { fee_vault.get_account_balance(SPENDER(), erc20.contract_address) == 0, 'balances deduct not updated' ); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] fn fee_vault_deduct() { let (erc20, fee_vault) = setup_contracts(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.add_deductor(SPENDER()); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x10000); fee_vault.deduct(SPENDER(), erc20.contract_address, 0x8000); assert( fee_vault.get_account_balance(SPENDER(), erc20.contract_address) == 0x10000 - 0x8000, 'balances deduct not updated' ); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] @@ -202,106 +201,106 @@ fn fee_vault_deduct() { fn fee_vault_deduct_fails_if_not_deductor() { let (erc20, fee_vault) = setup_contracts(); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x10000); fee_vault.deduct(SPENDER(), erc20.contract_address, 0x8000); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] #[should_panic(expected: ('Insufficent balance',))] fn fee_vault_deduct_fails_if_insufficent_balance() { let (erc20, fee_vault) = setup_contracts(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.add_deductor(SPENDER()); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x1000); fee_vault.deduct(SPENDER(), erc20.contract_address, 0x8000); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] fn fee_vault_collect() { let (erc20, fee_vault) = setup_contracts(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.add_deductor(SPENDER()); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x10000); fee_vault.deduct(SPENDER(), erc20.contract_address, 0x8000); - stop_prank(CheatTarget::One(fee_vault.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.collect(OWNER(), erc20.contract_address, 0x10000); assert(erc20.balance_of(OWNER()) == 0x10000, 'balance collect failed'); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] fn fee_vault_collect_native() { let (erc20, fee_vault) = setup_contracts(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.add_deductor(SPENDER()); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x10000); fee_vault.deduct(SPENDER(), erc20.contract_address, 0x8000); - stop_prank(CheatTarget::One(fee_vault.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.collect_native(OWNER(), 0x10000); assert(erc20.balance_of(OWNER()) == 0x10000, 'balance collect failed'); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] #[should_panic(expected: ('Caller is not the owner',))] fn fee_vault_collect_fails_if_not_owner() { let (erc20, fee_vault) = setup_contracts(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.add_deductor(SPENDER()); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x10000); fee_vault.collect(SPENDER(), erc20.contract_address, 0x10000); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } #[test] #[should_panic(expected: ('Insufficent balance',))] fn fee_vault_collect_fails_if_insufficent_balance() { let (erc20, fee_vault) = setup_contracts(); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.add_deductor(SPENDER()); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); erc20.mint_to(SPENDER(), 0x10000); - start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); + snf::start_prank(CheatTarget::One(erc20.contract_address), SPENDER()); erc20.approve(fee_vault.contract_address, 0x10000); - stop_prank(CheatTarget::One(erc20.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); + snf::stop_prank(CheatTarget::One(erc20.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), SPENDER()); fee_vault.deposit(SPENDER(), erc20.contract_address, 0x1000); - stop_prank(CheatTarget::One(fee_vault.contract_address)); - start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::start_prank(CheatTarget::One(fee_vault.contract_address), OWNER()); fee_vault.collect(OWNER(), erc20.contract_address, 0x10000); - stop_prank(CheatTarget::One(fee_vault.contract_address)); + snf::stop_prank(CheatTarget::One(fee_vault.contract_address)); } diff --git a/src/tests/common.cairo b/src/tests/common.cairo index ead239a..1ee6b0e 100644 --- a/src/tests/common.cairo +++ b/src/tests/common.cairo @@ -7,9 +7,8 @@ use blobstream_sn::succinctx::function_registry::interfaces::{ }; use blobstream_sn::succinctx::interfaces::{IFeeVaultDispatcher, IFeeVaultDispatcherTrait}; use openzeppelin::tests::utils::constants::OWNER; -use snforge_std::{ - declare, ContractClassTrait, start_prank, stop_prank, CheatTarget, spy_events, SpyOn, EventSpy -}; +use snforge_std as snf; +use snforge_std::{ContractClassTrait, CheatTarget, SpyOn, EventSpy}; use starknet::ContractAddress; // https://sepolia.etherscan.io/tx/0xadced8dc7f4bb01d730ed78daecbf9640417c5bd60b0ada23c9045cc953481a5#eventlog @@ -21,24 +20,24 @@ const NEXT_HEADER_DIGEST: u256 = 0xfd6c88812a160ff288fe557111815b3433c539c77a356 fn setup_base() -> ContractAddress { // deploy the token associated with the fee vault - let token_class = declare('MockERC20'); + let token_class = snf::declare('MockERC20'); let token_calldata = array!['FeeToken', 'FT']; let token_address = token_class.deploy(@token_calldata).unwrap(); // deploy the fee vault - let fee_vault_class = declare('succinct_fee_vault'); + let fee_vault_class = snf::declare('succinct_fee_vault'); let fee_calldata = array![token_address.into(), OWNER().into()]; let fee_vault_address = fee_vault_class.deploy(@fee_calldata).unwrap(); // deploy the succinct gateway - let succinct_gateway_class = declare('succinct_gateway'); + let succinct_gateway_class = snf::declare('succinct_gateway'); let gateway_addr = succinct_gateway_class .deploy(@array![OWNER().into(), fee_vault_address.into()]) .unwrap(); let gateway = IFunctionRegistryDispatcher { contract_address: gateway_addr }; // deploy the mock function verifier - let func_verifier_class = declare('function_verifier_mock'); + let func_verifier_class = snf::declare('function_verifier_mock'); let header_range_verifier = func_verifier_class .deploy(@array![HEADER_RANGE_DIGEST.low.into(), HEADER_RANGE_DIGEST.high.into()]) .unwrap(); @@ -53,7 +52,7 @@ fn setup_base() -> ContractAddress { .register_function(OWNER(), next_header_verifier, 'NEXT_HEADER'); // deploy blobstreamx - let blobstreamx_class = declare('blobstreamx'); + let blobstreamx_class = snf::declare('blobstreamx'); let calldata = array![ gateway_addr.into(), OWNER().into(), @@ -70,23 +69,23 @@ fn setup_base() -> ContractAddress { fn setup_spied() -> (ContractAddress, EventSpy) { let blobstreamx = setup_base(); - let mut spy = spy_events(SpyOn::One(blobstreamx)); + let mut spy = snf::spy_events(SpyOn::One(blobstreamx)); (blobstreamx, spy) } fn setup_succinct_gateway() -> ContractAddress { // deploy the token associated with the fee vault - let token_class = declare('MockERC20'); + let token_class = snf::declare('MockERC20'); let token_calldata = array!['FeeToken', 'FT']; let token_address = token_class.deploy(@token_calldata).unwrap(); // deploy the fee vault - let fee_vault_class = declare('succinct_fee_vault'); + let fee_vault_class = snf::declare('succinct_fee_vault'); let fee_calldata = array![token_address.into(), OWNER().into()]; let fee_vault_address = fee_vault_class.deploy(@fee_calldata).unwrap(); - let succinct_gateway_class = declare('succinct_gateway'); + let succinct_gateway_class = snf::declare('succinct_gateway'); let calldata = array![OWNER().into(), fee_vault_address.into()]; succinct_gateway_class.deploy(@calldata).unwrap() } diff --git a/src/tests/test_blobstreamx.cairo b/src/tests/test_blobstreamx.cairo index c0a1588..7917f33 100644 --- a/src/tests/test_blobstreamx.cairo +++ b/src/tests/test_blobstreamx.cairo @@ -10,7 +10,9 @@ use blobstream_sn::succinctx::interfaces::{ use blobstream_sn::tests::common::{ setup_base, setup_spied, setup_succinct_gateway, TEST_START_BLOCK, TEST_END_BLOCK, TEST_HEADER, }; -use snforge_std::{EventSpy, EventAssertions, store, map_entry_address}; +use openzeppelin::tests::utils::constants::OWNER; +use snforge_std as snf; +use snforge_std::{CheatTarget, EventSpy, EventAssertions}; use starknet::secp256_trait::Signature; use starknet::{ContractAddress, EthAddress, info::get_block_number}; @@ -161,9 +163,9 @@ fn blobstreamx_request_header_range_latest_header_null() { let bsx = setup_blobstreamx(); let latest_block = get_bsx_latest_block(bsx.contract_address); - store( + snf::store( bsx.contract_address, - map_entry_address( + snf::map_entry_address( selector!("block_height_to_header_hash"), array![latest_block.into()].span(), ), array![0, 0].span() @@ -185,3 +187,12 @@ fn blobstreamx_request_header_range_target_block_not_in_range_2() { let latest_block = get_bsx_latest_block(bsx.contract_address); bsx.request_header_range(latest_block + 1001); } + +#[test] +#[should_panic(expected: ('Contract is frozen',))] +fn blobstreamx_frozen() { + let bsx = setup_blobstreamx(); + snf::start_prank(CheatTarget::One(bsx.contract_address), OWNER()); + bsx.set_frozen(true); + bsx.commit_header_range(0); +} diff --git a/src/tests/test_ownable.cairo b/src/tests/test_ownable.cairo index 19e7d2d..abb18dc 100644 --- a/src/tests/test_ownable.cairo +++ b/src/tests/test_ownable.cairo @@ -2,8 +2,9 @@ use blobstream_sn::tests::common::{setup_base, setup_spied}; use openzeppelin::access::ownable::OwnableComponent; use openzeppelin::access::ownable::interface::{IOwnableDispatcher, IOwnableDispatcherTrait}; use openzeppelin::tests::utils::constants::{OWNER, NEW_OWNER}; +use snforge_std as snf; use snforge_std::cheatcodes::events::EventAssertions; -use snforge_std::{declare, start_prank, stop_prank, CheatTarget, EventSpy}; +use snforge_std::{CheatTarget, EventSpy}; fn setup_ownable() -> IOwnableDispatcher { IOwnableDispatcher { contract_address: setup_base() } @@ -19,9 +20,9 @@ fn blobstreamx_transfer_ownership() { let (ownable, mut spy) = setup_ownable_spied(); assert(ownable.owner() == OWNER().into(), 'initial owner wrong'); - start_prank(CheatTarget::One(ownable.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(ownable.contract_address), OWNER()); ownable.transfer_ownership(NEW_OWNER()); - stop_prank(CheatTarget::One(ownable.contract_address)); + snf::stop_prank(CheatTarget::One(ownable.contract_address)); assert(ownable.owner() == NEW_OWNER().into(), 'transfer owner failed'); diff --git a/src/tests/test_upgradeable.cairo b/src/tests/test_upgradeable.cairo index 1f592bd..a61c3c1 100644 --- a/src/tests/test_upgradeable.cairo +++ b/src/tests/test_upgradeable.cairo @@ -7,8 +7,9 @@ use openzeppelin::upgrades::interface::{ IUpgradeable, IUpgradeableDispatcher, IUpgradeableDispatcherTrait }; use openzeppelin::upgrades::upgradeable::UpgradeableComponent; +use snforge_std as snf; use snforge_std::cheatcodes::events::EventAssertions; -use snforge_std::{declare, start_prank, stop_prank, CheatTarget, EventSpy}; +use snforge_std::{CheatTarget, EventSpy}; const TEST_VAL: felt252 = 420; @@ -24,11 +25,11 @@ fn setup_upgradeable_spied() -> (IUpgradeableDispatcher, EventSpy) { #[test] fn blobstreamx_upgrade() { let (upgradeable, mut spy) = setup_upgradeable_spied(); - let v2_class = declare('mock_upgradeable'); + let v2_class = snf::declare('mock_upgradeable'); - start_prank(CheatTarget::One(upgradeable.contract_address), OWNER()); + snf::start_prank(CheatTarget::One(upgradeable.contract_address), OWNER()); upgradeable.upgrade(v2_class.class_hash); - stop_prank(CheatTarget::One(upgradeable.contract_address)); + snf::stop_prank(CheatTarget::One(upgradeable.contract_address)); let expected_event = UpgradeableComponent::Upgraded { class_hash: v2_class.class_hash }; spy @@ -51,6 +52,6 @@ fn blobstreamx_upgrade() { fn blobstreamx_upgrade_not_owner() { let upgradeable = setup_upgradeable(); - let v2_class = declare('mock_upgradeable'); + let v2_class = snf::declare('mock_upgradeable'); upgradeable.upgrade(v2_class.class_hash); }