diff --git a/.github/actions/install-starknet-foundry/action.yml b/.github/actions/install-starknet-foundry/action.yml index 02b9b59dc..8e4360edf 100644 --- a/.github/actions/install-starknet-foundry/action.yml +++ b/.github/actions/install-starknet-foundry/action.yml @@ -4,7 +4,7 @@ description: A composite action that installs the snforge and sncast binaries inputs: starknet_foundry_version: description: Starknet Foundry release version - default: "0.21.0" + default: "0.27.0" required: false runs: @@ -16,4 +16,3 @@ runs: run: | curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | sh snfoundryup -v ${{ inputs.starknet_foundry_version }} - diff --git a/.github/workflows/contracts.yml b/.github/workflows/contracts.yml index 58e06e4bc..d10fdfdc7 100644 --- a/.github/workflows/contracts.yml +++ b/.github/workflows/contracts.yml @@ -41,5 +41,8 @@ jobs: - name: Install Cairo uses: ./.github/actions/install-cairo + - name: Install Starknet Foundry + uses: ./.github/actions/install-starknet-foundry + - name: Test run: nix develop -c make test-cairo-contracts diff --git a/.gitignore b/.gitignore index 1ec5b7415..bf22810e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.snfoundry_cache .direnv artifacts/ vendor/ diff --git a/.tool-versions b/.tool-versions index b00c44d37..e3f251c90 100644 --- a/.tool-versions +++ b/.tool-versions @@ -11,6 +11,7 @@ actionlint 1.6.12 shellcheck 0.8.0 scarb 2.6.5 postgres 15.1 +starknet-foundry 0.27.0 # Kubernetes k3d 5.4.4 diff --git a/.vscode/settings.json b/.vscode/settings.json index bb4c99574..3f77e7328 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,7 @@ "editor.formatOnSave": true, "editor.formatOnSaveTimeout": 1500, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "files.insertFinalNewline": true } diff --git a/contracts/Scarb.lock b/contracts/Scarb.lock index 88a112553..0c0ba3523 100644 --- a/contracts/Scarb.lock +++ b/contracts/Scarb.lock @@ -1,14 +1,74 @@ # Code generated by scarb DO NOT EDIT. version = 1 +[[package]] +name = "alexandria_bytes" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_data_structures", + "alexandria_math", +] + +[[package]] +name = "alexandria_data_structures" +version = "0.2.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_encoding", +] + +[[package]] +name = "alexandria_encoding" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_bytes", + "alexandria_math", + "alexandria_numeric", +] + +[[package]] +name = "alexandria_math" +version = "0.2.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_data_structures", +] + +[[package]] +name = "alexandria_numeric" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_math", + "alexandria_searching", +] + +[[package]] +name = "alexandria_searching" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_data_structures", +] + [[package]] name = "chainlink" version = "0.1.0" dependencies = [ + "alexandria_bytes", + "alexandria_encoding", "openzeppelin", + "snforge_std", ] [[package]] name = "openzeppelin" version = "0.10.0" source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.10.0#d77082732daab2690ba50742ea41080eb23299d3" + +[[package]] +name = "snforge_std" +version = "0.27.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" diff --git a/contracts/Scarb.toml b/contracts/Scarb.toml index 69c519dfd..a84f65f83 100644 --- a/contracts/Scarb.toml +++ b/contracts/Scarb.toml @@ -7,6 +7,7 @@ homepage = "https://github.com/smartcontractkit/chainlink-starknet" [scripts] sierra = "cairo-compile . -r" +test = "snforge test" # Add your own custom commands and run them with scarb run # Uncomment if you want to use dependencies @@ -14,6 +15,9 @@ sierra = "cairo-compile . -r" [dependencies] starknet = ">=2.6.3" openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.10.0" } +alexandria_bytes = { git = "https://github.com/keep-starknet-strange/alexandria.git", rev = "bcdca70afdf59c9976148e95cebad5cf63d75a7f" } +alexandria_encoding = { git = "https://github.com/keep-starknet-strange/alexandria.git", rev = "bcdca70afdf59c9976148e95cebad5cf63d75a7f" } +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.27.0" } [lib] diff --git a/contracts/src/libraries/mocks.cairo b/contracts/src/libraries/mocks.cairo index 9a58bab7d..a6e8a7395 100644 --- a/contracts/src/libraries/mocks.cairo +++ b/contracts/src/libraries/mocks.cairo @@ -1,2 +1,3 @@ mod mock_upgradeable; mod mock_non_upgradeable; +mod mock_multisig_target; diff --git a/contracts/src/libraries/mocks/mock_multisig_target.cairo b/contracts/src/libraries/mocks/mock_multisig_target.cairo new file mode 100644 index 000000000..686fa976d --- /dev/null +++ b/contracts/src/libraries/mocks/mock_multisig_target.cairo @@ -0,0 +1,16 @@ +#[starknet::contract] +mod MockMultisigTarget { + use array::ArrayTrait; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl HelperImpl of HelperTrait { + #[external(v0)] + fn increment(ref self: ContractState, val1: felt252, val2: felt252) -> Array { + array![val1 + 1, val2 + 1] + } + } +} diff --git a/contracts/src/tests/test_access_controller.cairo b/contracts/src/tests/test_access_controller.cairo index 17d570978..a78715cf4 100644 --- a/contracts/src/tests/test_access_controller.cairo +++ b/contracts/src/tests/test_access_controller.cairo @@ -19,13 +19,18 @@ use chainlink::libraries::access_control::{ IAccessController, IAccessControllerDispatcher, IAccessControllerDispatcherTrait }; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + + fn STATE() -> AccessController::ContractState { AccessController::contract_state_for_testing() } fn setup() -> ContractAddress { let account: ContractAddress = contract_address_const::<777>(); - set_caller_address(account); + start_cheat_caller_address_global(account); account } @@ -44,10 +49,8 @@ fn test_access_control() { // Deploy access controller let calldata = array![owner.into(), // owner ]; - let (accessControllerAddr, _) = deploy_syscall( - AccessController::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (accessControllerAddr, _) = declare("AccessController").unwrap().deploy(@calldata).unwrap(); should_implement_access_control(accessControllerAddr, owner); } @@ -62,7 +65,7 @@ fn should_implement_access_control(contract_addr: ContractAddress, owner: Contra let contract = IAccessControllerDispatcher { contract_address: contract_addr }; let acc2: ContractAddress = contract_address_const::<2222987765>(); - set_contract_address(owner); // required to call contract as owner + start_cheat_caller_address_global(owner); // access check is enabled by default assert(!contract.has_access(acc2, array![]), 'should not have access'); diff --git a/contracts/src/tests/test_aggregator.cairo b/contracts/src/tests/test_aggregator.cairo index e2c3d81c3..77719d6f9 100644 --- a/contracts/src/tests/test_aggregator.cairo +++ b/contracts/src/tests/test_aggregator.cairo @@ -25,6 +25,10 @@ use chainlink::token::link_token::LinkToken; use chainlink::tests::test_ownable::should_implement_ownable; use chainlink::tests::test_access_controller::should_implement_access_control; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + #[test] fn test_pow_2_0() { assert(pow(2, 0) == 0x1, 'expected 0x1'); @@ -78,15 +82,17 @@ fn setup() -> ( let acc1: ContractAddress = contract_address_const::<777>(); let acc2: ContractAddress = contract_address_const::<888>(); // set acc1 as default caller - set_caller_address(acc1); + start_cheat_caller_address_global(acc1); // deploy billing access controller let calldata = array![acc1.into(), // owner = acc1; ]; - let (billingAccessControllerAddr, _) = deploy_syscall( - AccessController::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) + + let (billingAccessControllerAddr, _) = declare("AccessController") + .unwrap() + .deploy(@calldata) .unwrap(); + let billingAccessController = IAccessControllerDispatcher { contract_address: billingAccessControllerAddr }; @@ -95,10 +101,9 @@ fn setup() -> ( let calldata = array![acc1.into(), // minter = acc1; acc1.into(), // owner = acc1; ]; - let (linkTokenAddr, _) = deploy_syscall( - LinkToken::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (linkTokenAddr, _) = declare("LinkToken").unwrap().deploy(@calldata).unwrap(); + let linkToken = ILinkTokenDispatcher { contract_address: linkTokenAddr }; // return accounts, billing access controller, link token @@ -118,10 +123,8 @@ fn test_ownable() { 8, // decimals 123, // description ]; - let (aggregatorAddr, _) = deploy_syscall( - Aggregator::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (aggregatorAddr, _) = declare("Aggregator").unwrap().deploy(@calldata).unwrap(); should_implement_ownable(aggregatorAddr, account); } @@ -139,10 +142,13 @@ fn test_access_control() { 8, // decimals 123, // description ]; - let (aggregatorAddr, _) = deploy_syscall( - Aggregator::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (aggregatorAddr, _) = declare("Aggregator").unwrap().deploy(@calldata).unwrap(); + + // let (aggregatorAddr, _) = deploy_syscall( + // Aggregator::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false + // ) + // .unwrap(); should_implement_access_control(aggregatorAddr, account); } @@ -169,7 +175,7 @@ fn test_set_billing_access_controller_not_owner() { ); // set billing access controller should revert if caller is not owner - set_caller_address(acc2); + start_cheat_caller_address_global(acc2); BillingImpl::set_billing_access_controller(ref state, billingAccessController.contract_address); } @@ -196,7 +202,7 @@ fn test_set_billing_config_no_access() { gas_base: 1, gas_per_signature: 1, }; - set_caller_address(acc2); + start_cheat_caller_address_global(acc2); BillingImpl::set_billing(ref state, config); } @@ -237,7 +243,7 @@ fn test_set_billing_config_as_acc_with_access() { let (owner, acc2, billingAccessController, _) = setup(); let mut state = STATE(); // grant acc2 access on access controller - set_contract_address(owner); + start_cheat_caller_address_global(owner); billingAccessController.add_access(acc2); Aggregator::constructor( @@ -258,7 +264,7 @@ fn test_set_billing_config_as_acc_with_access() { gas_base: 1, gas_per_signature: 1, }; - set_caller_address(acc2); + start_cheat_caller_address_global(acc2); BillingImpl::set_billing(ref state, config); // check billing config @@ -281,9 +287,8 @@ fn test_set_payees_caller_not_owner() { ); let payees = array![PayeeConfig { transmitter: acc2, payee: acc2, },]; - // set payee should revert if caller is not owner - set_caller_address(acc2); + start_cheat_caller_address_global(acc2); PayeeManagementImpl::set_payees(ref state, payees); } @@ -296,8 +301,7 @@ fn test_set_single_payee() { ); let payees = array![PayeeConfig { transmitter: acc2, payee: acc2, },]; - - set_caller_address(owner); + start_cheat_caller_address_global(owner); PayeeManagementImpl::set_payees(ref state, payees); } @@ -313,8 +317,7 @@ fn test_set_multiple_payees() { PayeeConfig { transmitter: acc2, payee: acc2, }, PayeeConfig { transmitter: owner, payee: owner, }, ]; - - set_caller_address(owner); + start_cheat_caller_address_global(owner); PayeeManagementImpl::set_payees(ref state, payees); } @@ -330,7 +333,7 @@ fn test_transfer_payeeship_caller_not_payee() { let transmitter = contract_address_const::<123>(); let payees = array![PayeeConfig { transmitter: transmitter, payee: acc2, },]; - set_caller_address(owner); + start_cheat_caller_address_global(owner); PayeeManagementImpl::set_payees(ref state, payees); PayeeManagementImpl::transfer_payeeship(ref state, transmitter, owner); } @@ -347,9 +350,9 @@ fn test_transfer_payeeship_to_self() { let transmitter = contract_address_const::<123>(); let payees = array![PayeeConfig { transmitter: transmitter, payee: acc2, },]; - set_caller_address(owner); + start_cheat_caller_address_global(owner); PayeeManagementImpl::set_payees(ref state, payees); - set_caller_address(acc2); + start_cheat_caller_address_global(acc2); PayeeManagementImpl::transfer_payeeship(ref state, transmitter, acc2); } @@ -365,9 +368,9 @@ fn test_accept_payeeship_caller_not_proposed_payee() { let transmitter = contract_address_const::<123>(); let payees = array![PayeeConfig { transmitter: transmitter, payee: acc2, },]; - set_caller_address(owner); + start_cheat_caller_address_global(owner); PayeeManagementImpl::set_payees(ref state, payees); - set_caller_address(acc2); + start_cheat_caller_address_global(acc2); PayeeManagementImpl::transfer_payeeship(ref state, transmitter, owner); PayeeManagementImpl::accept_payeeship(ref state, transmitter); } @@ -383,11 +386,11 @@ fn test_transfer_and_accept_payeeship() { let transmitter = contract_address_const::<123>(); let payees = array![PayeeConfig { transmitter: transmitter, payee: acc2, },]; - set_caller_address(owner); + start_cheat_caller_address_global(owner); PayeeManagementImpl::set_payees(ref state, payees); - set_caller_address(acc2); + start_cheat_caller_address_global(acc2); PayeeManagementImpl::transfer_payeeship(ref state, transmitter, owner); - set_caller_address(owner); + start_cheat_caller_address_global(owner); PayeeManagementImpl::accept_payeeship(ref state, transmitter); } // --- Payments and Withdrawals Tests --- @@ -408,7 +411,7 @@ fn test_owed_payment_no_rounds() { let transmitter = contract_address_const::<123>(); let mut payees = array![PayeeConfig { transmitter: transmitter, payee: acc2, },]; - set_caller_address(owner); + start_cheat_caller_address_global(owner); PayeeManagementImpl::set_payees(ref state, payees); let owed = BillingImpl::owed_payment(@state, transmitter); diff --git a/contracts/src/tests/test_aggregator_proxy.cairo b/contracts/src/tests/test_aggregator_proxy.cairo index ef33d0f66..eb7e350bc 100644 --- a/contracts/src/tests/test_aggregator_proxy.cairo +++ b/contracts/src/tests/test_aggregator_proxy.cairo @@ -24,6 +24,11 @@ use chainlink::utils::split_felt; use chainlink::tests::test_ownable::should_implement_ownable; use chainlink::tests::test_access_controller::should_implement_access_control; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + + fn STATE() -> AggregatorProxy::ContractState { AggregatorProxy::contract_state_for_testing() } @@ -37,15 +42,17 @@ fn setup() -> ( ) { // Set account as default caller let account: ContractAddress = contract_address_const::<1>(); - set_caller_address(account); + + start_cheat_caller_address_global(account); // Deploy mock aggregator 1 let mut calldata = ArrayTrait::new(); calldata.append(8); // decimals = 8 - let (mockAggregatorAddr1, _) = deploy_syscall( - MockAggregator::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let contract_class = declare("MockAggregator").unwrap(); + + let (mockAggregatorAddr1, _) = contract_class.deploy(@calldata).unwrap(); + let mockAggregator1 = IMockAggregatorDispatcher { contract_address: mockAggregatorAddr1 }; // Deploy mock aggregator 2 @@ -53,10 +60,9 @@ fn setup() -> ( // so we need to change the decimals parameter to avoid an address conflict with mock aggregator 1 let mut calldata2 = ArrayTrait::new(); calldata2.append(10); // decimals = 10 - let (mockAggregatorAddr2, _) = deploy_syscall( - MockAggregator::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata2.span(), false - ) - .unwrap(); + + let (mockAggregatorAddr2, _) = contract_class.deploy(@calldata).unwrap(); + let mockAggregator2 = IMockAggregatorDispatcher { contract_address: mockAggregatorAddr2 }; // Return account, mock aggregator address and mock aggregator contract @@ -69,10 +75,7 @@ fn test_ownable() { // Deploy aggregator proxy let calldata = array![account.into(), // owner = account mockAggregatorAddr.into(),]; - let (aggregatorProxyAddr, _) = deploy_syscall( - AggregatorProxy::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + let (aggregatorProxyAddr, _) = declare("AggregatorProxy").unwrap().deploy(@calldata).unwrap(); should_implement_ownable(aggregatorProxyAddr, account); } @@ -83,10 +86,8 @@ fn test_access_control() { // Deploy aggregator proxy let calldata = array![account.into(), // owner = account mockAggregatorAddr.into(),]; - let (aggregatorProxyAddr, _) = deploy_syscall( - AggregatorProxy::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (aggregatorProxyAddr, _) = declare("AggregatorProxy").unwrap().deploy(@calldata).unwrap(); should_implement_access_control(aggregatorProxyAddr, account); } @@ -133,7 +134,7 @@ fn test_query_latest_round_data_without_access() { // insert round into mock aggregator mockAggregator.set_latest_round_data(10, 1, 9, 8); // set caller to non-owner address with no read access - set_caller_address(contract_address_const::<2>()); + start_cheat_caller_address_global(contract_address_const::<2>()); // query latest round AggregatorProxyImpl::latest_round_data(@state); } @@ -149,7 +150,7 @@ fn test_query_latest_answer_without_access() { // insert round into mock aggregator mockAggregator.set_latest_round_data(10, 1, 9, 8); // set caller to non-owner address with no read access - set_caller_address(contract_address_const::<2>()); + start_cheat_caller_address_global(contract_address_const::<2>()); // query latest round AggregatorProxyImpl::latest_answer(@state); } diff --git a/contracts/src/tests/test_erc677.cairo b/contracts/src/tests/test_erc677.cairo index 99b9c8fbf..b81394a21 100644 --- a/contracts/src/tests/test_erc677.cairo +++ b/contracts/src/tests/test_erc677.cairo @@ -16,6 +16,10 @@ use chainlink::token::mock::invalid_erc667_receiver::InvalidReceiver; use chainlink::libraries::token::erc677::ERC677Component; use chainlink::libraries::token::erc677::ERC677Component::ERC677Impl; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + #[starknet::interface] trait MockInvalidReceiver { fn set_supports(ref self: TContractState, value: bool); @@ -30,16 +34,15 @@ use chainlink::token::mock::valid_erc667_receiver::{ fn setup() -> ContractAddress { let account: ContractAddress = contract_address_const::<1>(); // Set account as default caller - set_caller_address(account); + start_cheat_caller_address_global(account); account } fn setup_valid_receiver() -> (ContractAddress, MockValidReceiverDispatcher) { let calldata = ArrayTrait::new(); - let (address, _) = deploy_syscall( - ValidReceiver::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (address, _) = declare("ValidReceiver").unwrap().deploy(@calldata).unwrap(); + let contract = MockValidReceiverDispatcher { contract_address: address }; (address, contract) } @@ -47,10 +50,9 @@ fn setup_valid_receiver() -> (ContractAddress, MockValidReceiverDispatcher) { fn setup_invalid_receiver() -> (ContractAddress, MockInvalidReceiverDispatcher) { let calldata = ArrayTrait::new(); - let (address, _) = deploy_syscall( - InvalidReceiver::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (address, _) = declare("InvalidReceiver").unwrap().deploy(@calldata).unwrap(); + let contract = MockInvalidReceiverDispatcher { contract_address: address }; (address, contract) } @@ -83,7 +85,7 @@ fn test_valid_transfer_and_call() { } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +#[should_panic] fn test_invalid_receiver_supports_interface_true() { setup(); let (receiver_address, receiver) = setup_invalid_receiver(); @@ -103,7 +105,7 @@ fn test_invalid_receiver_supports_interface_false() { #[test] -#[should_panic(expected: ('CONTRACT_NOT_DEPLOYED',))] +#[should_panic] fn test_nonexistent_receiver() { setup(); diff --git a/contracts/src/tests/test_link_token.cairo b/contracts/src/tests/test_link_token.cairo index 0c0fde3ed..1ee0f9946 100644 --- a/contracts/src/tests/test_link_token.cairo +++ b/contracts/src/tests/test_link_token.cairo @@ -17,6 +17,11 @@ use chainlink::token::link_token::LinkToken::{MintableToken, UpgradeableImpl}; use openzeppelin::token::erc20::ERC20Component::{ERC20Impl, ERC20MetadataImpl}; use chainlink::tests::test_ownable::should_implement_ownable; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + + // only tests link token specific functionality // erc20 and erc677 functionality is already tested elsewhere @@ -27,7 +32,7 @@ fn STATE() -> LinkToken::ContractState { fn setup() -> ContractAddress { let account: ContractAddress = contract_address_const::<1>(); // Set account as default caller - set_caller_address(account); + start_cheat_caller_address_global(account); account } @@ -38,10 +43,8 @@ fn test_ownable() { let mut calldata = ArrayTrait::new(); calldata.append(class_hash_const::<123>().into()); // minter calldata.append(account.into()); // owner - let (linkAddr, _) = deploy_syscall( - LinkToken::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (linkAddr, _) = declare("LinkToken").unwrap().deploy(@calldata).unwrap(); should_implement_ownable(linkAddr, account); } diff --git a/contracts/src/tests/test_mock_aggregator.cairo b/contracts/src/tests/test_mock_aggregator.cairo index e95b7b87e..af3387415 100644 --- a/contracts/src/tests/test_mock_aggregator.cairo +++ b/contracts/src/tests/test_mock_aggregator.cairo @@ -4,6 +4,10 @@ use chainlink::ocr2::mocks::mock_aggregator::MockAggregator; use starknet::contract_address_const; use chainlink::ocr2::aggregator::Round; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + fn STATE() -> MockAggregator::ContractState { MockAggregator::contract_state_for_testing() } @@ -11,7 +15,7 @@ fn STATE() -> MockAggregator::ContractState { fn setup() -> ContractAddress { let account: ContractAddress = contract_address_const::<777>(); // Set account as default caller - set_caller_address(account); + start_cheat_caller_address_global(account); account } diff --git a/contracts/src/tests/test_multisig.cairo b/contracts/src/tests/test_multisig.cairo index becfe4d7d..77eeb17b7 100644 --- a/contracts/src/tests/test_multisig.cairo +++ b/contracts/src/tests/test_multisig.cairo @@ -17,23 +17,10 @@ use chainlink::multisig::Multisig; use chainlink::multisig::Multisig::{MultisigImpl, UpgradeableImpl}; use chainlink::multisig::{IMultisigDispatcher}; -#[starknet::contract] -mod MultisigTest { - use array::ArrayTrait; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl HelperImpl of HelperTrait { - #[external(v0)] - fn increment(ref self: ContractState, val1: felt252, val2: felt252) -> Array { - array![val1 + 1, val2 + 1] - } - } -} - +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, cheat_caller_address, CheatSpan +}; fn STATE() -> Multisig::ContractState { Multisig::contract_state_for_testing() @@ -123,7 +110,7 @@ fn test_submit_transaction() { let signers = array![signer]; Multisig::constructor(ref state, :signers, threshold: 1); - set_caller_address(signer); + start_cheat_caller_address_global(signer); let to = contract_address_const::<42>(); let function_selector = 10; MultisigImpl::submit_transaction( @@ -147,7 +134,7 @@ fn test_submit_transaction_not_signer() { let signers = array![signer]; Multisig::constructor(ref state, :signers, threshold: 1); - set_caller_address(contract_address_const::<3>()); + start_cheat_caller_address_global(contract_address_const::<3>()); MultisigImpl::submit_transaction( ref state, to: contract_address_const::<42>(), @@ -164,7 +151,7 @@ fn test_confirm_transaction() { let signers = array![signer1, signer2]; Multisig::constructor(ref state, :signers, threshold: 2); - set_caller_address(signer1); + start_cheat_caller_address_global(signer1); MultisigImpl::submit_transaction( ref state, to: contract_address_const::<42>(), @@ -189,15 +176,14 @@ fn test_confirm_transaction_not_signer() { let not_signer = contract_address_const::<2>(); let signers = array![signer]; Multisig::constructor(ref state, :signers, threshold: 1); - set_caller_address(signer); + start_cheat_caller_address_global(signer); MultisigImpl::submit_transaction( ref state, to: contract_address_const::<42>(), function_selector: 10, calldata: sample_calldata(), ); - - set_caller_address(not_signer); + start_cheat_caller_address_global(not_signer); MultisigImpl::confirm_transaction(ref state, nonce: 0); } @@ -208,7 +194,7 @@ fn test_revoke_confirmation() { let signer2 = contract_address_const::<2>(); let signers = array![signer1, signer2]; Multisig::constructor(ref state, :signers, threshold: 2); - set_caller_address(signer1); + start_cheat_caller_address_global(signer1); MultisigImpl::submit_transaction( ref state, to: contract_address_const::<42>(), @@ -237,7 +223,7 @@ fn test_revoke_confirmation_not_signer() { let not_signer = contract_address_const::<2>(); let mut signers = array![signer]; Multisig::constructor(ref state, :signers, threshold: 2); - set_caller_address(signer); + start_cheat_caller_address_global(signer); MultisigImpl::submit_transaction( ref state, to: contract_address_const::<42>(), @@ -245,8 +231,7 @@ fn test_revoke_confirmation_not_signer() { calldata: sample_calldata(), ); MultisigImpl::confirm_transaction(ref state, nonce: 0); - - set_caller_address(not_signer); + start_cheat_caller_address_global(not_signer); MultisigImpl::revoke_confirmation(ref state, nonce: 0); } @@ -257,8 +242,9 @@ fn test_execute_confirmation_below_threshold() { let signer1 = contract_address_const::<1>(); let signer2 = contract_address_const::<2>(); let signers = array![signer1, signer2]; + Multisig::constructor(ref state, :signers, threshold: 2); - set_caller_address(signer1); + start_cheat_caller_address_global(signer1); MultisigImpl::submit_transaction( ref state, to: contract_address_const::<42>(), @@ -274,8 +260,7 @@ fn test_execute_confirmation_below_threshold() { fn test_upgrade_not_multisig() { let mut state = STATE(); let account = contract_address_const::<777>(); - set_caller_address(account); - + start_cheat_caller_address_global(account); UpgradeableImpl::upgrade(ref state, class_hash_const::<1>()) } @@ -286,11 +271,12 @@ fn test_execute() { let signer2 = contract_address_const::<2>(); let signers = array![signer1, signer2]; Multisig::constructor(ref state, :signers, threshold: 2); - let (test_address, _) = deploy_syscall( - MultisigTest::TEST_CLASS_HASH.try_into().unwrap(), 0, ArrayTrait::new().span(), false - ) - .unwrap(); - set_caller_address(signer1); + + let calldata = ArrayTrait::new(); + + let (test_address, _) = declare("MockMultisigTarget").unwrap().deploy(@calldata).unwrap(); + + start_cheat_caller_address_global(signer1); let increment_calldata = array![42, 100]; MultisigImpl::submit_transaction( ref state, @@ -300,7 +286,7 @@ fn test_execute() { calldata: increment_calldata, ); MultisigImpl::confirm_transaction(ref state, nonce: 0); - set_caller_address(signer2); + start_cheat_caller_address_global(signer2); MultisigImpl::confirm_transaction(ref state, nonce: 0); let response = MultisigImpl::execute_transaction(ref state, nonce: 0); @@ -318,7 +304,7 @@ fn test_execute_not_signer() { let signer2 = contract_address_const::<2>(); let signers = array![signer1, signer2]; Multisig::constructor(ref state, :signers, threshold: 2); - set_caller_address(signer1); + start_cheat_caller_address_global(signer1); MultisigImpl::submit_transaction( ref state, to: contract_address_const::<42>(), @@ -326,96 +312,105 @@ fn test_execute_not_signer() { calldata: sample_calldata(), ); MultisigImpl::confirm_transaction(ref state, nonce: 0); - set_caller_address(signer2); + start_cheat_caller_address_global(signer2); MultisigImpl::confirm_transaction(ref state, nonce: 0); - - set_caller_address(contract_address_const::<3>()); + start_cheat_caller_address_global(contract_address_const::<3>()); MultisigImpl::execute_transaction(ref state, nonce: 0); } #[test] #[should_panic(expected: ('transaction invalid',))] fn test_execute_after_set_signers() { - let mut state = STATE(); - let contract_address = contract_address_const::<100>(); - set_contract_address(contract_address); let signer1 = contract_address_const::<1>(); let signer2 = contract_address_const::<2>(); let signer3 = contract_address_const::<3>(); let signers = array![signer1, signer2]; - Multisig::constructor(ref state, :signers, threshold: 2); - set_caller_address(signer1); - MultisigImpl::submit_transaction( - ref state, - to: contract_address_const::<42>(), - function_selector: 10, - calldata: sample_calldata(), - ); - MultisigImpl::confirm_transaction(ref state, nonce: 0); - set_caller_address(signer2); - MultisigImpl::confirm_transaction(ref state, nonce: 0); - set_caller_address(contract_address); - let new_signers = array![signer2, signer3]; - MultisigImpl::set_signers(ref state, new_signers); + let init_threshold: usize = 2; - set_caller_address(signer2); - MultisigImpl::execute_transaction(ref state, nonce: 0); + let mut deploy_calldata = ArrayTrait::new(); + Serde::serialize(@signers, ref deploy_calldata); + Serde::serialize(@init_threshold, ref deploy_calldata); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); + + let multisig = IMultisigDispatcher { contract_address: multisig_address }; + + start_cheat_caller_address_global(signer1); + multisig + .submit_transaction( + to: contract_address_const::<42>(), function_selector: 10, calldata: sample_calldata(), + ); + multisig.confirm_transaction(nonce: 0); + start_cheat_caller_address_global(signer2); + multisig.confirm_transaction(nonce: 0); + start_cheat_caller_address_global(multisig_address); + let new_signers = array![signer2, signer3]; + multisig.set_signers(new_signers); + start_cheat_caller_address_global(signer2); + multisig.execute_transaction(nonce: 0); } #[test] #[should_panic(expected: ('transaction invalid',))] fn test_execute_after_set_signers_and_threshold() { - let mut state = STATE(); - let contract_address = contract_address_const::<100>(); - set_contract_address(contract_address); let signer1 = contract_address_const::<1>(); let signer2 = contract_address_const::<2>(); let signer3 = contract_address_const::<3>(); let signers = array![signer1, signer2]; - Multisig::constructor(ref state, :signers, threshold: 2); - set_caller_address(signer1); - MultisigImpl::submit_transaction( - ref state, - to: contract_address_const::<42>(), - function_selector: 10, - calldata: sample_calldata(), - ); - MultisigImpl::confirm_transaction(ref state, nonce: 0); - set_caller_address(signer2); - MultisigImpl::confirm_transaction(ref state, nonce: 0); - set_caller_address(contract_address); - let new_signers = array![signer2, signer3]; - MultisigImpl::set_signers_and_threshold(ref state, new_signers, 1); + let init_threshold: usize = 2; - set_caller_address(signer2); - MultisigImpl::execute_transaction(ref state, nonce: 0); + let mut deploy_calldata = ArrayTrait::new(); + Serde::serialize(@signers, ref deploy_calldata); + Serde::serialize(@init_threshold, ref deploy_calldata); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); + + let multisig = IMultisigDispatcher { contract_address: multisig_address }; + + // Multisig::constructor(ref state, :signers, threshold: 2); + start_cheat_caller_address_global(signer1); + multisig + .submit_transaction( + to: contract_address_const::<42>(), function_selector: 10, calldata: sample_calldata(), + ); + multisig.confirm_transaction(nonce: 0); + start_cheat_caller_address_global(signer2); + multisig.confirm_transaction(nonce: 0); + start_cheat_caller_address_global(multisig_address); + let new_signers = array![signer2, signer3]; + multisig.set_signers_and_threshold(new_signers, 1); + start_cheat_caller_address_global(signer2); + multisig.execute_transaction(nonce: 0); } #[test] #[should_panic(expected: ('transaction invalid',))] fn test_execute_after_set_threshold() { - let mut state = STATE(); - let contract_address = contract_address_const::<100>(); - set_contract_address(contract_address); let signer1 = contract_address_const::<1>(); let signer2 = contract_address_const::<2>(); let signers = array![signer1, signer2]; - Multisig::constructor(ref state, :signers, threshold: 2); - set_caller_address(signer1); - MultisigImpl::submit_transaction( - ref state, - to: contract_address_const::<42>(), - function_selector: 10, - calldata: sample_calldata(), - ); - MultisigImpl::confirm_transaction(ref state, nonce: 0); - set_caller_address(signer2); - MultisigImpl::confirm_transaction(ref state, nonce: 0); - set_caller_address(contract_address); - MultisigImpl::set_threshold(ref state, 1); + let init_threshold: usize = 2; - set_caller_address(signer1); - MultisigImpl::execute_transaction(ref state, nonce: 0); + let mut deploy_calldata = ArrayTrait::new(); + Serde::serialize(@signers, ref deploy_calldata); + Serde::serialize(@init_threshold, ref deploy_calldata); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); + + let multisig = IMultisigDispatcher { contract_address: multisig_address }; + + start_cheat_caller_address_global(signer1); + multisig + .submit_transaction( + to: contract_address_const::<42>(), function_selector: 10, calldata: sample_calldata(), + ); + multisig.confirm_transaction(nonce: 0); + start_cheat_caller_address_global(signer2); + multisig.confirm_transaction(nonce: 0); + start_cheat_caller_address_global(multisig_address); + multisig.set_threshold(1); + start_cheat_caller_address_global(signer1); + multisig.execute_transaction(nonce: 0); } // test set_threshold (non-recursive) @@ -431,14 +426,12 @@ fn test_set_threshold() { let mut deploy_calldata = ArrayTrait::new(); Serde::serialize(@signers, ref deploy_calldata); Serde::serialize(@init_threshold, ref deploy_calldata); - let (multisig_address, _) = deploy_syscall( - Multisig::TEST_CLASS_HASH.try_into().unwrap(), 0, deploy_calldata.span(), false - ) - .unwrap(); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; assert(multisig.get_threshold() == init_threshold, 'invalid init threshold'); - set_contract_address(multisig_address); + start_cheat_caller_address_global(multisig_address); multisig.set_threshold(new_threshold); assert(multisig.get_threshold() == new_threshold, 'threshold was not updated'); } @@ -457,10 +450,8 @@ fn test_recursive_set_threshold() { let mut deploy_calldata = ArrayTrait::new(); Serde::serialize(@signers, ref deploy_calldata); Serde::serialize(@init_threshold, ref deploy_calldata); - let (multisig_address, _) = deploy_syscall( - Multisig::TEST_CLASS_HASH.try_into().unwrap(), 0, deploy_calldata.span(), false - ) - .unwrap(); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); // Gets a dispatcher (so we can call methods on the deployed contract) let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -472,19 +463,21 @@ fn test_recursive_set_threshold() { // contract. let mut set_threshold_calldata = ArrayTrait::new(); Serde::serialize(@new_threshold, ref set_threshold_calldata); - set_contract_address(s1); + start_cheat_caller_address_global(s1); multisig .submit_transaction(multisig_address, selector!("set_threshold"), set_threshold_calldata); // Signer 1 confirms the transaction - set_contract_address(s1); + start_cheat_caller_address_global(s1); multisig.confirm_transaction(0); // Signer 2 confirms the transaction - set_contract_address(s2); + start_cheat_caller_address_global(s2); multisig.confirm_transaction(0); // Once we have enough confirmations, we execute the transaction - set_contract_address(s1); + // cheat only once because we want the multisig to execute the recursive tx + cheat_caller_address(multisig_address, s1, CheatSpan::TargetCalls(1)); + multisig.execute_transaction(0); // Now we check that the threshold was actually updated @@ -503,10 +496,8 @@ fn test_set_signers() { let mut deploy_calldata = ArrayTrait::new(); Serde::serialize(@init_signers, ref deploy_calldata); Serde::serialize(@threshold, ref deploy_calldata); - let (multisig_address, _) = deploy_syscall( - Multisig::TEST_CLASS_HASH.try_into().unwrap(), 0, deploy_calldata.span(), false - ) - .unwrap(); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -516,7 +507,7 @@ fn test_set_signers() { assert(*returned_signers.at(1) == s2, 'should match signer 2'); assert(multisig.get_threshold() == 2, 'wrong init threshold'); - set_contract_address(multisig_address); + start_cheat_caller_address_global(multisig_address); multisig.set_signers(new_signers); let updated_signers = multisig.get_signers(); @@ -539,10 +530,8 @@ fn test_recursive_set_signers() { let mut deploy_calldata = ArrayTrait::new(); Serde::serialize(@init_signers, ref deploy_calldata); Serde::serialize(@init_threshold, ref deploy_calldata); - let (multisig_address, _) = deploy_syscall( - Multisig::TEST_CLASS_HASH.try_into().unwrap(), 0, deploy_calldata.span(), false - ) - .unwrap(); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); // Gets a dispatcher (so we can call methods on the deployed contract) let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -559,19 +548,19 @@ fn test_recursive_set_signers() { // contract. let mut set_signers_calldata = ArrayTrait::new(); Serde::serialize(@new_signers, ref set_signers_calldata); - set_contract_address(s1); + start_cheat_caller_address_global(s1); multisig.submit_transaction(multisig_address, selector!("set_signers"), set_signers_calldata); // Signer 1 confirms the transaction - set_contract_address(s1); + start_cheat_caller_address_global(s1); multisig.confirm_transaction(0); // Signer 2 confirms the transaction - set_contract_address(s2); + start_cheat_caller_address_global(s2); multisig.confirm_transaction(0); // Once we have enough confirmations, we execute the transaction - set_contract_address(s1); + cheat_caller_address(multisig_address, s1, CheatSpan::TargetCalls(1)); multisig.execute_transaction(0); // Now we check that the signers were actually updated @@ -595,10 +584,8 @@ fn test_set_signers_and_threshold() { let mut deploy_calldata = ArrayTrait::new(); Serde::serialize(@init_signers, ref deploy_calldata); Serde::serialize(@init_threshold, ref deploy_calldata); - let (multisig_address, _) = deploy_syscall( - Multisig::TEST_CLASS_HASH.try_into().unwrap(), 0, deploy_calldata.span(), false - ) - .unwrap(); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -609,7 +596,7 @@ fn test_set_signers_and_threshold() { assert(*returned_signers.at(2) == s3, 'should match signer 3'); assert(multisig.get_threshold() == init_threshold, 'wrong init threshold'); - set_contract_address(multisig_address); + start_cheat_caller_address_global(multisig_address); multisig.set_signers_and_threshold(new_signers, new_threshold); let updated_signers = multisig.get_signers(); @@ -635,10 +622,8 @@ fn test_recursive_set_signers_and_threshold() { let mut deploy_calldata = ArrayTrait::new(); Serde::serialize(@init_signers, ref deploy_calldata); Serde::serialize(@init_threshold, ref deploy_calldata); - let (multisig_address, _) = deploy_syscall( - Multisig::TEST_CLASS_HASH.try_into().unwrap(), 0, deploy_calldata.span(), false - ) - .unwrap(); + + let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); // Gets a dispatcher (so we can call methods on the deployed contract) let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -657,7 +642,7 @@ fn test_recursive_set_signers_and_threshold() { let mut set_signers_and_threshold_calldata = ArrayTrait::new(); Serde::serialize(@new_signers, ref set_signers_and_threshold_calldata); Serde::serialize(@new_threshold, ref set_signers_and_threshold_calldata); - set_contract_address(s1); + start_cheat_caller_address_global(s1); multisig .submit_transaction( multisig_address, @@ -666,19 +651,19 @@ fn test_recursive_set_signers_and_threshold() { ); // Signer 1 confirms the transaction - set_contract_address(s1); + start_cheat_caller_address_global(s1); multisig.confirm_transaction(0); // Signer 2 confirms the transaction - set_contract_address(s2); + start_cheat_caller_address_global(s2); multisig.confirm_transaction(0); // Signer 3 confirms the transaction - set_contract_address(s3); + start_cheat_caller_address_global(s3); multisig.confirm_transaction(0); // Once we have enough confirmations, we execute the transaction - set_contract_address(s1); + cheat_caller_address(multisig_address, s1, CheatSpan::TargetCalls(1)); multisig.execute_transaction(0); // Now we check that the signers were actually updated diff --git a/contracts/src/tests/test_ownable.cairo b/contracts/src/tests/test_ownable.cairo index 40e86c1c5..d898bbb73 100644 --- a/contracts/src/tests/test_ownable.cairo +++ b/contracts/src/tests/test_ownable.cairo @@ -8,6 +8,10 @@ use openzeppelin::access::ownable::interface::{ IOwnableTwoStep, IOwnableTwoStepDispatcher, IOwnableTwoStepDispatcherTrait }; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + // // General ownable contract tests // @@ -20,13 +24,13 @@ fn should_implement_ownable(contract_addr: ContractAddress, owner: ContractAddre assert(owner == contract.owner(), 'owner does not match'); // transfer ownership - check owner unchanged and proposed owner set correctly - set_contract_address(owner); // required to call contract as owner + start_cheat_caller_address_global(owner); contract.transfer_ownership(acc2); assert(owner == contract.owner(), 'owner should remain unchanged'); assert(acc2 == contract.pending_owner(), 'acc2 should be proposed owner'); // accept ownership - check owner changed and proposed owner set to zero - set_contract_address(acc2); // required to call function as acc2 + start_cheat_caller_address_global(acc2); contract.accept_ownership(); assert(contract.owner() == acc2, 'failed to change ownership'); assert(contract.pending_owner().is_zero(), 'proposed owner should be zero'); diff --git a/contracts/src/tests/test_sequencer_uptime_feed.cairo b/contracts/src/tests/test_sequencer_uptime_feed.cairo index 51dabbd25..a7b44ff24 100644 --- a/contracts/src/tests/test_sequencer_uptime_feed.cairo +++ b/contracts/src/tests/test_sequencer_uptime_feed.cairo @@ -29,6 +29,11 @@ use chainlink::emergency::sequencer_uptime_feed::{ ISequencerUptimeFeed, ISequencerUptimeFeedDispatcher, ISequencerUptimeFeedDispatcherTrait }; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + + fn PROXY() -> AggregatorProxy::ContractState { AggregatorProxy::contract_state_for_testing() } @@ -39,16 +44,16 @@ fn STATE() -> SequencerUptimeFeed::ContractState { fn setup() -> (ContractAddress, ContractAddress, ISequencerUptimeFeedDispatcher) { let account: ContractAddress = contract_address_const::<777>(); - set_caller_address(account); + + start_cheat_caller_address_global(account); // Deploy seqeuencer uptime feed let calldata = array![0, // initial status account.into() // owner ]; - let (sequencerFeedAddr, _) = deploy_syscall( - SequencerUptimeFeed::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (sequencerFeedAddr, _) = declare("SequencerUptimeFeed").unwrap().deploy(@calldata).unwrap(); + let sequencerUptimeFeed = ISequencerUptimeFeedDispatcher { contract_address: sequencerFeedAddr }; @@ -72,13 +77,14 @@ fn test_access_control() { #[should_panic()] fn test_set_l1_sender_not_owner() { let (_, _, sequencerUptimeFeed) = setup(); + start_cheat_caller_address_global(contract_address_const::<111>()); sequencerUptimeFeed.set_l1_sender(EthAddress { address: 789 }); } #[test] fn test_set_l1_sender() { let (owner, _, sequencerUptimeFeed) = setup(); - set_contract_address(owner); + start_cheat_caller_address_global(owner); sequencerUptimeFeed.set_l1_sender(EthAddress { address: 789 }); assert(sequencerUptimeFeed.l1_sender().address == 789, 'l1_sender should be set to 789'); } @@ -104,8 +110,7 @@ fn test_latest_answer_no_access() { #[test] fn test_aggregator_proxy_response() { let (owner, sequencerFeedAddr, _) = setup(); - - set_contract_address(owner); + start_cheat_caller_address_global(owner); let contract = IAccessControllerDispatcher { contract_address: sequencerFeedAddr }; contract.add_access(owner); diff --git a/contracts/src/tests/test_upgradeable.cairo b/contracts/src/tests/test_upgradeable.cairo index 4d4213573..fee927616 100644 --- a/contracts/src/tests/test_upgradeable.cairo +++ b/contracts/src/tests/test_upgradeable.cairo @@ -16,9 +16,14 @@ use chainlink::libraries::mocks::mock_non_upgradeable::{ IMockNonUpgradeableDispatcherImpl }; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + + fn setup() -> ContractAddress { let account: ContractAddress = contract_address_const::<777>(); - set_caller_address(account); + start_cheat_caller_address_global(account); account } @@ -27,14 +32,15 @@ fn test_upgrade_and_call() { let _ = setup(); let calldata = array![]; - let (contractAddr, _) = deploy_syscall( - MockUpgradeable::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false - ) - .unwrap(); + + let (contractAddr, _) = declare("MockUpgradeable").unwrap().deploy(@calldata).unwrap(); + let mockUpgradeable = IMockUpgradeableDispatcher { contract_address: contractAddr }; assert(mockUpgradeable.foo() == true, 'should call foo'); - mockUpgradeable.upgrade(MockNonUpgradeable::TEST_CLASS_HASH.try_into().unwrap()); + let contract_class = declare("MockNonUpgradeable").unwrap(); + + mockUpgradeable.upgrade(contract_class.class_hash); // now, contract should be different let mockNonUpgradeable = IMockNonUpgradeableDispatcher { contract_address: contractAddr }; diff --git a/examples/contracts/aggregator_consumer/Scarb.lock b/examples/contracts/aggregator_consumer/Scarb.lock index 586d04a23..5bdff8546 100644 --- a/examples/contracts/aggregator_consumer/Scarb.lock +++ b/examples/contracts/aggregator_consumer/Scarb.lock @@ -9,11 +9,66 @@ dependencies = [ "snforge_std", ] +[[package]] +name = "alexandria_bytes" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_data_structures", + "alexandria_math", +] + +[[package]] +name = "alexandria_data_structures" +version = "0.2.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_encoding", +] + +[[package]] +name = "alexandria_encoding" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_bytes", + "alexandria_math", + "alexandria_numeric", +] + +[[package]] +name = "alexandria_math" +version = "0.2.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_data_structures", +] + +[[package]] +name = "alexandria_numeric" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_math", + "alexandria_searching", +] + +[[package]] +name = "alexandria_searching" +version = "0.1.0" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +dependencies = [ + "alexandria_data_structures", +] + [[package]] name = "chainlink" version = "0.1.0" dependencies = [ + "alexandria_bytes", + "alexandria_encoding", "openzeppelin", + "snforge_std", ] [[package]] @@ -23,5 +78,5 @@ source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.10.0#d7 [[package]] name = "snforge_std" -version = "0.21.0" -source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.21.0#2996b8c1dd66b2715fc67e69578089f278a46790" +version = "0.27.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" diff --git a/examples/contracts/aggregator_consumer/Scarb.toml b/examples/contracts/aggregator_consumer/Scarb.toml index e7868b138..8da76d784 100644 --- a/examples/contracts/aggregator_consumer/Scarb.toml +++ b/examples/contracts/aggregator_consumer/Scarb.toml @@ -8,10 +8,13 @@ name = "aggregator_consumer" version = "0.1.0" cairo-version = "2.6.3" +# [scripts] +# test = "snforge test" + # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.21.0" } +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.27.0" } chainlink = { path = "../../../contracts" } starknet = ">=2.6.3" diff --git a/examples/contracts/aggregator_consumer/tests/test_consumer.cairo b/examples/contracts/aggregator_consumer/tests/test_consumer.cairo index 31d86386c..b7afc0b70 100644 --- a/examples/contracts/aggregator_consumer/tests/test_consumer.cairo +++ b/examples/contracts/aggregator_consumer/tests/test_consumer.cairo @@ -13,13 +13,23 @@ use starknet::ContractAddress; fn deploy_mock_aggregator(decimals: u8) -> ContractAddress { let mut calldata = ArrayTrait::new(); calldata.append(decimals.into()); - return declare("MockAggregator").deploy(@calldata).unwrap(); + + let contract = declare("MockAggregator").unwrap(); + + let (contract_address, _) = contract.deploy(@calldata).unwrap(); + + contract_address } fn deploy_consumer(aggregator_address: ContractAddress) -> ContractAddress { let mut calldata = ArrayTrait::new(); calldata.append(aggregator_address.into()); - return declare("AggregatorConsumer").deploy(@calldata).unwrap(); + + let contract = declare("AggregatorConsumer").unwrap(); + + let (contract_address, _) = contract.deploy(@calldata).unwrap(); + + contract_address } #[test] @@ -79,7 +89,9 @@ fn test_set_and_read_answer() { let consumer_dispatcher = IAggregatorConsumerDispatcher { contract_address: consumer_address }; // Let's make sure the AggregatorConsumer was initialized correctly - assert(consumer_dispatcher.read_ocr_address() == mock_aggregator_address, 'Invalid OCR address'); + assert( + consumer_dispatcher.read_ocr_address() == mock_aggregator_address, 'Invalid OCR address' + ); assert(consumer_dispatcher.read_answer() == 0, 'Invalid initial answer'); // No round data has been initialized, so reading the latest round should return no data diff --git a/examples/contracts/aggregator_consumer/tests/test_price_consumer_with_sequencer.cairo b/examples/contracts/aggregator_consumer/tests/test_price_consumer_with_sequencer.cairo index 9582c8030..91874ba2e 100644 --- a/examples/contracts/aggregator_consumer/tests/test_price_consumer_with_sequencer.cairo +++ b/examples/contracts/aggregator_consumer/tests/test_price_consumer_with_sequencer.cairo @@ -1,5 +1,3 @@ -use snforge_std::{declare, ContractClassTrait, start_prank, stop_prank, CheatTarget}; - use chainlink::emergency::sequencer_uptime_feed::ISequencerUptimeFeedDispatcherTrait; use chainlink::emergency::sequencer_uptime_feed::ISequencerUptimeFeedDispatcher; use chainlink::libraries::access_control::IAccessControllerDispatcherTrait; @@ -14,17 +12,23 @@ use starknet::contract_address_const; use starknet::get_caller_address; use starknet::ContractAddress; +use snforge_std::{ + declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global +}; + fn deploy_mock_aggregator(decimals: u8) -> ContractAddress { let mut calldata = ArrayTrait::new(); calldata.append(decimals.into()); - return declare("MockAggregator").deploy(@calldata).unwrap(); + let (contract_address, _) = declare("MockAggregator").unwrap().deploy(@calldata).unwrap(); + contract_address } fn deploy_uptime_feed(initial_status: u128, owner_address: ContractAddress) -> ContractAddress { let mut calldata = ArrayTrait::new(); calldata.append(initial_status.into()); calldata.append(owner_address.into()); - return declare("SequencerUptimeFeed").deploy(@calldata).unwrap(); + let (contract_address, _) = declare("SequencerUptimeFeed").unwrap().deploy(@calldata).unwrap(); + contract_address } fn deploy_price_consumer( @@ -33,7 +37,11 @@ fn deploy_price_consumer( let mut calldata = ArrayTrait::new(); calldata.append(uptime_feed_address.into()); calldata.append(aggregator_address.into()); - return declare("AggregatorPriceConsumer").deploy(@calldata).unwrap(); + let (contract_address, _) = declare("AggregatorPriceConsumer") + .unwrap() + .deploy(@calldata) + .unwrap(); + contract_address } #[test] @@ -52,7 +60,8 @@ fn test_get_latest_price() { // Adds the price consumer contract to the sequencer uptime feed access control list // which allows the price consumer to call the get_latest_price function - start_prank(CheatTarget::All, owner); + start_cheat_caller_address_global(owner); + // start_prank(CheatTarget::All, owner); IAccessControllerDispatcher { contract_address: uptime_feed_address } .add_access(price_consumer_address); @@ -62,7 +71,8 @@ fn test_get_latest_price() { // a new round is initialized using its initial status as the round's answer, so the // latest price should be the initial status that was passed into the sequencer uptime // feed's constructor. - start_prank(CheatTarget::All, price_consumer_address); + start_cheat_caller_address_global(price_consumer_address); + // start_prank(CheatTarget::All, price_consumer_address); let latest_price = IAggregatorPriceConsumerDispatcher { contract_address: price_consumer_address } @@ -70,7 +80,7 @@ fn test_get_latest_price() { assert(latest_price == init_status, 'latest price is incorrect'); // Now let's update the round - stop_prank(CheatTarget::All); + stop_cheat_caller_address_global(); let answer = 1; let block_num = 12345; let observation_timestamp = 100000; @@ -79,7 +89,7 @@ fn test_get_latest_price() { .set_latest_round_data(answer, block_num, observation_timestamp, transmission_timestamp); // This should now return the updated answer - start_prank(CheatTarget::All, price_consumer_address); + start_cheat_caller_address_global(price_consumer_address); let updated_latest_price = IAggregatorPriceConsumerDispatcher { contract_address: price_consumer_address }