diff --git a/.github/actions/install-cairo/action.yml b/.github/actions/install-cairo/action.yml index d3f1524d6..b4843f05d 100644 --- a/.github/actions/install-cairo/action.yml +++ b/.github/actions/install-cairo/action.yml @@ -4,25 +4,16 @@ description: A composite action that installs cairo and scarb binaries inputs: cairo_version: description: Cairo release version - default: "v2.6.4" + default: "v2.7.1" required: false scarb_version: description: Scarb release version - default: "v2.6.5" + default: "v2.7.1" required: false runs: using: composite steps: - - name: Setup Cairo for Linux - id: install-cairo - shell: bash - run: | - wget https://github.com/starkware-libs/cairo/releases/download/${{ inputs.cairo_version }}/release-x86_64-unknown-linux-musl.tar.gz - tar -xvzf release-x86_64-unknown-linux-musl.tar.gz - mv -vf cairo cairo-build - echo "$GITHUB_WORKSPACE/cairo-build/bin" >> $GITHUB_PATH - - name: Setup Scarb for Linux id: install-scarb shell: bash diff --git a/.github/actions/install-starknet-foundry/action.yml b/.github/actions/install-starknet-foundry/action.yml index 8e4360edf..a27163052 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.27.0" + default: "0.29.0" required: false runs: diff --git a/.tool-versions b/.tool-versions index e3f251c90..4fcf5d79e 100644 --- a/.tool-versions +++ b/.tool-versions @@ -9,9 +9,9 @@ mockery 2.22.1 golangci-lint 1.55.0 actionlint 1.6.12 shellcheck 0.8.0 -scarb 2.6.5 +scarb 2.7.1 postgres 15.1 -starknet-foundry 0.27.0 +starknet-foundry 0.29.0 # Kubernetes k3d 5.4.4 diff --git a/Makefile b/Makefile index 7cdd24af0..ab561bac4 100644 --- a/Makefile +++ b/Makefile @@ -152,13 +152,13 @@ generate: mockery gomods .PHONY: format-cairo format-cairo: - cairo-format -i ./contracts/src/**/*.cairo - cairo-format -i ./examples/**/*.cairo + cd contracts && scarb fmt + cd examples/contracts/aggregator_consumer && scarb fmt .PHONY: format-cairo-check format-cairo-check: - cairo-format -c ./contracts/src/**/*.cairo - cairo-format -c ./examples/**/*.cairo + cd contracts && scarb fmt -c + cd examples/contracts/aggregator_consumer && scarb fmt -c .PHONY: format-ts format-ts: @@ -233,7 +233,7 @@ test-integration-soak-ci: .PHONY: test-examples test-examples: cd ./examples/contracts/aggregator_consumer && \ - snforge test + scarb test .PHONY: test-integration-gauntlet # TODO: fix example diff --git a/contracts/Scarb.lock b/contracts/Scarb.lock index 0c0ba3523..7d274b000 100644 --- a/contracts/Scarb.lock +++ b/contracts/Scarb.lock @@ -4,7 +4,7 @@ version = 1 [[package]] name = "alexandria_bytes" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_data_structures", "alexandria_math", @@ -13,7 +13,7 @@ dependencies = [ [[package]] name = "alexandria_data_structures" version = "0.2.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_encoding", ] @@ -21,7 +21,7 @@ dependencies = [ [[package]] name = "alexandria_encoding" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_bytes", "alexandria_math", @@ -31,7 +31,7 @@ dependencies = [ [[package]] name = "alexandria_math" version = "0.2.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_data_structures", ] @@ -39,7 +39,7 @@ dependencies = [ [[package]] name = "alexandria_numeric" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_math", "alexandria_searching", @@ -48,7 +48,7 @@ dependencies = [ [[package]] name = "alexandria_searching" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_data_structures", ] @@ -65,10 +65,98 @@ dependencies = [ [[package]] name = "openzeppelin" -version = "0.10.0" -source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.10.0#d77082732daab2690ba50742ea41080eb23299d3" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_governance", + "openzeppelin_introspection", + "openzeppelin_presets", + "openzeppelin_security", + "openzeppelin_token", + "openzeppelin_upgrades", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_access" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_account" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_governance" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_access", + "openzeppelin_introspection", +] + +[[package]] +name = "openzeppelin_introspection" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" + +[[package]] +name = "openzeppelin_presets" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_introspection", + "openzeppelin_token", + "openzeppelin_upgrades", +] + +[[package]] +name = "openzeppelin_security" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" + +[[package]] +name = "openzeppelin_token" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_account", + "openzeppelin_governance", + "openzeppelin_introspection", +] + +[[package]] +name = "openzeppelin_upgrades" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" + +[[package]] +name = "openzeppelin_utils" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" + +[[package]] +name = "snforge_scarb_plugin" +version = "0.1.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.29.0#d37d2272ca6c915117646de76cdf26ec06e44f61" [[package]] name = "snforge_std" -version = "0.27.0" -source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" +version = "0.29.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.29.0#d37d2272ca6c915117646de76cdf26ec06e44f61" +dependencies = [ + "snforge_scarb_plugin", +] diff --git a/contracts/Scarb.toml b/contracts/Scarb.toml index a84f65f83..e3353f9f0 100644 --- a/contracts/Scarb.toml +++ b/contracts/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "chainlink" version = "0.1.0" -cairo-version = "2.6.3" +cairo-version = "2.7.1" description = "Chainlink contracts for Starknet" homepage = "https://github.com/smartcontractkit/chainlink-starknet" @@ -13,11 +13,13 @@ test = "snforge test" # Uncomment if you want to use dependencies # Note: currently testing doesn't work with dependencies [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" } +starknet = "2.7.1" +openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.15.1" } +alexandria_bytes = { git = "https://github.com/keep-starknet-strange/alexandria.git", rev = "e1b080577aaa6889116fc8be5dde72b2fd21e397" } +alexandria_encoding = { git = "https://github.com/keep-starknet-strange/alexandria.git", rev = "e1b080577aaa6889116fc8be5dde72b2fd21e397" } + +[dev-dependencies] +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.29.0" } [lib] diff --git a/contracts/src/account.cairo b/contracts/src/account.cairo index dcda746e8..3318c2c7c 100644 --- a/contracts/src/account.cairo +++ b/contracts/src/account.cairo @@ -1,11 +1,14 @@ -// copied from https://raw.githubusercontent.com/OpenZeppelin/cairo-contracts/861fc416f87addbe23a3b47f9d19ab27c10d5dc8/src/presets/account.cairo (0.9.0) +// copied from +// https://raw.githubusercontent.com/OpenZeppelin/cairo-contracts/861fc416f87addbe23a3b47f9d19ab27c10d5dc8/src/presets/account.cairo +// (0.9.0) // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.9.0 (presets/account.cairo) /// # Account Preset /// -/// OpenZeppelin's basic account which can change its public key and declare, deploy, or call contracts. +/// OpenZeppelin's basic account which can change its public key and declare, deploy, or call +/// contracts. #[starknet::contract(account)] mod Account { use openzeppelin::account::AccountComponent; diff --git a/contracts/src/emergency/sequencer_uptime_feed.cairo b/contracts/src/emergency/sequencer_uptime_feed.cairo index fad5ad8f7..eacde6f95 100644 --- a/contracts/src/emergency/sequencer_uptime_feed.cairo +++ b/contracts/src/emergency/sequencer_uptime_feed.cairo @@ -20,6 +20,7 @@ mod SequencerUptimeFeed { use starknet::storage_write_syscall; use starknet::storage_address_from_base_and_offset; use starknet::class_hash::ClassHash; + use starknet::storage::Map; use box::BoxTrait; use traits::Into; @@ -58,7 +59,7 @@ mod SequencerUptimeFeed { // l1 sender is an starknet validator ethereum address _l1_sender: EthAddress, // maps round id to round transmission - _round_transmissions: LegacyMap, + _round_transmissions: Map, _latest_round_id: u128, } @@ -177,7 +178,8 @@ mod SequencerUptimeFeed { #[l1_handler] fn update_status(ref self: ContractState, from_address: felt252, status: u128, timestamp: u64) { - // Cairo enforces from_address to be a felt252 on the method signature, but we can cast it right after + // Cairo enforces from_address to be a felt252 on the method signature, but we can cast it + // right after let from_address: EthAddress = from_address.try_into().unwrap(); assert(self._l1_sender.read() == from_address, 'EXPECTED_FROM_BRIDGE_ONLY'); diff --git a/contracts/src/libraries/access_control.cairo b/contracts/src/libraries/access_control.cairo index b0a910d55..e971e4067 100644 --- a/contracts/src/libraries/access_control.cairo +++ b/contracts/src/libraries/access_control.cairo @@ -14,6 +14,7 @@ trait IAccessController { mod AccessControlComponent { use starknet::ContractAddress; use starknet::class_hash::ClassHash; + use starknet::storage::Map; use zeroable::Zeroable; use openzeppelin::access::ownable::OwnableComponent; @@ -23,7 +24,7 @@ mod AccessControlComponent { #[storage] struct Storage { _check_enabled: bool, - _access_list: LegacyMap, + _access_list: Map, } #[event] diff --git a/contracts/src/libraries/token/erc677.cairo b/contracts/src/libraries/token/erc677.cairo index 20fd6c54a..26ad289b5 100644 --- a/contracts/src/libraries/token/erc677.cairo +++ b/contracts/src/libraries/token/erc677.cairo @@ -12,7 +12,8 @@ trait IERC677Receiver { fn on_token_transfer( ref self: TContractState, sender: ContractAddress, value: u256, data: Array ); - // implements EIP-165, where function selectors are defined by Ethereum ABI using the ethereum function signatures + // implements EIP-165, where function selectors are defined by Ethereum ABI using the ethereum + // function signatures fn supports_interface(ref self: TContractState, interface_id: u32) -> bool; } diff --git a/contracts/src/libraries/upgradeable.cairo b/contracts/src/libraries/upgradeable.cairo index 6b9e6af73..959fe7f3d 100644 --- a/contracts/src/libraries/upgradeable.cairo +++ b/contracts/src/libraries/upgradeable.cairo @@ -25,11 +25,11 @@ mod Upgradeable { // this method assumes replace_class_syscall has a very low possibility of being deprecated // but if it does, we will either have upgraded the contract to be non-upgradeable by then - // because the starknet ecosystem has stabilized or we will be able to upgrade the contract to the proxy pattern - // #[internal] + // because the starknet ecosystem has stabilized or we will be able to upgrade the contract to + // the proxy pattern #[internal] fn upgrade(new_impl: ClassHash) { assert(!new_impl.is_zero(), 'Class hash cannot be zero'); replace_class_syscall(new_impl).unwrap_syscall(); - // TODO: Upgraded(new_impl); + // TODO: Upgraded(new_impl); } } diff --git a/contracts/src/multisig.cairo b/contracts/src/multisig.cairo index b1422df45..3a65763cc 100644 --- a/contracts/src/multisig.cairo +++ b/contracts/src/multisig.cairo @@ -90,6 +90,7 @@ mod Multisig { use starknet::storage_read_syscall; use starknet::storage_write_syscall; use starknet::class_hash::ClassHash; + use starknet::storage::Map; use chainlink::libraries::type_and_version::ITypeAndVersion; use chainlink::libraries::upgradeable::{Upgradeable, IUpgradeable}; @@ -154,14 +155,14 @@ mod Multisig { #[storage] struct Storage { _threshold: usize, - _signers: LegacyMap, - _is_signer: LegacyMap, + _signers: Map, + _is_signer: Map, _signers_len: usize, _tx_valid_since: u128, _next_nonce: u128, - _transactions: LegacyMap, - _transaction_calldata: LegacyMap<(u128, usize), felt252>, - _is_confirmed: LegacyMap<(u128, ContractAddress), bool>, + _transactions: Map, + _transaction_calldata: Map<(u128, usize), felt252>, + _is_confirmed: Map<(u128, ContractAddress), bool>, } #[constructor] @@ -342,10 +343,11 @@ mod Multisig { ) .unwrap_syscall(); - // TODO: this shouldn't be necessary. call_contract_syscall returns a Span, which - // is a serialized result, but returning a Span results in an error: + // TODO: this shouldn't be necessary. call_contract_syscall returns a Span, + // which is a serialized result, but returning a Span results in an error: // - // Trait has no implementation in context: core::serde::Serde::> + // Trait has no implementation in context: + // core::serde::Serde::> // // Cairo docs also have an example that returns a Span: // https://github.com/starkware-libs/cairo/blob/fe425d0893ff93a936bb3e8bbbac771033074bdb/docs/reference/src/components/cairo/modules/language_constructs/pages/contracts.adoc#L226 diff --git a/contracts/src/ocr2/aggregator.cairo b/contracts/src/ocr2/aggregator.cairo index d494c81e8..e01c127b5 100644 --- a/contracts/src/ocr2/aggregator.cairo +++ b/contracts/src/ocr2/aggregator.cairo @@ -196,6 +196,7 @@ mod Aggregator { use starknet::storage_write_syscall; use starknet::storage_address_from_base_and_offset; use starknet::class_hash::ClassHash; + use starknet::storage::Map; use openzeppelin::access::ownable::OwnableComponent; use openzeppelin::token::erc20::interface::{IERC20, IERC20Dispatcher, IERC20DispatcherTrait}; @@ -306,22 +307,20 @@ mod Aggregator { _latest_config_digest: felt252, // _oracles: Array, // NOTE: array can't be used in storage _oracles_len: usize, - _transmitters: LegacyMap, // - _signers: LegacyMap, // - _signers_list: LegacyMap, - _transmitters_list: LegacyMap, - _reward_from_aggregator_round_id: LegacyMap, // - _transmissions: LegacyMap, + _transmitters: Map, // + _signers: Map, // + _signers_list: Map, + _transmitters_list: Map, + _reward_from_aggregator_round_id: Map, // + _transmissions: Map, // link token _link_token: ContractAddress, // billing _billing_access_controller: ContractAddress, _billing: BillingConfig, // payee management - _payees: LegacyMap, // - _proposed_payees: LegacyMap< - ContractAddress, ContractAddress - > // + _payees: Map, // + _proposed_payees: Map // } #[generate_trait] @@ -615,30 +614,29 @@ mod Aggregator { ) { let mut index = 0; let mut span = oracles.span(); - while let Option::Some(oracle) = span - .pop_front() { - // NOTE: index should start with 1 here because storage is 0-initialized. - // That way signers(pkey) => 0 indicates "not present" - // This is why we increment first, before using the index - index += 1; - - // check for duplicates - let existing_signer = self._signers.read(*oracle.signer); - assert(existing_signer == 0_usize, 'repeated signer'); - - let existing_transmitter = self._transmitters.read(*oracle.transmitter); - assert(existing_transmitter.index == 0_usize, 'repeated transmitter'); - - self._signers.write(*oracle.signer, index); - self._signers_list.write(index, *oracle.signer); - - self - ._transmitters - .write(*oracle.transmitter, Oracle { index, payment_juels: 0_u128 }); - self._transmitters_list.write(index, *oracle.transmitter); - - self._reward_from_aggregator_round_id.write(index, latest_round_id); - }; + while let Option::Some(oracle) = span.pop_front() { + // NOTE: index should start with 1 here because storage is 0-initialized. + // That way signers(pkey) => 0 indicates "not present" + // This is why we increment first, before using the index + index += 1; + + // check for duplicates + let existing_signer = self._signers.read(*oracle.signer); + assert(existing_signer == 0_usize, 'repeated signer'); + + let existing_transmitter = self._transmitters.read(*oracle.transmitter); + assert(existing_transmitter.index == 0_usize, 'repeated transmitter'); + + self._signers.write(*oracle.signer, index); + self._signers_list.write(index, *oracle.signer); + + self + ._transmitters + .write(*oracle.transmitter, Oracle { index, payment_juels: 0_u128 }); + self._transmitters_list.write(index, *oracle.transmitter); + + self._reward_from_aggregator_round_id.write(index, latest_round_id); + }; self._oracles_len.write(index); } } @@ -739,12 +737,12 @@ mod Aggregator { ); // Check all signatures are unique (we only saw each pubkey once) - // NOTE: This relies on protocol-level design constraints (MAX_ORACLES = 31, f = 10) which - // ensures we have enough bits to store a count for each oracle. Whenever the MAX_ORACLES - // is updated, the signed_count parameter should be reconsidered. + // NOTE: This relies on protocol-level design constraints (MAX_ORACLES = 31, f = 10) + // which ensures we have enough bits to store a count for each oracle. Whenever the + // MAX_ORACLES is updated, the signed_count parameter should be reconsidered. // - // Although 31 bits is enough, we use a u128 here for simplicity because BitAnd and BitOr - // operators are defined only for u128 and u256. + // Although 31 bits is enough, we use a u128 here for simplicity because BitAnd and + // BitOr operators are defined only for u128 and u256. assert(MAX_ORACLES == 31_u32, ''); self.verify_signatures(msg, ref signatures, 0_u128); @@ -827,22 +825,21 @@ mod Aggregator { mut signed_count: u128 ) { let mut span = signatures.span(); - while let Option::Some(signature) = span - .pop_front() { - let index = self._signers.read(*signature.public_key); - assert(index != 0_usize, 'invalid signer'); // 0 index == uninitialized - - let indexed_bit = pow(2_u128, index.into() - 1_u128); - let prev_signed_count = signed_count; - signed_count = signed_count | indexed_bit; - assert(prev_signed_count != signed_count, 'duplicate signer'); - - let is_valid = ecdsa::check_ecdsa_signature( - msg, *signature.public_key, *signature.r, *signature.s - ); + while let Option::Some(signature) = span.pop_front() { + let index = self._signers.read(*signature.public_key); + assert(index != 0_usize, 'invalid signer'); // 0 index == uninitialized - assert(is_valid, ''); - }; + let indexed_bit = pow(2_u128, index.into() - 1_u128); + let prev_signed_count = signed_count; + signed_count = signed_count | indexed_bit; + assert(prev_signed_count != signed_count, 'duplicate signer'); + + let is_valid = ecdsa::check_ecdsa_signature( + msg, *signature.public_key, *signature.r, *signature.s + ); + + assert(is_valid, ''); + }; } } @@ -1189,26 +1186,25 @@ mod Aggregator { impl PayeeManagementImpl of super::PayeeManagement { fn set_payees(ref self: ContractState, mut payees: Array) { self.ownable.assert_only_owner(); - while let Option::Some(payee) = payees - .pop_front() { - let current_payee = self._payees.read(payee.transmitter); - let is_unset = current_payee.is_zero(); - let is_same = current_payee == payee.payee; - assert(is_unset | is_same, 'payee already set'); - - self._payees.write(payee.transmitter, payee.payee); - - self - .emit( - Event::PayeeshipTransferred( - PayeeshipTransferred { - transmitter: payee.transmitter, - previous: current_payee, - current: payee.payee - } - ) - ); - } + while let Option::Some(payee) = payees.pop_front() { + let current_payee = self._payees.read(payee.transmitter); + let is_unset = current_payee.is_zero(); + let is_same = current_payee == payee.payee; + assert(is_unset | is_same, 'payee already set'); + + self._payees.write(payee.transmitter, payee.payee); + + self + .emit( + Event::PayeeshipTransferred( + PayeeshipTransferred { + transmitter: payee.transmitter, + previous: current_payee, + current: payee.payee + } + ) + ); + } } fn transfer_payeeship( diff --git a/contracts/src/ocr2/aggregator_proxy.cairo b/contracts/src/ocr2/aggregator_proxy.cairo index 9859c9ccd..16cf20264 100644 --- a/contracts/src/ocr2/aggregator_proxy.cairo +++ b/contracts/src/ocr2/aggregator_proxy.cairo @@ -46,6 +46,7 @@ mod AggregatorProxy { use starknet::storage_write_syscall; use starknet::storage_address_from_base_and_offset; use starknet::class_hash::ClassHash; + use starknet::storage::Map; use openzeppelin::access::ownable::OwnableComponent; @@ -88,7 +89,7 @@ mod AggregatorProxy { access_control: AccessControlComponent::Storage, _current_phase: Phase, _proposed_aggregator: ContractAddress, - _phases: LegacyMap + _phases: Map } #[event] @@ -178,7 +179,7 @@ mod AggregatorProxy { self._set_aggregator(address); } - // -- Upgradeable -- + // -- Upgradeable -- #[abi(embed_v0)] impl UpgradeableImpl of IUpgradeable { diff --git a/contracts/src/ocr2/mocks/mock_aggregator.cairo b/contracts/src/ocr2/mocks/mock_aggregator.cairo index eceb7d3c8..310fbc206 100644 --- a/contracts/src/ocr2/mocks/mock_aggregator.cairo +++ b/contracts/src/ocr2/mocks/mock_aggregator.cairo @@ -13,6 +13,7 @@ trait IMockAggregator { mod MockAggregator { use array::ArrayTrait; use starknet::contract_address_const; + use starknet::storage::Map; use traits::Into; use chainlink::ocr2::aggregator::IAggregator; @@ -25,7 +26,7 @@ mod MockAggregator { #[storage] struct Storage { - _transmissions: LegacyMap, + _transmissions: Map, _latest_aggregator_round_id: u128, _decimals: u8 } diff --git a/contracts/src/tests/test_access_controller.cairo b/contracts/src/tests/test_access_controller.cairo index a78715cf4..f2466f132 100644 --- a/contracts/src/tests/test_access_controller.cairo +++ b/contracts/src/tests/test_access_controller.cairo @@ -20,7 +20,8 @@ use chainlink::libraries::access_control::{ }; use snforge_std::{ - declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, DeclareResultTrait }; @@ -50,7 +51,9 @@ fn test_access_control() { let calldata = array![owner.into(), // owner ]; - let (accessControllerAddr, _) = declare("AccessController").unwrap().deploy(@calldata).unwrap(); + let contract = declare("AccessController").unwrap().contract_class(); + + let (accessControllerAddr, _) = contract.deploy(@calldata).unwrap(); should_implement_access_control(accessControllerAddr, owner); } diff --git a/contracts/src/tests/test_aggregator.cairo b/contracts/src/tests/test_aggregator.cairo index 77719d6f9..6225a9564 100644 --- a/contracts/src/tests/test_aggregator.cairo +++ b/contracts/src/tests/test_aggregator.cairo @@ -12,6 +12,7 @@ use traits::Into; use traits::TryInto; use option::OptionTrait; use core::result::ResultTrait; +use core::panic_with_felt252; use chainlink::ocr2::aggregator::pow; use chainlink::ocr2::aggregator::Aggregator; @@ -26,7 +27,8 @@ 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 + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, DeclareResultTrait }; #[test] @@ -90,6 +92,7 @@ fn setup() -> ( let (billingAccessControllerAddr, _) = declare("AccessController") .unwrap() + .contract_class() .deploy(@calldata) .unwrap(); @@ -102,7 +105,11 @@ fn setup() -> ( acc1.into(), // owner = acc1; ]; - let (linkTokenAddr, _) = declare("LinkToken").unwrap().deploy(@calldata).unwrap(); + let (linkTokenAddr, _) = declare("LinkToken") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); let linkToken = ILinkTokenDispatcher { contract_address: linkTokenAddr }; @@ -124,7 +131,11 @@ fn test_ownable() { 123, // description ]; - let (aggregatorAddr, _) = declare("Aggregator").unwrap().deploy(@calldata).unwrap(); + let (aggregatorAddr, _) = declare("Aggregator") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); should_implement_ownable(aggregatorAddr, account); } @@ -143,7 +154,11 @@ fn test_access_control() { 123, // description ]; - let (aggregatorAddr, _) = declare("Aggregator").unwrap().deploy(@calldata).unwrap(); + let (aggregatorAddr, _) = declare("Aggregator") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); // let (aggregatorAddr, _) = deploy_syscall( // Aggregator::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false @@ -153,7 +168,6 @@ fn test_access_control() { should_implement_access_control(aggregatorAddr, account); } - #[test] #[should_panic(expected: ('Caller is not the owner',))] fn test_upgrade_non_owner() { diff --git a/contracts/src/tests/test_aggregator_proxy.cairo b/contracts/src/tests/test_aggregator_proxy.cairo index eb7e350bc..3a586dc44 100644 --- a/contracts/src/tests/test_aggregator_proxy.cairo +++ b/contracts/src/tests/test_aggregator_proxy.cairo @@ -25,7 +25,8 @@ 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 + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, DeclareResultTrait }; @@ -49,19 +50,20 @@ fn setup() -> ( let mut calldata = ArrayTrait::new(); calldata.append(8); // decimals = 8 - let contract_class = declare("MockAggregator").unwrap(); + let contract = declare("MockAggregator").unwrap().contract_class(); - let (mockAggregatorAddr1, _) = contract_class.deploy(@calldata).unwrap(); + let (mockAggregatorAddr1, _) = contract.deploy(@calldata).unwrap(); let mockAggregator1 = IMockAggregatorDispatcher { contract_address: mockAggregatorAddr1 }; // Deploy mock aggregator 2 // note: deployment address is deterministic based on deploy_syscall parameters - // so we need to change the decimals parameter to avoid an address conflict with mock aggregator 1 + // 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, _) = contract_class.deploy(@calldata).unwrap(); + let (mockAggregatorAddr2, _) = contract.deploy(@calldata).unwrap(); let mockAggregator2 = IMockAggregatorDispatcher { contract_address: mockAggregatorAddr2 }; @@ -75,7 +77,11 @@ fn test_ownable() { // Deploy aggregator proxy let calldata = array![account.into(), // owner = account mockAggregatorAddr.into(),]; - let (aggregatorProxyAddr, _) = declare("AggregatorProxy").unwrap().deploy(@calldata).unwrap(); + let (aggregatorProxyAddr, _) = declare("AggregatorProxy") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); should_implement_ownable(aggregatorProxyAddr, account); } @@ -87,7 +93,11 @@ fn test_access_control() { let calldata = array![account.into(), // owner = account mockAggregatorAddr.into(),]; - let (aggregatorProxyAddr, _) = declare("AggregatorProxy").unwrap().deploy(@calldata).unwrap(); + let (aggregatorProxyAddr, _) = declare("AggregatorProxy") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); should_implement_access_control(aggregatorProxyAddr, account); } @@ -118,7 +128,7 @@ fn test_query_latest_round_data() { assert(round.started_at == 9, 'started_at should be 9'); assert(round.updated_at == 8, 'updated_at should be 8'); - // latest_answer matches up with latest_round_data + // latest_answer matches up with latest_round_data let latest_answer = AggregatorProxyImpl::latest_answer(@state); assert(latest_answer == 10, '(latest) answer should be 10'); } diff --git a/contracts/src/tests/test_erc677.cairo b/contracts/src/tests/test_erc677.cairo index b81394a21..ecb36b7a5 100644 --- a/contracts/src/tests/test_erc677.cairo +++ b/contracts/src/tests/test_erc677.cairo @@ -17,7 +17,8 @@ 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 + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, DeclareResultTrait }; #[starknet::interface] @@ -29,7 +30,8 @@ use chainlink::token::mock::valid_erc667_receiver::{ MockValidReceiver, MockValidReceiverDispatcher, MockValidReceiverDispatcherTrait }; -// Ignored tests are dependent on upgrading our version of cairo to include this PR https://github.com/starkware-libs/cairo/pull/2912/files +// Ignored tests are dependent on upgrading our version of cairo to include this PR +// https://github.com/starkware-libs/cairo/pull/2912/files fn setup() -> ContractAddress { let account: ContractAddress = contract_address_const::<1>(); @@ -41,7 +43,11 @@ fn setup() -> ContractAddress { fn setup_valid_receiver() -> (ContractAddress, MockValidReceiverDispatcher) { let calldata = ArrayTrait::new(); - let (address, _) = declare("ValidReceiver").unwrap().deploy(@calldata).unwrap(); + let (address, _) = declare("ValidReceiver") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); let contract = MockValidReceiverDispatcher { contract_address: address }; (address, contract) @@ -51,7 +57,11 @@ fn setup_valid_receiver() -> (ContractAddress, MockValidReceiverDispatcher) { fn setup_invalid_receiver() -> (ContractAddress, MockInvalidReceiverDispatcher) { let calldata = ArrayTrait::new(); - let (address, _) = declare("InvalidReceiver").unwrap().deploy(@calldata).unwrap(); + let (address, _) = declare("InvalidReceiver") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); let contract = MockInvalidReceiverDispatcher { contract_address: address }; (address, contract) @@ -62,7 +72,8 @@ type ComponentState = fn transfer_and_call(receiver: ContractAddress) { let data = ArrayTrait::::new(); - // have to send 0 because ERC20 is not initialized with starting supply when using this library by itself + // have to send 0 because ERC20 is not initialized with starting supply when using this library + // by itself let mut state: ComponentState = ERC677Component::component_state_for_testing(); state.transfer_and_call(receiver, u256 { high: 0, low: 0 }, data); } diff --git a/contracts/src/tests/test_link_token.cairo b/contracts/src/tests/test_link_token.cairo index 1ee0f9946..709bc6413 100644 --- a/contracts/src/tests/test_link_token.cairo +++ b/contracts/src/tests/test_link_token.cairo @@ -18,11 +18,12 @@ 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 + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, DeclareResultTrait }; -// only tests link token specific functionality +// only tests link token specific functionality // erc20 and erc677 functionality is already tested elsewhere fn STATE() -> LinkToken::ContractState { @@ -44,7 +45,7 @@ fn test_ownable() { calldata.append(class_hash_const::<123>().into()); // minter calldata.append(account.into()); // owner - let (linkAddr, _) = declare("LinkToken").unwrap().deploy(@calldata).unwrap(); + let (linkAddr, _) = declare("LinkToken").unwrap().contract_class().deploy(@calldata).unwrap(); should_implement_ownable(linkAddr, account); } @@ -101,7 +102,7 @@ fn test_permissioned_mint_from_nonminter() { } #[test] -#[should_panic(expected: ('u256_sub Overflow',))] +#[should_panic(expected: ('ERC20: insufficient balance',))] fn test_permissioned_burn_from_minter() { let zero = 0; let sender = setup(); diff --git a/contracts/src/tests/test_multisig.cairo b/contracts/src/tests/test_multisig.cairo index 77eeb17b7..499eb7fe1 100644 --- a/contracts/src/tests/test_multisig.cairo +++ b/contracts/src/tests/test_multisig.cairo @@ -19,7 +19,7 @@ use chainlink::multisig::{IMultisigDispatcher}; use snforge_std::{ declare, ContractClassTrait, start_cheat_caller_address_global, - stop_cheat_caller_address_global, cheat_caller_address, CheatSpan + stop_cheat_caller_address_global, cheat_caller_address, CheatSpan, DeclareResultTrait }; fn STATE() -> Multisig::ContractState { @@ -123,7 +123,7 @@ fn test_submit_transaction() { assert(transaction.calldata_len == sample_calldata().len(), 'should match calldata length'); assert(!transaction.executed, 'should not be executed'); assert(transaction.confirmations == 0, 'should not have confirmations'); -// TODO: compare calldata when loops are supported + // TODO: compare calldata when loops are supported } #[test] @@ -274,7 +274,11 @@ fn test_execute() { let calldata = ArrayTrait::new(); - let (test_address, _) = declare("MockMultisigTarget").unwrap().deploy(@calldata).unwrap(); + let (test_address, _) = declare("MockMultisigTarget") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); start_cheat_caller_address_global(signer1); let increment_calldata = array![42, 100]; @@ -331,7 +335,11 @@ fn test_execute_after_set_signers() { 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_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -363,7 +371,11 @@ fn test_execute_after_set_signers_and_threshold() { 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_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -395,7 +407,11 @@ fn test_execute_after_set_threshold() { 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_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -427,7 +443,11 @@ fn test_set_threshold() { 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_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; assert(multisig.get_threshold() == init_threshold, 'invalid init threshold'); @@ -451,16 +471,20 @@ fn test_recursive_set_threshold() { 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_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); // Gets a dispatcher (so we can call methods on the deployed contract) let multisig = IMultisigDispatcher { contract_address: multisig_address }; // Checks that the threshold was correctly initialized on deployment assert(multisig.get_threshold() == init_threshold, 'invalid init threshold'); - // Recursive call occurs here - this code proposes a transaction to the - // multisig contract that calls the set_threshold function on the multisig - // contract. + // Recursive call occurs here - this code proposes a transaction to the + // multisig contract that calls the set_threshold function on the multisig + // contract. let mut set_threshold_calldata = ArrayTrait::new(); Serde::serialize(@new_threshold, ref set_threshold_calldata); start_cheat_caller_address_global(s1); @@ -497,7 +521,11 @@ fn test_set_signers() { Serde::serialize(@init_signers, ref deploy_calldata); Serde::serialize(@threshold, ref deploy_calldata); - let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); + let (multisig_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -531,7 +559,11 @@ fn test_recursive_set_signers() { Serde::serialize(@init_signers, ref deploy_calldata); Serde::serialize(@init_threshold, ref deploy_calldata); - let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); + let (multisig_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); // Gets a dispatcher (so we can call methods on the deployed contract) let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -543,9 +575,9 @@ fn test_recursive_set_signers() { assert(*returned_signers.at(1) == s2, 'should match signer 2'); assert(multisig.get_threshold() == 2, 'wrong init threshold'); - // Recursive call occurs here - this code proposes a transaction to the - // multisig contract that calls the set_signers function on the multisig - // contract. + // Recursive call occurs here - this code proposes a transaction to the + // multisig contract that calls the set_signers function on the multisig + // contract. let mut set_signers_calldata = ArrayTrait::new(); Serde::serialize(@new_signers, ref set_signers_calldata); start_cheat_caller_address_global(s1); @@ -585,7 +617,11 @@ fn test_set_signers_and_threshold() { Serde::serialize(@init_signers, ref deploy_calldata); Serde::serialize(@init_threshold, ref deploy_calldata); - let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); + let (multisig_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -623,7 +659,11 @@ fn test_recursive_set_signers_and_threshold() { Serde::serialize(@init_signers, ref deploy_calldata); Serde::serialize(@init_threshold, ref deploy_calldata); - let (multisig_address, _) = declare("Multisig").unwrap().deploy(@deploy_calldata).unwrap(); + let (multisig_address, _) = declare("Multisig") + .unwrap() + .contract_class() + .deploy(@deploy_calldata) + .unwrap(); // Gets a dispatcher (so we can call methods on the deployed contract) let multisig = IMultisigDispatcher { contract_address: multisig_address }; @@ -636,8 +676,8 @@ fn test_recursive_set_signers_and_threshold() { assert(*returned_signers.at(2) == s3, 'should match signer 3'); assert(multisig.get_threshold() == 3, 'wrong init threshold'); - // Recursive call occurs here - this code proposes a transaction to the - // multisig contract that calls the set_signers_and_threshold function + // Recursive call occurs here - this code proposes a transaction to the + // multisig contract that calls the set_signers_and_threshold function // on the multisig contract. let mut set_signers_and_threshold_calldata = ArrayTrait::new(); Serde::serialize(@new_signers, ref set_signers_and_threshold_calldata); diff --git a/contracts/src/tests/test_sequencer_uptime_feed.cairo b/contracts/src/tests/test_sequencer_uptime_feed.cairo index a7b44ff24..e99d3b4c4 100644 --- a/contracts/src/tests/test_sequencer_uptime_feed.cairo +++ b/contracts/src/tests/test_sequencer_uptime_feed.cairo @@ -30,7 +30,8 @@ use chainlink::emergency::sequencer_uptime_feed::{ }; use snforge_std::{ - declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, DeclareResultTrait }; @@ -52,7 +53,11 @@ fn setup() -> (ContractAddress, ContractAddress, ISequencerUptimeFeedDispatcher) account.into() // owner ]; - let (sequencerFeedAddr, _) = declare("SequencerUptimeFeed").unwrap().deploy(@calldata).unwrap(); + let (sequencerFeedAddr, _) = declare("SequencerUptimeFeed") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); let sequencerUptimeFeed = ISequencerUptimeFeedDispatcher { contract_address: sequencerFeedAddr @@ -74,7 +79,7 @@ fn test_access_control() { } #[test] -#[should_panic()] +#[should_panic] fn test_set_l1_sender_not_owner() { let (_, _, sequencerUptimeFeed) = setup(); start_cheat_caller_address_global(contract_address_const::<111>()); @@ -120,7 +125,7 @@ fn test_aggregator_proxy_response() { let latest_round_data = proxy.latest_round_data(); assert(latest_round_data.answer == 0, 'latest_round_data should be 0'); - // latest answer + // latest answer let latest_answer = proxy.latest_answer(); assert(latest_answer == 0, 'latest_answer should be 0'); diff --git a/contracts/src/tests/test_upgradeable.cairo b/contracts/src/tests/test_upgradeable.cairo index fee927616..6f2a56e44 100644 --- a/contracts/src/tests/test_upgradeable.cairo +++ b/contracts/src/tests/test_upgradeable.cairo @@ -17,7 +17,8 @@ use chainlink::libraries::mocks::mock_non_upgradeable::{ }; use snforge_std::{ - declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, DeclareResultTrait }; @@ -33,14 +34,18 @@ fn test_upgrade_and_call() { let calldata = array![]; - let (contractAddr, _) = declare("MockUpgradeable").unwrap().deploy(@calldata).unwrap(); + let (contractAddr, _) = declare("MockUpgradeable") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); let mockUpgradeable = IMockUpgradeableDispatcher { contract_address: contractAddr }; assert(mockUpgradeable.foo() == true, 'should call foo'); - let contract_class = declare("MockNonUpgradeable").unwrap(); + let contract = declare("MockNonUpgradeable").unwrap().contract_class(); - mockUpgradeable.upgrade(contract_class.class_hash); + mockUpgradeable.upgrade(*(contract.class_hash)); // now, contract should be different let mockNonUpgradeable = IMockNonUpgradeableDispatcher { contract_address: contractAddr }; diff --git a/contracts/src/token/link_token.cairo b/contracts/src/token/link_token.cairo index 24bdb2271..4ffe888be 100644 --- a/contracts/src/token/link_token.cairo +++ b/contracts/src/token/link_token.cairo @@ -69,15 +69,31 @@ mod LinkToken { impl MintableToken of IMintableToken { fn permissioned_mint(ref self: ContractState, account: ContractAddress, amount: u256) { only_minter(@self); - self.erc20._mint(account, amount); + self.erc20.mint(account, amount); } fn permissioned_burn(ref self: ContractState, account: ContractAddress, amount: u256) { only_minter(@self); - self.erc20._burn(account, amount); + self.erc20.burn(account, amount); } } + impl HooksImpl of ERC20Component::ERC20HooksTrait { + fn before_update( + ref self: ERC20Component::ComponentState::, + from: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) {} + + fn after_update( + ref self: ERC20Component::ComponentState::, + from: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) {} + } + #[constructor] fn constructor(ref self: ContractState, minter: ContractAddress, owner: ContractAddress) { @@ -109,12 +125,14 @@ mod LinkToken { } } - // fn increase_allowance(ref self: ContractState, spender: ContractAddress, added_value: u256) -> bool { + // fn increase_allowance(ref self: ContractState, spender: ContractAddress, added_value: u256) + // -> bool { // let mut state = ERC20::unsafe_new_contract_state(); // ERC20::ERC20Impl::increase_allowance(ref state, spender, added_value) // } - // fn decrease_allowance(ref self: ContractState, spender: ContractAddress, subtracted_value: u256) -> bool { + // fn decrease_allowance(ref self: ContractState, spender: ContractAddress, subtracted_value: + // u256) -> bool { // let mut state = ERC20::unsafe_new_contract_state(); // ERC20::ERC20Impl::decrease_allowance(ref state, spender, subtracted_value) // } diff --git a/examples/contracts/aggregator_consumer/Scarb.lock b/examples/contracts/aggregator_consumer/Scarb.lock index 5bdff8546..36b34015d 100644 --- a/examples/contracts/aggregator_consumer/Scarb.lock +++ b/examples/contracts/aggregator_consumer/Scarb.lock @@ -12,7 +12,7 @@ dependencies = [ [[package]] name = "alexandria_bytes" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_data_structures", "alexandria_math", @@ -21,7 +21,7 @@ dependencies = [ [[package]] name = "alexandria_data_structures" version = "0.2.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_encoding", ] @@ -29,7 +29,7 @@ dependencies = [ [[package]] name = "alexandria_encoding" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_bytes", "alexandria_math", @@ -39,7 +39,7 @@ dependencies = [ [[package]] name = "alexandria_math" version = "0.2.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_data_structures", ] @@ -47,7 +47,7 @@ dependencies = [ [[package]] name = "alexandria_numeric" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_math", "alexandria_searching", @@ -56,7 +56,7 @@ dependencies = [ [[package]] name = "alexandria_searching" version = "0.1.0" -source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=bcdca70afdf59c9976148e95cebad5cf63d75a7f#bcdca70afdf59c9976148e95cebad5cf63d75a7f" +source = "git+https://github.com/keep-starknet-strange/alexandria.git?rev=e1b080577aaa6889116fc8be5dde72b2fd21e397#e1b080577aaa6889116fc8be5dde72b2fd21e397" dependencies = [ "alexandria_data_structures", ] @@ -68,15 +68,102 @@ 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" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_governance", + "openzeppelin_introspection", + "openzeppelin_presets", + "openzeppelin_security", + "openzeppelin_token", + "openzeppelin_upgrades", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_access" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_account" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_governance" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_access", + "openzeppelin_introspection", +] + +[[package]] +name = "openzeppelin_introspection" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" + +[[package]] +name = "openzeppelin_presets" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_introspection", + "openzeppelin_token", + "openzeppelin_upgrades", +] + +[[package]] +name = "openzeppelin_security" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" + +[[package]] +name = "openzeppelin_token" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" +dependencies = [ + "openzeppelin_account", + "openzeppelin_governance", + "openzeppelin_introspection", +] + +[[package]] +name = "openzeppelin_upgrades" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" + +[[package]] +name = "openzeppelin_utils" +version = "0.15.1" +source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.15.1#2f8a93d762858714095a1d391afffa9e21df6983" + +[[package]] +name = "snforge_scarb_plugin" +version = "0.1.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.28.0#4dfe39d96690ed6b3d56971512700de3f58288ea" [[package]] name = "snforge_std" -version = "0.27.0" -source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" +version = "0.28.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.28.0#4dfe39d96690ed6b3d56971512700de3f58288ea" +dependencies = [ + "snforge_scarb_plugin", +] diff --git a/examples/contracts/aggregator_consumer/Scarb.toml b/examples/contracts/aggregator_consumer/Scarb.toml index 8da76d784..623a240cd 100644 --- a/examples/contracts/aggregator_consumer/Scarb.toml +++ b/examples/contracts/aggregator_consumer/Scarb.toml @@ -6,7 +6,10 @@ [package] name = "aggregator_consumer" version = "0.1.0" -cairo-version = "2.6.3" +cairo-version = "2.7.1" + +[scripts] +test = "snforge test" # [scripts] # test = "snforge test" @@ -14,9 +17,11 @@ cairo-version = "2.6.3" # 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.27.0" } chainlink = { path = "../../../contracts" } -starknet = ">=2.6.3" +starknet = "2.7.1" + +[dev-dependencies] +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.29.0" } [lib] diff --git a/examples/contracts/aggregator_consumer/scripts/Scarb.toml b/examples/contracts/aggregator_consumer/scripts/Scarb.toml index bf06f1d83..91db3b33c 100644 --- a/examples/contracts/aggregator_consumer/scripts/Scarb.toml +++ b/examples/contracts/aggregator_consumer/scripts/Scarb.toml @@ -1,15 +1,15 @@ [package] name = "src" version = "0.1.0" -cairo-version = "2.6.3" +cairo-version = "2.7.1" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -sncast_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.21.0" } +sncast_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.29.0" } chainlink = { path = "../../../../contracts" } aggregator_consumer = { path = "../" } -starknet = ">=2.6.3" +starknet = "2.7.1" [lib] casm = true @@ -19,6 +19,5 @@ casm = true build-external-contracts = [ "chainlink::emergency::sequencer_uptime_feed::SequencerUptimeFeed", "chainlink::ocr2::mocks::mock_aggregator::MockAggregator", - "aggregator_consumer::ocr2::consumer::AggregatorConsumer" + "aggregator_consumer::ocr2::consumer::AggregatorConsumer", ] - diff --git a/examples/contracts/aggregator_consumer/scripts/src/mock_aggregator/set_latest_round.cairo b/examples/contracts/aggregator_consumer/scripts/src/mock_aggregator/set_latest_round.cairo index d5a2a0150..8b853bd43 100644 --- a/examples/contracts/aggregator_consumer/scripts/src/mock_aggregator/set_latest_round.cairo +++ b/examples/contracts/aggregator_consumer/scripts/src/mock_aggregator/set_latest_round.cairo @@ -9,7 +9,7 @@ fn main() { .try_into() .unwrap(); - // Feel free to modify these + // Feel free to modify these let answer = 1; let block_num = 12345; let observation_timestamp = 1711716556; diff --git a/examples/contracts/aggregator_consumer/tests/test_consumer.cairo b/examples/contracts/aggregator_consumer/tests/test_consumer.cairo index b7afc0b70..6cd305c8c 100644 --- a/examples/contracts/aggregator_consumer/tests/test_consumer.cairo +++ b/examples/contracts/aggregator_consumer/tests/test_consumer.cairo @@ -1,4 +1,4 @@ -use snforge_std::{declare, ContractClassTrait}; +use starknet::ContractAddress; use chainlink::ocr2::mocks::mock_aggregator::IMockAggregatorDispatcherTrait; use chainlink::ocr2::mocks::mock_aggregator::IMockAggregatorDispatcher; @@ -8,13 +8,14 @@ use chainlink::ocr2::aggregator_proxy::IAggregatorDispatcher; use aggregator_consumer::ocr2::consumer::IAggregatorConsumerDispatcherTrait; use aggregator_consumer::ocr2::consumer::IAggregatorConsumerDispatcher; -use starknet::ContractAddress; +use snforge_std::{declare, ContractClassTrait, DeclareResultTrait}; + fn deploy_mock_aggregator(decimals: u8) -> ContractAddress { let mut calldata = ArrayTrait::new(); calldata.append(decimals.into()); - let contract = declare("MockAggregator").unwrap(); + let contract = declare("MockAggregator").unwrap().contract_class(); let (contract_address, _) = contract.deploy(@calldata).unwrap(); @@ -25,7 +26,7 @@ fn deploy_consumer(aggregator_address: ContractAddress) -> ContractAddress { let mut calldata = ArrayTrait::new(); calldata.append(aggregator_address.into()); - let contract = declare("AggregatorConsumer").unwrap(); + let contract = declare("AggregatorConsumer").unwrap().contract_class(); let (contract_address, _) = contract.deploy(@calldata).unwrap(); @@ -118,7 +119,7 @@ fn test_set_and_read_answer() { assert(latest_round.started_at == observation_timestamp, 'bad started_at'); assert(latest_round.updated_at == transmission_timestamp, 'bad updated_at'); - // Now let's test that we can set the answer + // Now let's test that we can set the answer consumer_dispatcher.set_answer(latest_round.answer); assert(answer == consumer_dispatcher.read_answer(), 'Invalid answer'); } 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 91874ba2e..0b59e0243 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 @@ -13,13 +13,18 @@ use starknet::get_caller_address; use starknet::ContractAddress; use snforge_std::{ - declare, ContractClassTrait, start_cheat_caller_address_global, stop_cheat_caller_address_global + declare, ContractClassTrait, start_cheat_caller_address_global, + stop_cheat_caller_address_global, DeclareResultTrait }; fn deploy_mock_aggregator(decimals: u8) -> ContractAddress { let mut calldata = ArrayTrait::new(); calldata.append(decimals.into()); - let (contract_address, _) = declare("MockAggregator").unwrap().deploy(@calldata).unwrap(); + let (contract_address, _) = declare("MockAggregator") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); contract_address } @@ -27,7 +32,11 @@ fn deploy_uptime_feed(initial_status: u128, owner_address: ContractAddress) -> C let mut calldata = ArrayTrait::new(); calldata.append(initial_status.into()); calldata.append(owner_address.into()); - let (contract_address, _) = declare("SequencerUptimeFeed").unwrap().deploy(@calldata).unwrap(); + let (contract_address, _) = declare("SequencerUptimeFeed") + .unwrap() + .contract_class() + .deploy(@calldata) + .unwrap(); contract_address } @@ -39,6 +48,7 @@ fn deploy_price_consumer( calldata.append(aggregator_address.into()); let (contract_address, _) = declare("AggregatorPriceConsumer") .unwrap() + .contract_class() .deploy(@calldata) .unwrap(); contract_address @@ -65,11 +75,11 @@ fn test_get_latest_price() { IAccessControllerDispatcher { contract_address: uptime_feed_address } .add_access(price_consumer_address); - // The get_latest_price function returns the mock aggregator's latest round answer. At - // this point in the test, there is only one round that is initialized and that is the - // one that the sequencer uptime feed creates when it is deployed. In its constructor, - // 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 + // The get_latest_price function returns the mock aggregator's latest round answer. At + // this point in the test, there is only one round that is initialized and that is the + // one that the sequencer uptime feed creates when it is deployed. In its constructor, + // 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_cheat_caller_address_global(price_consumer_address); // start_prank(CheatTarget::All, price_consumer_address); diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 9302ca824..1734db1b8 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -1,24 +1,30 @@ # This is the default configuration so OCR2 tests can run without issues [ChainlinkImage] -image="public.ecr.aws/chainlink/chainlink" -version="2.9.0" +image = "public.ecr.aws/chainlink/chainlink" +version = "2.9.0" [Logging] -test_log_collect=false +test_log_collect = false [Logging.LogStream] -log_targets=["file"] -log_producer_timeout="10s" -log_producer_retry_limit=10 +log_targets = ["file"] +log_producer_timeout = "10s" +log_producer_retry_limit = 10 [Network] -selected_networks=["SIMULATED"] # Not needed for Starknet but mandatory from CTF (do not change) +selected_networks = [ + "SIMULATED", +] # Not needed for Starknet but mandatory from CTF (do not change) [Network.RpcHttpUrls] -simulated = ["http://127.0.0.1"] # Not needed for Starknet but mandatory from CTF (do not change) +simulated = [ + "http://127.0.0.1", +] # Not needed for Starknet but mandatory from CTF (do not change) [Network.RpcWsUrls] -simulated = ["wss://127.0.0.1"] # Not needed for Starknet but mandatory from CTF (do not change) +simulated = [ + "wss://127.0.0.1", +] # Not needed for Starknet but mandatory from CTF (do not change) [Common] internal_docker_repo = "public.ecr.aws/chainlink" @@ -26,7 +32,7 @@ inside_k8 = false network = "localnet" user = "satoshi" stateful_db = false -devnet_image = "shardlabs/starknet-devnet-rs:a147b4cd72f9ce9d1fa665d871231370db0f51c7" +devnet_image = "shardlabs/starknet-devnet-rs:438da575b2a514c44d8a70ca6169f9dd7e585b2c" postgres_version = "15.7" [OCR2] diff --git a/ops/charts/devnet/templates/deployment.yaml b/ops/charts/devnet/templates/deployment.yaml index f3c841bb6..5b372249d 100644 --- a/ops/charts/devnet/templates/deployment.yaml +++ b/ops/charts/devnet/templates/deployment.yaml @@ -29,7 +29,7 @@ spec: {{- if eq .Values.real_node true }} image: "{{ .Values.repository | default "eqlabs/pathfinder"}}:{{ .Values.tag | default "v0.1.8-alpha"}}" {{- else }} - image: "{{ .Values.repository | default "shardlabs/starknet-devnet-rs"}}:{{ .Values.tag | default "a147b4cd72f9ce9d1fa665d871231370db0f51c7"}}" + image: "{{ .Values.repository | default "shardlabs/starknet-devnet-rs"}}:{{ .Values.tag | default "438da575b2a514c44d8a70ca6169f9dd7e585b2c"}}" args: ["--port", {{ .Values.service.internalPort | quote}}, "--seed", {{ .Values.seed | quote}}, "--account-class", "cairo1", "--gas-price", "1", "--data-gas-price", "1"] {{- end }} imagePullPolicy: IfNotPresent diff --git a/ops/devnet/environment.go b/ops/devnet/environment.go index 6948a91e2..b801d7e4d 100644 --- a/ops/devnet/environment.go +++ b/ops/devnet/environment.go @@ -73,7 +73,7 @@ func defaultProps() map[string]any { "starknet-dev": map[string]any{ "image": map[string]any{ "image": "shardlabs/starknet-devnet-rs", - "version": "a147b4cd72f9ce9d1fa665d871231370db0f51c7", + "version": "438da575b2a514c44d8a70ca6169f9dd7e585b2c", }, "resources": map[string]any{ "requests": map[string]any{ diff --git a/ops/scripts/devnet-hardhat.sh b/ops/scripts/devnet-hardhat.sh index c56d67880..c9a0a677a 100755 --- a/ops/scripts/devnet-hardhat.sh +++ b/ops/scripts/devnet-hardhat.sh @@ -13,10 +13,10 @@ bash "$(dirname -- "$0")/devnet-hardhat-down.sh" echo "Checking CPU structure..." if [[ $cpu_struct == *"arm"* ]]; then echo "Starting arm devnet container..." - container_version="${CONTAINER_VERSION:-a147b4cd72f9ce9d1fa665d871231370db0f51c7}-arm" + container_version="${CONTAINER_VERSION:-438da575b2a514c44d8a70ca6169f9dd7e585b2c}-arm" else echo "Starting i386 devnet container..." - container_version="${CONTAINER_VERSION:-a147b4cd72f9ce9d1fa665d871231370db0f51c7}" + container_version="${CONTAINER_VERSION:-438da575b2a514c44d8a70ca6169f9dd7e585b2c}" fi echo "Starting starknet-devnet" diff --git a/scripts/devnet.sh b/scripts/devnet.sh index 70fb3a3a2..921484b04 100755 --- a/scripts/devnet.sh +++ b/scripts/devnet.sh @@ -13,10 +13,10 @@ echo "Checking CPU structure..." if [[ $cpu_struct == *"arm"* ]] then echo "Starting arm devnet container..." - container_version="a147b4cd72f9ce9d1fa665d871231370db0f51c7-arm" + container_version="438da575b2a514c44d8a70ca6169f9dd7e585b2c-arm" else echo "Starting i386 devnet container..." - container_version="a147b4cd72f9ce9d1fa665d871231370db0f51c7" + container_version="438da575b2a514c44d8a70ca6169f9dd7e585b2c" fi echo "Starting starknet-devnet"