Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BCI-1923: Cairo Test Upgradeable #326

Merged
merged 6 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mockery 2.22.1
golangci-lint 1.51.2
actionlint 1.6.12
shellcheck 0.8.0
scarb 0.7.0

# Kubernetes
k3d 5.4.4
Expand Down
12 changes: 7 additions & 5 deletions contracts/src/access_control/access_controller.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod AccessController {

use chainlink::libraries::access_control::{AccessControl, IAccessController};
use chainlink::libraries::ownable::{Ownable, IOwnable};
use chainlink::libraries::upgradeable::Upgradeable;
use chainlink::libraries::upgradeable::{Upgradeable, IUpgradeable};

#[storage]
struct Storage {}
Expand Down Expand Up @@ -98,9 +98,11 @@ mod AccessController {
}

#[external(v0)]
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
let ownable = Ownable::unsafe_new_contract_state();
Ownable::assert_only_owner(@ownable);
Upgradeable::upgrade(new_impl);
impl UpgradeableImpl of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
let ownable = Ownable::unsafe_new_contract_state();
Ownable::assert_only_owner(@ownable);
Upgradeable::upgrade(new_impl);
}
}
}
1 change: 1 addition & 0 deletions contracts/src/libraries.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ mod ownable;
mod access_control;
mod token;
mod upgradeable;
mod mocks;
2 changes: 2 additions & 0 deletions contracts/src/libraries/mocks.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod mock_upgradeable;
mod mock_non_upgradeable;
20 changes: 20 additions & 0 deletions contracts/src/libraries/mocks/mock_non_upgradeable.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#[starknet::interface]
trait IMockNonUpgradeable<TContractState> {
fn bar(self: @TContractState) -> bool;
}

#[starknet::contract]
mod MockNonUpgradeable {
#[storage]
struct Storage {}

#[constructor]
fn constructor(ref self: ContractState) {}

#[external(v0)]
impl MockNonUpgradeableImpl of super::IMockNonUpgradeable<ContractState> {
fn bar(self: @ContractState) -> bool {
true
}
}
}
31 changes: 31 additions & 0 deletions contracts/src/libraries/mocks/mock_upgradeable.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use starknet::class_hash::ClassHash;

#[starknet::interface]
trait IMockUpgradeable<TContractState> {
fn foo(self: @TContractState) -> bool;
fn upgrade(ref self: TContractState, new_impl: ClassHash);
}

#[starknet::contract]
mod MockUpgradeable {
use starknet::class_hash::ClassHash;

use chainlink::libraries::upgradeable::Upgradeable;

#[storage]
struct Storage {}

#[constructor]
fn constructor(ref self: ContractState) {}

#[external(v0)]
impl MockUpgradeableImpl of super::IMockUpgradeable<ContractState> {
fn foo(self: @ContractState) -> bool {
true
}

fn upgrade(ref self: ContractState, new_impl: ClassHash) {
Upgradeable::upgrade(new_impl)
}
}
}
1 change: 1 addition & 0 deletions contracts/src/libraries/upgradeable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use starknet::class_hash::ClassHash;

#[starknet::interface]
trait IUpgradeable<TContractState> {
// note: any contract that uses this module will have a mutable reference to contract state
fn upgrade(ref self: TContractState, new_impl: ClassHash);
}

Expand Down
16 changes: 9 additions & 7 deletions contracts/src/multisig.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ trait IMultisig<TContractState> {
fn is_executed(self: @TContractState, nonce: u128) -> bool;
fn get_transaction(self: @TContractState, nonce: u128) -> (Transaction, Array::<felt252>);
fn type_and_version(self: @TContractState) -> felt252;
fn upgrade(ref self: TContractState, new_impl: ClassHash);
fn submit_transaction(
ref self: TContractState,
to: ContractAddress,
Expand Down Expand Up @@ -93,7 +92,7 @@ mod Multisig {
use starknet::storage_write_syscall;
use starknet::class_hash::ClassHash;

use chainlink::libraries::upgradeable::Upgradeable;
use chainlink::libraries::upgradeable::{Upgradeable, IUpgradeable};

#[event]
#[derive(Drop, starknet::Event)]
Expand Down Expand Up @@ -162,6 +161,14 @@ mod Multisig {
self._set_threshold(threshold);
}

#[external(v0)]
impl UpgradeableImpl of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
self._require_multisig();
Upgradeable::upgrade(new_impl)
}
}

#[external(v0)]
impl MultisigImpl of super::IMultisig<ContractState> {
/// Views
Expand Down Expand Up @@ -214,11 +221,6 @@ mod Multisig {

/// Externals

fn upgrade(ref self: ContractState, new_impl: ClassHash) {
self._require_multisig();
Upgradeable::upgrade(new_impl)
}

fn submit_transaction(
ref self: ContractState,
to: ContractAddress,
Expand Down
12 changes: 7 additions & 5 deletions contracts/src/ocr2/aggregator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ mod Aggregator {
use chainlink::utils::split_felt;
use chainlink::libraries::ownable::{Ownable, IOwnable};
use chainlink::libraries::access_control::AccessControl;
use chainlink::libraries::upgradeable::Upgradeable;
use chainlink::libraries::upgradeable::{Upgradeable, IUpgradeable};

use openzeppelin::token::erc20::interface::{IERC20, IERC20Dispatcher, IERC20DispatcherTrait};

Expand Down Expand Up @@ -375,10 +375,12 @@ mod Aggregator {
// --- Upgradeable ---

#[external(v0)]
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
let ownable = Ownable::unsafe_new_contract_state();
Ownable::assert_only_owner(@ownable);
Upgradeable::upgrade(new_impl)
impl UpgradeableImpl of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
let ownable = Ownable::unsafe_new_contract_state();
Ownable::assert_only_owner(@ownable);
Upgradeable::upgrade(new_impl)
}
}

// --- Ownership ---
Expand Down
13 changes: 8 additions & 5 deletions contracts/src/ocr2/aggregator_proxy.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod AggregatorProxy {
use chainlink::libraries::ownable::{Ownable, IOwnable};
use chainlink::libraries::access_control::{AccessControl, IAccessController};
use chainlink::utils::split_felt;
use chainlink::libraries::upgradeable::Upgradeable;
use chainlink::libraries::upgradeable::{Upgradeable, IUpgradeable};

const SHIFT: felt252 = 0x100000000000000000000000000000000;
const MAX_ID: felt252 = 0xffffffffffffffffffffffffffffffff;
Expand Down Expand Up @@ -172,12 +172,15 @@ mod AggregatorProxy {
// -- Upgradeable --

#[external(v0)]
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
let ownable = Ownable::unsafe_new_contract_state();
Ownable::assert_only_owner(@ownable);
Upgradeable::upgrade(new_impl)
impl UpgradeableImpl of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
let ownable = Ownable::unsafe_new_contract_state();
Ownable::assert_only_owner(@ownable);
Upgradeable::upgrade(new_impl)
}
}


// -- Access Control --

#[external(v0)]
Expand Down
4 changes: 3 additions & 1 deletion contracts/src/tests/test_access_controller.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use option::OptionTrait;
use core::result::ResultTrait;

use chainlink::access_control::access_controller::AccessController;
use chainlink::access_control::access_controller::AccessController::UpgradeableImpl;

use chainlink::libraries::access_control::{
IAccessController, IAccessControllerDispatcher, IAccessControllerDispatcherTrait
};
Expand All @@ -34,7 +36,7 @@ fn test_upgrade_not_owner() {
let sender = setup();
let mut state = STATE();

AccessController::upgrade(ref state, class_hash_const::<2>());
UpgradeableImpl::upgrade(ref state, class_hash_const::<2>());
}

#[test]
Expand Down
7 changes: 5 additions & 2 deletions contracts/src/tests/test_aggregator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use core::result::ResultTrait;

use chainlink::ocr2::aggregator::pow;
use chainlink::ocr2::aggregator::Aggregator;
use chainlink::ocr2::aggregator::Aggregator::{AggregatorImpl, BillingImpl, PayeeManagementImpl};
use chainlink::ocr2::aggregator::Aggregator::{
AggregatorImpl, BillingImpl, PayeeManagementImpl, UpgradeableImpl
};
use chainlink::ocr2::aggregator::Aggregator::BillingConfig;
use chainlink::ocr2::aggregator::Aggregator::PayeeConfig;
use chainlink::access_control::access_controller::AccessController;
Expand Down Expand Up @@ -155,7 +157,8 @@ fn test_access_control() {
fn test_upgrade_non_owner() {
let sender = setup();
let mut state = STATE();
Aggregator::upgrade(ref state, class_hash_const::<123>());

UpgradeableImpl::upgrade(ref state, class_hash_const::<123>());
}

// --- Billing tests ---
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/tests/test_aggregator_proxy.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use chainlink::ocr2::mocks::mock_aggregator::{
// use chainlink::ocr2::aggregator::{IAggregator, IAggregatorDispatcher, IAggregatorDispatcherTrait};
use chainlink::ocr2::aggregator_proxy::AggregatorProxy;
use chainlink::ocr2::aggregator_proxy::AggregatorProxy::{
AggregatorProxyImpl, AggregatorProxyInternal, AccessControllerImpl
AggregatorProxyImpl, AggregatorProxyInternal, AccessControllerImpl, UpgradeableImpl
};
use chainlink::ocr2::aggregator::Round;
use chainlink::utils::split_felt;
Expand Down Expand Up @@ -95,7 +95,7 @@ fn test_access_control() {
fn test_upgrade_non_owner() {
let (_, _, _, _, _) = setup();
let mut state = STATE();
AggregatorProxy::upgrade(ref state, class_hash_const::<123>());
UpgradeableImpl::upgrade(ref state, class_hash_const::<123>());
}

fn test_query_latest_round_data() {
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/tests/test_link_token.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use option::OptionTrait;
use core::result::ResultTrait;

use chainlink::token::link_token::LinkToken;
use chainlink::token::link_token::LinkToken::{MintableToken, ERC20Impl};
use chainlink::token::link_token::LinkToken::{MintableToken, ERC20Impl, UpgradeableImpl};
use chainlink::tests::test_ownable::should_implement_ownable;

// only tests link token specific functionality
Expand Down Expand Up @@ -152,6 +152,6 @@ fn test_upgrade_non_owner() {
let mut state = STATE();
LinkToken::constructor(ref state, sender, contract_address_const::<111>());

LinkToken::upgrade(ref state, class_hash_const::<123>());
UpgradeableImpl::upgrade(ref state, class_hash_const::<123>());
}

4 changes: 2 additions & 2 deletions contracts/src/tests/test_multisig.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use traits::TryInto;

use chainlink::multisig::assert_unique_values;
use chainlink::multisig::Multisig;
use chainlink::multisig::Multisig::MultisigImpl;
use chainlink::multisig::Multisig::{MultisigImpl, UpgradeableImpl};

#[starknet::contract]
mod MultisigTest {
Expand Down Expand Up @@ -288,7 +288,7 @@ fn test_upgrade_not_multisig() {
let account = contract_address_const::<777>();
set_caller_address(account);

MultisigImpl::upgrade(ref state, class_hash_const::<1>())
UpgradeableImpl::upgrade(ref state, class_hash_const::<1>())
}

#[test]
Expand Down
34 changes: 31 additions & 3 deletions contracts/src/tests/test_upgradeable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,55 @@ use starknet::testing::set_caller_address;
use starknet::ContractAddress;
use starknet::contract_address_const;
use starknet::class_hash::class_hash_const;
use starknet::syscalls::deploy_syscall;

use chainlink::libraries::upgradeable::Upgradeable;
use chainlink::libraries::ownable::Ownable;

use chainlink::libraries::mocks::mock_upgradeable::{
MockUpgradeable, IMockUpgradeableDispatcher, IMockUpgradeableDispatcherTrait,
IMockUpgradeableDispatcherImpl
};
use chainlink::libraries::mocks::mock_non_upgradeable::{
MockNonUpgradeable, IMockNonUpgradeableDispatcher, IMockNonUpgradeableDispatcherTrait,
IMockNonUpgradeableDispatcherImpl
};

fn setup() -> ContractAddress {
let account: ContractAddress = contract_address_const::<777>();
set_caller_address(account);
account
}

// replace_class_syscall() not yet supported in tests
#[test]
#[ignore]
#[available_gas(2000000)]
fn test_upgrade() {
let sender = setup();

// doesn't error
Upgradeable::upgrade(class_hash_const::<1>());
}

#[test]
#[available_gas(2000000)]
fn test_upgrade_and_call() {
let sender = setup();

let calldata = array![];
let (contractAddr, _) = deploy_syscall(
MockUpgradeable::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false
)
.unwrap();
let mockUpgradeable = IMockUpgradeableDispatcher { contract_address: contractAddr };
assert(mockUpgradeable.foo() == true, 'should call foo');

mockUpgradeable.upgrade(MockNonUpgradeable::TEST_CLASS_HASH.try_into().unwrap());

// now, contract should be different
let mockNonUpgradeable = IMockNonUpgradeableDispatcher { contract_address: contractAddr };
assert(mockNonUpgradeable.bar() == true, 'should call bar');
}


#[test]
#[available_gas(2000000)]
#[should_panic(expected: ('Class hash cannot be zero',))]
Expand Down
12 changes: 7 additions & 5 deletions contracts/src/token/link_token.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod LinkToken {
use openzeppelin::token::erc20::interface::{IERC20, IERC20Dispatcher, IERC20DispatcherTrait};
use chainlink::libraries::token::erc677::ERC677;
use chainlink::libraries::ownable::{Ownable, IOwnable};
use chainlink::libraries::upgradeable::Upgradeable;
use chainlink::libraries::upgradeable::{Upgradeable, IUpgradeable};

const NAME: felt252 = 'ChainLink Token';
const SYMBOL: felt252 = 'LINK';
Expand Down Expand Up @@ -86,10 +86,12 @@ mod LinkToken {
// Upgradeable
//
#[external(v0)]
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
let ownable = Ownable::unsafe_new_contract_state();
Ownable::assert_only_owner(@ownable);
Upgradeable::upgrade(new_impl)
impl UpgradeableImpl of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
let ownable = Ownable::unsafe_new_contract_state();
Ownable::assert_only_owner(@ownable);
Upgradeable::upgrade(new_impl)
}
}

//
Expand Down
Loading