Skip to content

Commit

Permalink
test: add expected invoke auth error for unit tests (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahramy authored Nov 4, 2024
1 parent 12cba3b commit 890bfcf
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 137 deletions.
209 changes: 90 additions & 119 deletions contracts/axelar-gateway/src/test_gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::testutils::{
randint,
};
use crate::{AxelarGateway, AxelarGatewayClient};
use axelar_soroban_std::{assert_contract_err, assert_invocation, assert_last_emitted_event};
use axelar_soroban_std::{
assert_contract_err, assert_invocation, assert_invoke_auth_err, assert_invoke_auth_ok,
assert_last_emitted_event,
};
use soroban_sdk::testutils::BytesN as _;

use crate::error::ContractError;
Expand Down Expand Up @@ -349,22 +352,10 @@ fn rotate_signers_bypass_rotation_delay() {
let bypass_rotation_delay = true;
let new_epoch: u64 = client.epoch() + 1;

client
.mock_auths(&[MockAuth {
address: &operator,
invoke: &MockAuthInvoke {
contract: &contract_id,
fn_name: "rotate_signers",
args: (
new_signers.signers.clone(),
proof.clone(),
bypass_rotation_delay,
)
.into_val(&env),
sub_invokes: &[],
},
}])
.rotate_signers(&new_signers.signers, &proof, &bypass_rotation_delay);
assert_invoke_auth_ok!(
operator,
client.try_rotate_signers(&new_signers.signers, &proof, &bypass_rotation_delay)
);

assert_last_emitted_event(
&env,
Expand All @@ -378,6 +369,28 @@ fn rotate_signers_bypass_rotation_delay() {
);
}

#[test]
fn rotate_signers_bypass_rotation_delay_unauthorized() {
let (env, _, client) = setup_env();
let owner = Address::generate(&env);
let operator = Address::generate(&env);
let not_operator = Address::generate(&env);
let signers = initialize(&env, &client, owner.clone(), operator.clone(), 1, 5);
let new_signers = generate_signers_set(&env, 5, signers.domain_separator.clone());
let data_hash = new_signers.signers.signers_rotation_hash(&env);
let proof = generate_proof(&env, data_hash.clone(), signers);
let bypass_rotation_delay = true;

assert_invoke_auth_err!(
owner,
client.try_rotate_signers(&new_signers.signers, &proof, &bypass_rotation_delay)
);
assert_invoke_auth_err!(
not_operator,
client.try_rotate_signers(&new_signers.signers, &proof, &bypass_rotation_delay)
);
}

#[test]
fn rotate_signers_fail_not_latest_signers() {
let (env, _contract_id, client) = setup_env();
Expand All @@ -401,59 +414,25 @@ fn rotate_signers_fail_not_latest_signers() {
);
}

#[test]
#[should_panic(expected = "HostError: Error(Auth, InvalidAction)")] // Unauthorized
fn rotate_signers_bypass_rotation_delay_fail_if_not_operator() {
let (env, contract_id, client) = setup_env();
let owner = Address::generate(&env);
let operator = Address::generate(&env);
let user = Address::generate(&env);
let signers = initialize(&env, &client, owner, operator.clone(), 1, 5);
let new_signers = generate_signers_set(&env, 5, signers.domain_separator.clone());
let data_hash = new_signers.signers.signers_rotation_hash(&env);
let proof = generate_proof(&env, data_hash.clone(), signers);
let bypass_rotation_delay = true;

client
.mock_auths(&[MockAuth {
address: &user,
invoke: &MockAuthInvoke {
contract: &contract_id,
fn_name: "rotate_signers",
args: (
new_signers.signers.clone(),
proof.clone(),
bypass_rotation_delay,
)
.into_val(&env),
sub_invokes: &[],
},
}])
.rotate_signers(&new_signers.signers, &proof, &bypass_rotation_delay);
}

#[test]
fn transfer_operatorship() {
let (env, contract_id, client) = setup_env();
let owner = Address::generate(&env);
let operator = Address::generate(&env);
let new_operator = Address::generate(&env);

initialize(&env, &client, owner, operator.clone(), 1, randint(1, 10));
initialize(
&env,
&client,
owner.clone(),
operator.clone(),
1,
randint(1, 10),
);

assert_eq!(client.operator(), operator);

client
.mock_auths(&[MockAuth {
address: &operator,
invoke: &MockAuthInvoke {
contract: &contract_id,
fn_name: "transfer_operatorship",
args: (&new_operator,).into_val(&env),
sub_invokes: &[],
},
}])
.transfer_operatorship(&new_operator);
assert_invoke_auth_ok!(operator, client.try_transfer_operatorship(&new_operator));

assert_last_emitted_event(
&env,
Expand All @@ -470,28 +449,28 @@ fn transfer_operatorship() {
}

#[test]
#[should_panic(expected = "HostError: Error(Auth, InvalidAction)")] // Unauthorized
fn transfer_operatorship_unauthorized() {
let (env, contract_id, client) = setup_env();
let (env, _, client) = setup_env();
let owner = Address::generate(&env);
let operator = Address::generate(&env);
let new_operator = Address::generate(&env);
let user = Address::generate(&env);
let not_operator = Address::generate(&env);

initialize(&env, &client, owner, operator.clone(), 1, randint(1, 10));
initialize(
&env,
&client,
owner.clone(),
operator.clone(),
1,
randint(1, 10),
);

assert_eq!(client.operator(), operator);
client
.mock_auths(&[MockAuth {
address: &user,
invoke: &MockAuthInvoke {
contract: &contract_id,
fn_name: "transfer_operatorship",
args: (&new_operator,).into_val(&env),
sub_invokes: &[],
},
}])
.transfer_operatorship(&new_operator);

assert_invoke_auth_err!(owner, client.try_transfer_operatorship(&owner));
assert_invoke_auth_err!(
not_operator,
client.try_transfer_operatorship(&not_operator)
);
}

#[test]
Expand All @@ -501,21 +480,18 @@ fn transfer_ownership() {
let operator = Address::generate(&env);
let new_owner = Address::generate(&env);

initialize(&env, &client, owner.clone(), operator, 1, randint(1, 10));
initialize(
&env,
&client,
owner.clone(),
operator.clone(),
1,
randint(1, 10),
);

assert_eq!(client.owner(), owner);

client
.mock_auths(&[MockAuth {
address: &owner,
invoke: &MockAuthInvoke {
contract: &contract_id,
fn_name: "transfer_ownership",
args: (&new_owner,).into_val(&env),
sub_invokes: &[],
},
}])
.transfer_ownership(&new_owner);
assert_invoke_auth_ok!(owner, client.try_transfer_ownership(&new_owner));

assert_last_emitted_event(
&env,
Expand All @@ -532,28 +508,25 @@ fn transfer_ownership() {
}

#[test]
#[should_panic(expected = "HostError: Error(Auth, InvalidAction)")] // Unauthorized
fn transfer_ownership_unauthorized() {
let (env, contract_id, client) = setup_env();
let (env, _, client) = setup_env();
let owner = Address::generate(&env);
let operator = Address::generate(&env);
let new_owner = Address::generate(&env);
let user = Address::generate(&env);
let operator = Address::generate(&env);

initialize(&env, &client, owner.clone(), operator, 1, randint(1, 10));
initialize(
&env,
&client,
owner.clone(),
operator.clone(),
1,
randint(1, 10),
);

assert_eq!(client.owner(), owner);
client
.mock_auths(&[MockAuth {
address: &user,
invoke: &MockAuthInvoke {
contract: &contract_id,
fn_name: "transfer_ownership",
args: (&new_owner,).into_val(&env),
sub_invokes: &[],
},
}])
.transfer_ownership(&new_owner);

assert_invoke_auth_err!(new_owner, client.try_transfer_ownership(&new_owner));
assert_invoke_auth_err!(operator, client.try_transfer_ownership(&operator));
}

#[test]
Expand Down Expand Up @@ -648,26 +621,24 @@ fn upgrade_invalid_wasm_hash() {
}

#[test]
#[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
fn upgrade_unauthorized() {
let (env, contract_id, client) = setup_env();
let (env, _, client) = setup_env();
let owner = Address::generate(&env);
let operator = Address::generate(&env);
let user = Address::generate(&env);
let not_owner = Address::generate(&env);
let new_wasm_hash = BytesN::<32>::from_array(&env, &[0; 32]);

initialize(&env, &client, owner.clone(), operator, 1, randint(1, 10));
initialize(
&env,
&client,
owner.clone(),
operator.clone(),
1,
randint(1, 10),
);

assert_eq!(client.owner(), owner);
client
.mock_auths(&[MockAuth {
address: &user,
invoke: &MockAuthInvoke {
contract: &contract_id,
fn_name: "upgrade",
args: (new_wasm_hash.clone(),).into_val(&env),
sub_invokes: &[],
},
}])
.upgrade(&new_wasm_hash);

assert_invoke_auth_err!(not_owner, client.try_upgrade(&new_wasm_hash));
assert_invoke_auth_err!(operator, client.try_upgrade(&new_wasm_hash));
}
27 changes: 9 additions & 18 deletions contracts/interchain-token-service/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ extern crate std;
use crate::error::ContractError;
use crate::{contract::InterchainTokenService, contract::InterchainTokenServiceClient};

use axelar_soroban_std::{assert_contract_err, assert_last_emitted_event};
use soroban_sdk::{
testutils::{Address as _, MockAuth, MockAuthInvoke},
Address, Env, IntoVal, String, Symbol,
};
use axelar_soroban_std::{assert_contract_err, assert_invoke_auth_err, assert_last_emitted_event};
use soroban_sdk::testutils::{MockAuth, MockAuthInvoke};

use soroban_sdk::{testutils::Address as _, Address, Env, String, Symbol};

fn setup_env<'a>() -> (Env, Address, InterchainTokenServiceClient<'a>) {
let env = Env::default();
Expand Down Expand Up @@ -75,9 +74,8 @@ fn set_trusted_address() {
}

#[test]
#[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
fn set_trusted_address_fails_if_not_owner() {
let (env, contract_id, client) = setup_env();
let (env, _, client) = setup_env();
let owner = Address::generate(&env);

initialize(&env, &client, owner);
Expand All @@ -86,17 +84,10 @@ fn set_trusted_address_fails_if_not_owner() {
let chain = String::from_str(&env, "chain");
let trusted_address = String::from_str(&env, "trusted_address");

client
.mock_auths(&[MockAuth {
address: &not_owner,
invoke: &MockAuthInvoke {
contract: &contract_id,
fn_name: "set_trusted_address",
args: (chain.clone(), trusted_address.clone()).into_val(&env),
sub_invokes: &[],
},
}])
.set_trusted_address(&chain, &trusted_address);
assert_invoke_auth_err!(
not_owner,
client.try_set_trusted_address(&chain, &trusted_address)
);
}

#[test]
Expand Down
52 changes: 52 additions & 0 deletions packages/axelar-soroban-std/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,55 @@ macro_rules! assert_some {
}
};
}

#[macro_export]
macro_rules! assert_invoke_auth_ok {
($caller:expr, $client:ident . $method:ident ( $($arg:expr),* $(,)? )) => {{
let call_result = $client
.mock_auths(&[MockAuth {
address: &$caller,
invoke: &MockAuthInvoke {
contract: &$client.address,
fn_name: &stringify!($method).replace("try_", ""),
args: ($($arg.clone(),)*).into_val(&$client.env),
sub_invokes: &[],
},
}])
.$method($($arg),*);

match call_result {
Ok(_) => {}
Err(_) => panic!("Expected Ok result, but got an error."),
}
}};
}

#[macro_export]
macro_rules! assert_invoke_auth_err {
($caller:expr, $client:ident . $method:ident ( $($arg:expr),* $(,)? )) => {{
use soroban_sdk::{IntoVal, xdr::{ScError, ScErrorCode, ScVal}};

let call_result = $client
.mock_auths(&[MockAuth {
address: &$caller,
invoke: &MockAuthInvoke {
contract: &$client.address,
fn_name: &stringify!($method).replace("try_", ""),
args: ($($arg.clone(),)*).into_val(&$client.env),
sub_invokes: &[],
},
}])
.$method($($arg),*);

match call_result {
Err(_) => {
let val = ScVal::Error(ScError::Context(ScErrorCode::InvalidAction));
match ScError::try_from(val) {
Ok(ScError::Context(ScErrorCode::InvalidAction)) => {}
_ => panic!("Expected ScErrorCode::InvalidAction"),
}
}
Ok(_) => panic!("Expected error, but got Ok result."),
}
}};
}

0 comments on commit 890bfcf

Please sign in to comment.