Skip to content

Commit 10bed31

Browse files
committed
fix(minor-interchain-token-service): skip invariant checks for p2p
* ITS tokens deployed between core chains are deployed in p2p mode, and the hub has no awareness of their deployment. Therefore, we don't track balances for the tokens when the source or destination chain is a core chain, and we don't check whether the token is deployed.
1 parent 421b1ea commit 10bed31

File tree

4 files changed

+107
-10
lines changed

4 files changed

+107
-10
lines changed

contracts/interchain-token-service/src/contract/execute/mod.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use axelar_core_std::nexus;
12
use axelar_wasm_std::{killswitch, nonempty, FnExt, IntoContractError};
23
use cosmwasm_std::{DepsMut, HexBinary, QuerierWrapper, Response, Storage};
34
use error_stack::{bail, ensure, report, Result, ResultExt};
@@ -72,6 +73,8 @@ pub enum Error {
7273
token_id: TokenId,
7374
chain: ChainNameRaw,
7475
},
76+
#[error("error querying nexus module for chain registration for chain {0}")]
77+
Nexus(ChainNameRaw),
7578
}
7679

7780
/// Executes an incoming ITS message.
@@ -111,6 +114,7 @@ fn execute_message_on_hub(
111114

112115
let message = apply_to_hub(
113116
deps.storage,
117+
deps.querier,
114118
cc_id.source_chain.clone(),
115119
destination_chain.clone(),
116120
message,
@@ -141,6 +145,7 @@ fn execute_message_on_hub(
141145

142146
fn apply_to_hub(
143147
storage: &mut dyn Storage,
148+
querier: QuerierWrapper,
144149
source_chain: ChainNameRaw,
145150
destination_chain: ChainNameRaw,
146151
message: Message,
@@ -150,7 +155,7 @@ fn apply_to_hub(
150155

151156
match message {
152157
Message::InterchainTransfer(transfer) => {
153-
apply_to_transfer(storage, source_chain, destination_chain, transfer)
158+
apply_to_transfer(storage, querier, source_chain, destination_chain, transfer)
154159
.map(Message::InterchainTransfer)?
155160
}
156161
Message::DeployInterchainToken(deploy_token) => {
@@ -163,18 +168,39 @@ fn apply_to_hub(
163168

164169
fn apply_to_transfer(
165170
storage: &mut dyn Storage,
171+
querier: QuerierWrapper,
166172
source_chain: ChainNameRaw,
167173
destination_chain: ChainNameRaw,
168174
transfer: InterchainTransfer,
169175
) -> Result<InterchainTransfer, Error> {
170-
interceptors::subtract_supply_amount(storage, &source_chain, &transfer)?;
171-
let transfer = interceptors::apply_scaling_factor_to_amount(
172-
storage,
173-
&source_chain,
174-
&destination_chain,
175-
transfer,
176-
)?;
177-
interceptors::add_supply_amount(storage, &destination_chain, &transfer)?;
176+
// we only do balance tracking for amplifier chains
177+
let client: nexus::Client = client::CosmosClient::new(querier).into();
178+
let source_is_amplifier_chain = !client
179+
.is_chain_registered(&source_chain.normalize())
180+
.change_context(Error::Nexus(source_chain.clone()))?;
181+
let destination_is_amplifier_chain = !client
182+
.is_chain_registered(&destination_chain.normalize())
183+
.change_context(Error::Nexus(destination_chain.clone()))?;
184+
185+
if source_is_amplifier_chain {
186+
interceptors::subtract_supply_amount(storage, &source_chain, &transfer)?;
187+
}
188+
189+
// we only possibly scale if both source chain and destination chain are amplifier chains
190+
let transfer = if source_is_amplifier_chain && destination_is_amplifier_chain {
191+
interceptors::apply_scaling_factor_to_amount(
192+
storage,
193+
&source_chain,
194+
&destination_chain,
195+
transfer,
196+
)?
197+
} else {
198+
transfer
199+
};
200+
201+
if destination_is_amplifier_chain {
202+
interceptors::add_supply_amount(storage, &destination_chain, &transfer)?;
203+
}
178204

179205
Ok(transfer)
180206
}

contracts/interchain-token-service/tests/execute.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use interchain_token_service::{
1414
};
1515
use router_api::{Address, ChainName, ChainNameRaw, CrossChainId};
1616
use serde_json::json;
17+
use utils::params::{CORE_CHAIN, CORE_ITS_CONTRACT};
1718
use utils::{params, register_chains, TestMessage};
1819

1920
mod utils;
@@ -950,6 +951,64 @@ fn deploy_interchain_token_tracks_supply() {
950951
);
951952
}
952953

954+
#[test]
955+
fn transfer_interchain_token_from_core_does_not_check_balance_or_deployment() {
956+
let (
957+
mut deps,
958+
TestMessage {
959+
router_message,
960+
source_its_chain: _,
961+
source_its_contract,
962+
destination_its_chain,
963+
destination_its_contract: _,
964+
hub_message,
965+
},
966+
) = utils::setup();
967+
968+
let token_id = hub_message.token_id();
969+
let amount = nonempty::Uint256::try_from(400u64).unwrap();
970+
971+
// this deploys the token from source_its_chain to destination_its_chain
972+
assert_ok!(utils::execute_hub_message(
973+
deps.as_mut(),
974+
router_message.cc_id.clone(),
975+
source_its_contract.clone(),
976+
hub_message,
977+
));
978+
979+
let msg = HubMessage::SendToHub {
980+
destination_chain: destination_its_chain.clone(),
981+
message: InterchainTransfer {
982+
token_id,
983+
source_address: HexBinary::from([1; 32]).try_into().unwrap(),
984+
destination_address: HexBinary::from([2; 32]).try_into().unwrap(),
985+
amount,
986+
data: None,
987+
}
988+
.into(),
989+
};
990+
assert_ok!(utils::execute_hub_message(
991+
deps.as_mut(),
992+
CrossChainId {
993+
source_chain: CORE_CHAIN.parse().unwrap(),
994+
message_id: router_message.cc_id.message_id.clone()
995+
},
996+
CORE_ITS_CONTRACT.parse().unwrap(),
997+
msg,
998+
));
999+
1000+
assert_eq!(
1001+
assert_ok!(utils::query_token_instance(
1002+
deps.as_ref(),
1003+
destination_its_chain.clone(),
1004+
token_id
1005+
))
1006+
.unwrap()
1007+
.supply,
1008+
TokenSupply::Tracked(amount.into())
1009+
);
1010+
}
1011+
9531012
#[test]
9541013
fn deploy_interchain_token_with_minter_does_not_track_supply() {
9551014
let (

contracts/interchain-token-service/tests/utils/execute.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use interchain_token_service::msg::{self, ExecuteMsg, TruncationConfig};
1414
use interchain_token_service::{contract, HubMessage};
1515
use router_api::{Address, ChainName, ChainNameRaw, CrossChainId};
1616

17+
use super::params::{CORE_CHAIN, CORE_ITS_CONTRACT};
1718
use super::{instantiate_contract, TestMessage};
1819
use crate::utils::params;
1920

@@ -70,7 +71,7 @@ pub fn make_deps() -> OwnedDeps<MemoryStorage, MockApi, MockQuerier<AxelarQueryM
7071
AxelarQueryMsg::Nexus(nexus::query::QueryMsg::IsChainRegistered { chain }) => {
7172
Ok(to_json_binary(
7273
&(IsChainRegisteredResponse {
73-
is_registered: chain == "ethereum",
74+
is_registered: chain == CORE_CHAIN,
7475
}),
7576
)
7677
.into())
@@ -204,5 +205,14 @@ pub fn setup() -> (
204205
)
205206
.unwrap();
206207

208+
register_chain(
209+
deps.as_mut(),
210+
CORE_CHAIN.parse().unwrap(),
211+
CORE_ITS_CONTRACT.parse().unwrap(),
212+
Uint256::MAX.try_into().unwrap(),
213+
u8::MAX,
214+
)
215+
.unwrap();
216+
207217
(deps, TestMessage::dummy())
208218
}

contracts/interchain-token-service/tests/utils/params.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ pub const ROUTER: &str = "router";
33
pub const GATEWAY: &str = "gateway";
44
pub const GOVERNANCE: &str = "governance";
55
pub const ADMIN: &str = "admin";
6+
pub const CORE_CHAIN: &str = "core-ethereum";
7+
pub const CORE_ITS_CONTRACT: &str = "core-its-contract";

0 commit comments

Comments
 (0)