Skip to content

Commit

Permalink
Neutron IBC Transfer service
Browse files Browse the repository at this point in the history
  • Loading branch information
stiiifff committed Oct 16, 2024
1 parent a77bf39 commit 6a879a0
Show file tree
Hide file tree
Showing 16 changed files with 626 additions and 372 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions contracts/services/forwarder/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::msg::{ActionsMsgs, Config, ForwardingConstraints, QueryMsg, ServiceConfig};
use cosmwasm_std::{coin, Addr, Coin, Uint128};
use cosmwasm_std::{coin, Addr, Coin, Empty, Uint128};
use cw20::Cw20Coin;
use cw_multi_test::{error::AnyResult, App, AppResponse, ContractWrapper, Executor};
use cw_ownable::Ownership;
Expand Down Expand Up @@ -115,7 +115,7 @@ impl ForwarderTestSuite {
}
}

impl ServiceTestSuite for ForwarderTestSuite {
impl ServiceTestSuite<Empty, Empty> for ForwarderTestSuite {
fn app(&self) -> &App {
self.inner.app()
}
Expand Down
37 changes: 34 additions & 3 deletions contracts/services/generic-ibc-transfer/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, Deps, DepsMut, Uint128, Uint64};
use cosmwasm_std::{Addr, CustomQuery, Deps, DepsMut, Uint128, Uint64};
use cw_ownable::cw_ownable_query;
use getset::{Getters, Setters};
use valence_macros::OptionalStruct;
Expand Down Expand Up @@ -48,9 +48,24 @@ pub enum IbcTransferAmount {
#[cw_serde]
pub struct RemoteChainInfo {
pub channel_id: String,
pub port_id: Option<String>,
pub ibc_transfer_timeout: Option<Uint64>,
}

impl RemoteChainInfo {
pub fn new(
channel_id: String,
port_id: Option<String>,
ibc_transfer_timeout: Option<Uint64>,
) -> Self {
Self {
channel_id,
port_id,
ibc_transfer_timeout,
}
}
}

impl ServiceConfig {
pub fn new(
input_addr: ServiceAccountType,
Expand Down Expand Up @@ -91,6 +106,15 @@ impl ServiceConfig {
));
}

if let Some(port_id) = &self.remote_chain_info.port_id {
if port_id.is_empty() {
return Err(ServiceError::ConfigurationError(
"Invalid IBC transfer config: remote_chain_info's port_id cannot be empty (if specified)."
.to_string(),
));
}
}

if let Some(timeout) = self.remote_chain_info.ibc_transfer_timeout {
if timeout.is_zero() {
return Err(ServiceError::ConfigurationError(
Expand Down Expand Up @@ -136,7 +160,14 @@ impl ServiceConfigInterface<ServiceConfig> for ServiceConfig {
}

impl OptionalServiceConfig {
pub fn update_config(self, deps: &DepsMut, config: &mut Config) -> Result<(), ServiceError> {
pub fn update_config<T>(
self,
deps: &DepsMut<T>,
config: &mut Config,
) -> Result<(), ServiceError>
where
T: CustomQuery,
{
if let Some(input_addr) = self.input_addr {
config.input_addr = input_addr.to_addr(deps.api)?;
}
Expand All @@ -148,7 +179,7 @@ impl OptionalServiceConfig {
if let Some(denom) = self.denom {
config.denom = denom
.clone()
.into_checked(deps.as_ref())
.into_checked(deps.as_ref().into_empty())
.map_err(|err| ServiceError::ConfigurationError(err.to_string()))?;
}

Expand Down
126 changes: 62 additions & 64 deletions contracts/services/generic-ibc-transfer/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::msg::{ActionMsgs, Config, IbcTransferAmount, QueryMsg, RemoteChainInfo, ServiceConfig};
use cosmwasm_std::{coin, Addr, Uint128, Uint64};
use cosmwasm_std::{coin, Addr, Empty, Uint128, Uint64};
use cw_multi_test::{error::AnyResult, App, AppResponse, ContractWrapper, Executor};
use cw_ownable::Ownership;
use getset::{Getters, Setters};
Expand All @@ -18,7 +18,7 @@ struct IbcTransferTestSuite {
#[getset(get)]
inner: ServiceTestSuiteBase,
#[getset(get)]
gen_ibc_transfer_code_id: u64,
ibc_transfer_code_id: u64,
#[getset(get)]
input_addr: Addr,
#[getset(get)]
Expand All @@ -42,32 +42,32 @@ impl IbcTransferTestSuite {
let output_addr = inner.api().addr_make("output_account");

// Template contract
let gen_ibc_transfer_code = ContractWrapper::new(
let ibc_transfer_code = ContractWrapper::new(
crate::contract::execute,
crate::contract::instantiate,
crate::contract::query,
);

let gen_ibc_transfer_code_id = inner.app_mut().store_code(Box::new(gen_ibc_transfer_code));
let ibc_transfer_code_id = inner.app_mut().store_code(Box::new(ibc_transfer_code));

Self {
inner,
gen_ibc_transfer_code_id,
ibc_transfer_code_id,
input_addr,
output_addr,
input_balance,
}
}

pub fn gen_ibc_transfer_init(&mut self, cfg: &ServiceConfig) -> Addr {
pub fn ibc_transfer_init(&mut self, cfg: &ServiceConfig) -> Addr {
let init_msg = InstantiateMsg {
owner: self.owner().to_string(),
processor: self.processor().to_string(),
config: cfg.clone(),
};
let addr = self.contract_init(
self.gen_ibc_transfer_code_id,
"generic_ibc_transfer_svc",
self.ibc_transfer_code_id,
"ibc_transfer_service",
&init_msg,
&[],
);
Expand All @@ -85,7 +85,7 @@ impl IbcTransferTestSuite {
addr
}

fn gen_ibc_transfer_config(
fn ibc_transfer_config(
&self,
denom: String,
amount: IbcTransferAmount,
Expand Down Expand Up @@ -122,7 +122,7 @@ impl IbcTransferTestSuite {
}
}

impl ServiceTestSuite for IbcTransferTestSuite {
impl ServiceTestSuite<Empty, Empty> for IbcTransferTestSuite {
fn app(&self) -> &App {
self.inner.app()
}
Expand All @@ -148,22 +148,22 @@ impl ServiceTestSuite for IbcTransferTestSuite {
}
}

// Note: all tests below are replicated to the Neutron IBC transfer service
// Any change in the tests below should be reflected in the Neutron IBC transfer service.

#[test]
fn instantiate_with_valid_config() {
let mut suite = IbcTransferTestSuite::default();

let cfg = suite.gen_ibc_transfer_config(
let cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FullAmount,
"".to_string(),
RemoteChainInfo {
channel_id: "channel-1".to_string(),
ibc_transfer_timeout: Some(600u64.into()),
},
RemoteChainInfo::new("channel-1".to_string(), None, Some(600u64.into())),
);

// Instantiate IBC transfer contract
let svc = suite.gen_ibc_transfer_init(&cfg);
let svc = suite.ibc_transfer_init(&cfg);

// Verify owner
let owner_res: Ownership<Addr> = suite.query_wasm(&svc, &QueryMsg::Ownership {});
Expand Down Expand Up @@ -192,14 +192,11 @@ fn instantiate_with_valid_config() {
fn pre_validate_config_works() {
let suite = IbcTransferTestSuite::default();

let cfg = suite.gen_ibc_transfer_config(
let cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FullAmount,
"".to_string(),
RemoteChainInfo {
channel_id: "channel-1".to_string(),
ibc_transfer_timeout: Some(600u64.into()),
},
RemoteChainInfo::new("channel-1".to_string(), None, Some(600u64.into())),
);

// Pre-validate config
Expand All @@ -211,18 +208,15 @@ fn pre_validate_config_works() {
fn instantiate_fails_for_zero_amount() {
let mut suite = IbcTransferTestSuite::default();

let cfg = suite.gen_ibc_transfer_config(
let cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FixedAmount(Uint128::zero()),
"".to_string(),
RemoteChainInfo {
channel_id: "channel-1".to_string(),
ibc_transfer_timeout: Some(600u64.into()),
},
RemoteChainInfo::new("channel-1".to_string(), None, Some(600u64.into())),
);

// Instantiate Generic IBC transfer contract
suite.gen_ibc_transfer_init(&cfg);
// Instantiate IBC transfer contract
suite.ibc_transfer_init(&cfg);
}

#[test]
Expand All @@ -232,18 +226,37 @@ fn instantiate_fails_for_zero_amount() {
fn instantiate_fails_for_invalid_channel_id() {
let mut suite = IbcTransferTestSuite::default();

let cfg = suite.gen_ibc_transfer_config(
let cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FixedAmount(Uint128::one()),
"".to_string(),
RemoteChainInfo::new("".to_string(), None, Some(600u64.into())),
);

// Instantiate IBC transfer contract
suite.ibc_transfer_init(&cfg);
}

#[test]
#[should_panic(
expected = "Invalid IBC transfer config: remote_chain_info's port_id cannot be empty (if specified)."
)]
fn instantiate_fails_for_invalid_port_id() {
let mut suite = IbcTransferTestSuite::default();

let cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FixedAmount(Uint128::one()),
"".to_string(),
RemoteChainInfo {
channel_id: "".to_string(),
ibc_transfer_timeout: Some(600u64.into()),
},
RemoteChainInfo::new(
"channel-1".to_string(),
Some("".to_string()),
Some(600u64.into()),
),
);

// Instantiate Generic IBC transfer contract
suite.gen_ibc_transfer_init(&cfg);
// Instantiate IBC transfer contract
suite.ibc_transfer_init(&cfg);
}

#[test]
Expand All @@ -253,18 +266,15 @@ fn instantiate_fails_for_invalid_channel_id() {
fn instantiate_fails_for_invalid_ibc_transfer_timeout() {
let mut suite = IbcTransferTestSuite::default();

let cfg = suite.gen_ibc_transfer_config(
let cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FixedAmount(Uint128::one()),
"".to_string(),
RemoteChainInfo {
channel_id: "channel-1".to_string(),
ibc_transfer_timeout: Some(Uint64::zero()),
},
RemoteChainInfo::new("channel-1".to_string(), None, Some(Uint64::zero())),
);

// Instantiate Generic IBC transfer contract
suite.gen_ibc_transfer_init(&cfg);
// Instantiate IBC transfer contract
suite.ibc_transfer_init(&cfg);
}

// Config update tests
Expand All @@ -274,18 +284,15 @@ fn instantiate_fails_for_invalid_ibc_transfer_timeout() {
fn update_config_validates_config() {
let mut suite = IbcTransferTestSuite::default();

let mut cfg = suite.gen_ibc_transfer_config(
let mut cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FullAmount,
"".to_string(),
RemoteChainInfo {
channel_id: "channel-1".to_string(),
ibc_transfer_timeout: Some(600u64.into()),
},
RemoteChainInfo::new("channel-1".to_string(), None, Some(600u64.into())),
);

// Instantiate IBC transfer contract
let svc = suite.gen_ibc_transfer_init(&cfg);
let svc = suite.ibc_transfer_init(&cfg);

// Update config and set amount to zero
cfg.amount = IbcTransferAmount::FixedAmount(Uint128::zero());
Expand All @@ -298,18 +305,15 @@ fn update_config_validates_config() {
fn update_config_with_valid_config() {
let mut suite = IbcTransferTestSuite::default();

let mut cfg = suite.gen_ibc_transfer_config(
let mut cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FullAmount,
"".to_string(),
RemoteChainInfo {
channel_id: "channel-1".to_string(),
ibc_transfer_timeout: Some(600u64.into()),
},
RemoteChainInfo::new("channel-1".to_string(), None, Some(600u64.into())),
);

// Instantiate IBC transfer contract
let svc = suite.gen_ibc_transfer_init(&cfg);
let svc = suite.ibc_transfer_init(&cfg);

// Update config: swap input and output addresses
cfg.input_addr = ServiceAccountType::Addr(suite.output_addr().to_string());
Expand All @@ -330,10 +334,7 @@ fn update_config_with_valid_config() {
CheckedDenom::Native(NTRN.into()),
IbcTransferAmount::FixedAmount(ONE_MILLION.into()),
"Chancellor on brink of second bailout for banks.".to_string(),
RemoteChainInfo {
channel_id: "channel-1".to_string(),
ibc_transfer_timeout: Some(600u64.into())
}
RemoteChainInfo::new("channel-1".to_string(), None, Some(600u64.into()))
)
);
}
Expand All @@ -347,18 +348,15 @@ fn update_config_with_valid_config() {
fn ibc_transfer_fails_for_insufficient_balance() {
let mut suite = IbcTransferTestSuite::default();

let cfg = suite.gen_ibc_transfer_config(
let cfg = suite.ibc_transfer_config(
NTRN.to_string(),
IbcTransferAmount::FixedAmount(ONE_MILLION.into()),
"".to_string(),
RemoteChainInfo {
channel_id: "channel-1".to_string(),
ibc_transfer_timeout: Some(600u64.into()),
},
RemoteChainInfo::new("channel-1".to_string(), None, Some(600u64.into())),
);

// Instantiate contract
let svc = suite.gen_ibc_transfer_init(&cfg);
let svc = suite.ibc_transfer_init(&cfg);

// Execute IBC transfer
suite.execute_ibc_transfer(svc).unwrap();
Expand Down
Loading

0 comments on commit 6a879a0

Please sign in to comment.