Skip to content

Commit

Permalink
refactor: update mock auth macro to support non root auth (#134)
Browse files Browse the repository at this point in the history
Co-authored-by: Milap Sheth <[email protected]>
  • Loading branch information
ahramy and milapsheth authored Jan 17, 2025
1 parent 5800cf7 commit 7b6a553
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use soroban_sdk::token::{self, StellarAssetClient};
use soroban_sdk::{Address, Bytes, IntoVal, String, Symbol};
use soroban_token_sdk::metadata::TokenMetadata;
use stellar_axelar_std::address::AddressExt;
use stellar_axelar_std::{auth_invocation, events};
use stellar_axelar_std::{auth_invocation, events, mock_auth};
use stellar_interchain_token_service::event::InterchainTokenDeploymentStartedEvent;
use stellar_interchain_token_service::types::{
DeployInterchainToken, HubMessage, Message, TokenManagerType,
Expand All @@ -14,7 +14,7 @@ use utils::{setup_env, setup_gas_token};

#[test]
fn deploy_remote_canonical_token_succeeds() {
let (env, client, _, gas_service, _) = setup_env();
let (env, client, gateway, gas_service, _) = setup_env();
let spender = Address::generate(&env);
let gas_token = setup_gas_token(&env, &spender);
let asset = &env.register_stellar_asset_contract_v2(Address::generate(&env));
Expand Down Expand Up @@ -63,8 +63,35 @@ fn deploy_remote_canonical_token_succeeds() {
}
.abi_encode(&env);

let transfer_token_auth = mock_auth!(
env,
spender,
gas_token.transfer(spender, gas_service.address, gas_token.amount)
);

let pay_gas_auth = mock_auth!(
env,
spender,
gas_service.pay_gas(
client.address,
its_hub_chain,
its_hub_address,
payload,
spender,
gas_token,
Bytes::new(&env)
),
&[(transfer_token_auth.invoke).clone()]
);

let call_contract_auth = mock_auth!(
env,
spender,
gateway.call_contract(client.address, its_hub_chain, its_hub_address, payload)
);

let deployed_token_id = client
.mock_all_auths_allowing_non_root_auth()
.mock_auths(&[pay_gas_auth, call_contract_auth])
.deploy_remote_canonical_token(&token_address, &destination_chain, &spender, &gas_token);
assert_eq!(expected_id, deployed_token_id);

Expand Down
86 changes: 21 additions & 65 deletions contracts/upgrader/tests/atomic_upgrades.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
mod utils;

use soroban_sdk::testutils::{Address as _, MockAuth, MockAuthInvoke};
use soroban_sdk::testutils::Address as _;
use soroban_sdk::{Address, BytesN, Env, String};
use stellar_axelar_std::mock_auth;
use stellar_upgrader::{Upgrader, UpgraderClient};
use utils::{DataKey, DummyContract, DummyContractClient};

Expand All @@ -23,22 +24,12 @@ fn upgrade_and_migrate_are_atomic() {
let original_version: String = dummy_client.version();
assert_eq!(original_version, String::from_str(&env, "0.1.0"));

let (upgrade_auth, migrate_auth) =
build_invocation_auths(&env, &contract_address, &hash_after_upgrade, &expected_data);

// add the owner to the set of authenticated addresses
env.mock_auths(&[
MockAuth {
address: &owner,
invoke: &upgrade_auth,
},
MockAuth {
address: &owner,
invoke: &migrate_auth,
},
]);
let upgrader = UpgraderClient::new(&env, &upgrader_address);

UpgraderClient::new(&env, &upgrader_address).upgrade(
let upgrade_auth = mock_auth!(env, owner, dummy_client.upgrade(hash_after_upgrade));
let migrate_auth = mock_auth!(env, owner, dummy_client.migrate(expected_data));

upgrader.mock_auths(&[upgrade_auth, migrate_auth]).upgrade(
&contract_address,
&expected_version,
&hash_after_upgrade,
Expand Down Expand Up @@ -69,24 +60,17 @@ fn upgrade_fails_if_caller_is_authenticated_but_not_owner() {
..
} = setup_contracts_and_call_args();

let (upgrade_auth, migrate_auth) =
build_invocation_auths(&env, &contract_address, &hash_after_upgrade, &expected_data);
let dummy_client = DummyContractClient::new(&env, &contract_address);
let upgrader = UpgraderClient::new(&env, &upgrader_address);

// add the caller to the set of authenticated addresses
let caller = Address::generate(&env);
env.mock_auths(&[
MockAuth {
address: &caller,
invoke: &upgrade_auth,
},
MockAuth {
address: &caller,
invoke: &migrate_auth,
},
]);

let upgrade_auth = mock_auth!(env, caller, dummy_client.upgrade(hash_after_upgrade));
let migrate_auth = mock_auth!(env, caller, dummy_client.migrate(expected_data));

// should panic: caller is authenticated, but not the owner
UpgraderClient::new(&env, &upgrader_address).upgrade(
upgrader.mock_auths(&[upgrade_auth, migrate_auth]).upgrade(
&contract_address,
&expected_version,
&hash_after_upgrade,
Expand All @@ -106,24 +90,17 @@ fn upgrade_fails_if_correct_owner_is_not_authenticated_for_full_invocation_tree(
expected_data,
expected_version,
} = setup_contracts_and_call_args();
let dummy_client = DummyContractClient::new(&env, &contract_address);
let upgrader = UpgraderClient::new(&env, &upgrader_address);

let (upgrade_auth, migrate_auth) =
build_invocation_auths(&env, &contract_address, &hash_after_upgrade, &expected_data);

// only add the owner to the set of authenticated addresses for the upgrade function, and the caller for the migrate function
// add the caller to the set of authenticated addresses
let caller = Address::generate(&env);
env.mock_auths(&[
MockAuth {
address: &owner,
invoke: &upgrade_auth,
},
MockAuth {
address: &caller,
invoke: &migrate_auth,
},
]);

UpgraderClient::new(&env, &upgrader_address).upgrade(
let upgrade_auth = mock_auth!(env, owner, dummy_client.upgrade(hash_after_upgrade));
let migrate_auth = mock_auth!(env, caller, dummy_client.migrate(expected_data));

// only add the owner to the set of authenticated addresses for the upgrade function, and the caller for the migrate function
upgrader.mock_auths(&[upgrade_auth, migrate_auth]).upgrade(
&contract_address,
&expected_version,
&hash_after_upgrade,
Expand Down Expand Up @@ -184,24 +161,3 @@ fn setup_contracts_and_call_args() -> TestFixture {
expected_version,
}
}

fn build_invocation_auths<'a>(
env: &Env,
contract_address: &'a Address,
hash_after_upgrade: &'a BytesN<32>,
expected_data: &'a String,
) -> (MockAuthInvoke<'a>, MockAuthInvoke<'a>) {
let upgrade = MockAuthInvoke {
contract: contract_address,
fn_name: "upgrade",
args: soroban_sdk::vec![&env, hash_after_upgrade.to_val()],
sub_invokes: &[],
};
let migrate = MockAuthInvoke {
contract: contract_address,
fn_name: "migrate",
args: soroban_sdk::vec![&env, expected_data.to_val()],
sub_invokes: &[],
};
(upgrade, migrate)
}
54 changes: 38 additions & 16 deletions packages/axelar-std/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,15 @@ macro_rules! assert_some {
#[macro_export]
macro_rules! assert_auth {
($caller:expr, $client:ident . $method:ident ( $($arg:expr),* $(,)? )) => {{
use soroban_sdk::IntoVal;

// Paste is used to concatenate the method name with the `try_` prefix
paste::paste! {
let call_result = $client
.mock_auths($crate::mock_auth!($caller, $client, $method, $($arg),*))
.mock_auths(&[$crate::mock_auth!(
$client.env,
$caller,
$client.$method($($arg),*),
&[]
)])
.[<try_ $method>]($($arg),*);
}

Expand All @@ -132,11 +135,16 @@ macro_rules! assert_auth {
#[macro_export]
macro_rules! assert_auth_err {
($caller:expr, $client:ident . $method:ident ( $($arg:expr),* $(,)? )) => {{
use soroban_sdk::{IntoVal, xdr::{ScError, ScErrorCode, ScVal}};
use soroban_sdk::xdr::{ScError, ScErrorCode, ScVal};

paste::paste! {
let call_result = $client
.mock_auths($crate::mock_auth!($caller, $client, $method, $($arg),*))
.mock_auths(&[$crate::mock_auth!(
$client.env,
$caller,
$client.$method($($arg),*),
&[]
)])
.[<try_ $method>]($($arg),*);
}
match call_result {
Expand All @@ -154,15 +162,29 @@ macro_rules! assert_auth_err {

#[macro_export]
macro_rules! mock_auth {
($caller:expr, $client:ident, $method:ident, $($arg:expr),*) => {
&[soroban_sdk::testutils::MockAuth {
address: &$caller,
invoke: &soroban_sdk::testutils::MockAuthInvoke {
contract: &$client.address,
fn_name: &stringify!($method),
args: ($($arg.clone(),)*).into_val(&$client.env),
sub_invokes: &[],
},
}]
};
(
$env:expr,
$caller:expr,
$client:ident . $method:ident ( $($arg:expr),* $(,)? ),
$sub_invokes:expr
) => {{
use soroban_sdk::IntoVal;

soroban_sdk::testutils::MockAuth {
address: &$caller,
invoke: &soroban_sdk::testutils::MockAuthInvoke {
contract: &$client.address,
fn_name: &stringify!($method).replace("try_", ""),
args: ($($arg.clone(),)*).into_val(&$env),
sub_invokes: $sub_invokes,
},
}
}};
(
$env:expr,
$caller:expr,
$client:ident . $method:ident ( $($arg:expr),* $(,)? )
) => {{
mock_auth!($env, $caller, $client.$method($($arg),*), &[])
}};
}

0 comments on commit 7b6a553

Please sign in to comment.