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 2027]: Adds multisig cairo tests #359

Merged
merged 2 commits into from
Feb 19, 2024
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
2 changes: 0 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,6 @@ test-integration-soak-ci:
test-integration-contracts: build-ts env-devnet-hardhat
echo "Tests currently broken because of starknet-hardhat-plugin"
exit 1
cd packages-ts/integration-multisig/ && \
yarn test
cd packages-ts/starknet/ && \
yarn test

Expand Down
296 changes: 293 additions & 3 deletions contracts/src/tests/test_multisig.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use chainlink::multisig::IMultisigDispatcherTrait;
use core::traits::Into;
use starknet::class_hash_const;
use starknet::contract_address_const;
use starknet::syscalls::deploy_syscall;
Expand All @@ -13,6 +15,7 @@ use traits::TryInto;
use chainlink::multisig::assert_unique_values;
use chainlink::multisig::Multisig;
use chainlink::multisig::Multisig::{MultisigImpl, UpgradeableImpl};
use chainlink::multisig::{IMultisigDispatcher};

#[starknet::contract]
mod MultisigTest {
Expand All @@ -27,9 +30,6 @@ mod MultisigTest {
}
}

// TODO: test set_threshold with recursive call
// TODO: test set_signers with recursive call
// TODO: test set_signers_and_thershold with recursive call

fn STATE() -> Multisig::ContractState {
Multisig::contract_state_for_testing()
Expand Down Expand Up @@ -434,3 +434,293 @@ fn test_execute_after_set_threshold() {
set_caller_address(signer1);
MultisigImpl::execute_transaction(ref state, nonce: 0);
}

// test set_threshold (non-recursive)
#[test]
fn test_set_threshold() {
let s1 = contract_address_const::<1>();
let s2 = contract_address_const::<2>();
let s3 = contract_address_const::<3>();
let signers = array![s1, s2, s3];
let init_threshold: usize = 3;
let new_threshold: usize = 2;

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 = IMultisigDispatcher { contract_address: multisig_address };
assert(multisig.get_threshold() == init_threshold, 'invalid init threshold');
set_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig.set_threshold(new_threshold);
assert(multisig.get_threshold() == new_threshold, 'threshold was not updated');
}

// test set_threshold with recursive call
#[test]
fn test_recursive_set_threshold() {
// Defines helper variables
let s1 = contract_address_const::<1>();
let s2 = contract_address_const::<2>();
let signers = array![s1, s2];
let init_threshold: usize = 2;
let new_threshold: usize = 1;

// Deploys the contract
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();

// 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.
let mut set_threshold_calldata = ArrayTrait::new();
Serde::serialize(@new_threshold, ref set_threshold_calldata);
set_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig
.submit_transaction(multisig_address, selector!("set_threshold"), set_threshold_calldata);

// Signer 1 confirms the transaction
set_caller_address(s1);
set_contract_address(s1);
multisig.confirm_transaction(0);

// Signer 2 confirms the transaction
set_caller_address(s2);
set_contract_address(s2);
multisig.confirm_transaction(0);

// Once we have enough confirmations, we execute the transaction
set_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig.execute_transaction(0);

// Now we check that the threshold was actually updated
assert(multisig.get_threshold() == new_threshold, 'threshold was not updated');
}

// test set_signers (non-recursive)
#[test]
fn test_set_signers() {
let s1 = contract_address_const::<1>();
let s2 = contract_address_const::<2>();
let init_signers = array![s1, s2];
let new_signers = array![s1];
let threshold: usize = 2;

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 = IMultisigDispatcher { contract_address: multisig_address };

let returned_signers = multisig.get_signers();
assert(returned_signers.len() == 2, 'should match signers length');
assert(*returned_signers.at(0) == s1, 'should match signer 1');
assert(*returned_signers.at(1) == s2, 'should match signer 2');
assert(multisig.get_threshold() == 2, 'wrong init threshold');

set_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig.set_signers(new_signers);

let updated_signers = multisig.get_signers();
assert(updated_signers.len() == 1, 'should match signers length');
assert(*updated_signers.at(0) == s1, 'should match signer 1');
assert(multisig.get_threshold() == 1, 'threshold not updated');
}

// test set_signers with recursive call
#[test]
fn test_recursive_set_signers() {
// Defines helper variables
let s1 = contract_address_const::<1>();
let s2 = contract_address_const::<2>();
let init_signers = array![s1, s2];
let new_signers = array![s1];
let init_threshold: usize = 2;

// Deploys the contract
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();

// Gets a dispatcher (so we can call methods on the deployed contract)
let multisig = IMultisigDispatcher { contract_address: multisig_address };

// Checks that the signers were correctly initialized on deployment
let returned_signers = multisig.get_signers();
assert(returned_signers.len() == 2, 'should match signers length');
assert(*returned_signers.at(0) == s1, 'should match signer 1');
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.
let mut set_signers_calldata = ArrayTrait::new();
Serde::serialize(@new_signers, ref set_signers_calldata);
set_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig.submit_transaction(multisig_address, selector!("set_signers"), set_signers_calldata);

// Signer 1 confirms the transaction
set_caller_address(s1);
set_contract_address(s1);
multisig.confirm_transaction(0);

// Signer 2 confirms the transaction
set_caller_address(s2);
set_contract_address(s2);
multisig.confirm_transaction(0);

// Once we have enough confirmations, we execute the transaction
set_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig.execute_transaction(0);

// Now we check that the signers were actually updated
let updated_signers = multisig.get_signers();
assert(updated_signers.len() == 1, 'should match signers length');
assert(*updated_signers.at(0) == s1, 'should match signer 1');
assert(multisig.get_threshold() == 1, 'wrong threshold');
}

// test set_signers_and_threshold (non-recursive)
#[test]
fn test_set_signers_and_threshold() {
let s1 = contract_address_const::<1>();
let s2 = contract_address_const::<2>();
let s3 = contract_address_const::<3>();
let init_signers = array![s1, s2, s3];
let new_signers = array![s1, s2];
let init_threshold: usize = 3;
let new_threshold: usize = 1;

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 = IMultisigDispatcher { contract_address: multisig_address };

let returned_signers = multisig.get_signers();
assert(returned_signers.len() == 3, 'should match signers length');
assert(*returned_signers.at(0) == s1, 'should match signer 1');
assert(*returned_signers.at(1) == s2, 'should match signer 2');
assert(*returned_signers.at(2) == s3, 'should match signer 3');
assert(multisig.get_threshold() == init_threshold, 'wrong init threshold');

set_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig.set_signers_and_threshold(new_signers, new_threshold);

let updated_signers = multisig.get_signers();
assert(updated_signers.len() == 2, 'should match signers length');
assert(*updated_signers.at(0) == s1, 'should match signer 1');
assert(*updated_signers.at(1) == s2, 'should match signer 2');
assert(multisig.get_threshold() == new_threshold, 'threshold not updated');
}

// test set_signers_and_threshold with recursive call
#[test]
fn test_recursive_set_signers_and_threshold() {
// Defines helper variables
let s1 = contract_address_const::<1>();
let s2 = contract_address_const::<2>();
let s3 = contract_address_const::<3>();
let init_signers = array![s1, s2, s3];
let new_signers = array![s1, s2];
let init_threshold: usize = 3;
let new_threshold: usize = 1;

// Deploys the contract
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();

// Gets a dispatcher (so we can call methods on the deployed contract)
let multisig = IMultisigDispatcher { contract_address: multisig_address };

// Checks that the initial state is correct
let returned_signers = multisig.get_signers();
assert(returned_signers.len() == 3, 'should match signers length');
assert(*returned_signers.at(0) == s1, 'should match signer 1');
assert(*returned_signers.at(1) == s2, 'should match signer 2');
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
// on the multisig contract.
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_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig
.submit_transaction(
multisig_address,
selector!("set_signers_and_threshold"),
set_signers_and_threshold_calldata
);

// Signer 1 confirms the transaction
set_caller_address(s1);
set_contract_address(s1);
multisig.confirm_transaction(0);

// Signer 2 confirms the transaction
set_caller_address(s2);
set_contract_address(s2);
multisig.confirm_transaction(0);

// Signer 3 confirms the transaction
set_caller_address(s3);
set_contract_address(s3);
multisig.confirm_transaction(0);

// Once we have enough confirmations, we execute the transaction
set_caller_address(multisig_address);
set_contract_address(multisig_address);
multisig.execute_transaction(0);

// Now we check that the signers were actually updated
let updated_signers = multisig.get_signers();
assert(updated_signers.len() == 2, 'should match signers length');
assert(*updated_signers.at(0) == s1, 'should match signer 1');
assert(*updated_signers.at(1) == s2, 'should match signer 2');
assert(multisig.get_threshold() == 1, 'wrong threshold');
}

41 changes: 0 additions & 41 deletions packages-ts/integration-multisig/hardhat.config.ts

This file was deleted.

24 changes: 0 additions & 24 deletions packages-ts/integration-multisig/package.json

This file was deleted.

Loading
Loading