Skip to content

Commit

Permalink
feat: add setup method during contract instantiate
Browse files Browse the repository at this point in the history
Signed-off-by: Night Owl <[email protected]>
  • Loading branch information
nightowl121 committed Sep 8, 2023
1 parent 137e360 commit 2320ccc
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 87 deletions.
148 changes: 76 additions & 72 deletions contracts/core-contracts/cw-asset-manager/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
use cosmwasm_std::entry_point;
use std::str::FromStr;

use cosmwasm_std::{ensure_eq, entry_point};
use cosmwasm_std::{
to_binary, Addr, Binary, Deps, DepsMut, Env, Event, MessageInfo, QueryRequest, Reply, Response,
StdError, StdResult, SubMsg, SubMsgResult, Uint128, WasmMsg, WasmQuery,
};
use std::str::FromStr;
// use cw2::set_contract_version;
use cw2::set_contract_version;
use cw20::{AllowanceResponse, Cw20ExecuteMsg, Cw20QueryMsg};

use cw_common::asset_manager_msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
use cw_common::network_address::IconAddressValidation;
use cw_common::network_address::NetworkAddress;
use cw_common::x_call_msg::XCallMsg;
use cw_common::x_call_msg::{GetNetworkAddress, XCallMsg};
use cw_common::xcall_data_types::Deposit;

use crate::constants::SUCCESS_REPLY_MSG;
use crate::contract::exec::setup;
use crate::error::ContractError;
use crate::helpers::{decode_encoded_bytes, validate_archway_address, DecodedStruct};
use crate::state::*;

// // version info for migration info
// const CONTRACT_NAME: &str = "crates.io:cw-asset-manager";
// const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
// version info for migration info
const CONTRACT_NAME: &str = "crates.io:cw-asset-manager";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
_env: Env,
info: MessageInfo,
_msg: InstantiateMsg,
) -> StdResult<Response> {
// set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

msg: InstantiateMsg,
) -> Result<Response, ContractError> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)
.map_err(ContractError::Std)?;
OWNER.save(deps.storage, &info.sender)?;
Ok(Response::new().add_attribute("action", "instantiated"))

setup(deps, msg.source_xcall, msg.destination_asset_manager)
}

#[cfg_attr(not(feature = "library"), entry_point)]
Expand All @@ -45,7 +49,11 @@ pub fn execute(
ExecuteMsg::ConfigureXcall {
source_xcall,
destination_asset_manager,
} => exec::configure_network(deps, info, source_xcall, destination_asset_manager),
} => {
let owner = OWNER.load(deps.storage).map_err(ContractError::Std)?;
ensure_eq!(owner, info.sender, ContractError::OnlyOwner);
setup(deps, source_xcall, destination_asset_manager)
}
ExecuteMsg::HandleCallMessage { from, data } => {
exec::handle_xcall_msg(deps, env, info, from, data)
}
Expand All @@ -71,8 +79,8 @@ pub fn execute(
//you can optimize this
let recipient: NetworkAddress = match to {
Some(to_address) => {
let nw_addr = NetworkAddress::from_str(&*to_address).unwrap();
if !nw_addr.validate() {
let nw_addr = NetworkAddress::from_str(&to_address).unwrap();
if !nw_addr.validate_foreign_addresses() {
return Err(ContractError::InvalidRecipientAddress);
}
nw_addr
Expand Down Expand Up @@ -102,61 +110,57 @@ pub fn execute(
}

mod exec {
use cw_xcall_multi::msg::QueryMsg::GetNetworkAddress;
use rlp::Encodable;
use std::str::FromStr;

use rlp::Encodable;

use cw_common::xcall_data_types::DepositRevert;

use super::*;

pub fn configure_network(
pub fn setup(
deps: DepsMut,
info: MessageInfo,
source_xcall: String,
destination_asset_manager: String,
) -> Result<Response, ContractError> {
let owner = OWNER.load(deps.storage)?;
if info.sender != owner {
return Err(ContractError::OnlyOwner);
}

let x_addr = deps.api.addr_validate(source_xcall.as_ref())?;
// validate source xcall
let x_call_addr = deps
.api
.addr_validate(&source_xcall)
.map_err(ContractError::Std)?;

// query network address of xcall
let query_msg = GetNetworkAddress {};

let query = QueryRequest::Wasm(WasmQuery::Smart {
contract_addr: x_addr.to_string(),
msg: to_binary(&query_msg)?,
contract_addr: x_call_addr.to_string(),
msg: to_binary(&query_msg).map_err(ContractError::Std)?,
});

let x_network_address: NetworkAddress = deps.querier.query(&query)?;
let xcall_network_address: NetworkAddress = deps.querier.query(&query)?;

if x_network_address.ok() {
if !xcall_network_address.to_string().is_empty() {
return Err(ContractError::XAddressNotFound);
}

let (nid, _) = x_network_address.get_parts();
// Obtain native network id
let nid = xcall_network_address.nid();

let dest_nw_addr = NetworkAddress::from_str(&*destination_asset_manager).unwrap();

if !dest_nw_addr.validate() {
return Err(ContractError::InvalidNetworkAddressFormat {});
// validate icon asset manager
let icon_asset_manager =
NetworkAddress::from_str(&destination_asset_manager).map_err(ContractError::Std)?;
if !icon_asset_manager.validate_foreign_addresses() {
return Err(ContractError::InvalidNetworkAddressFormat);
}

//save in case required
let (dest_id, _dest_address) = dest_nw_addr.get_parts();

//update state
X_NETWORK_ADDRESS.save(deps.storage, &x_network_address)?;
SOURCE_XCALL
.save(deps.storage, &x_call_addr)
.map_err(ContractError::Std)?;
X_CALL_NETWORK_ADDRESS.save(deps.storage, &xcall_network_address)?;
NID.save(deps.storage, &nid)?;
//TODO: Rename to ICON asset manager
ICON_ASSET_MANAGER.save(deps.storage, &dest_nw_addr)?;
SOURCE_XCALL.save(deps.storage, &source_xcall)?;
ICON_ASSET_MANAGER.save(deps.storage, &dest_nw_addr)?;
ICON_NET_ID.save(deps.storage, &dest_id)?;
ICON_ASSET_MANAGER.save(deps.storage, &icon_asset_manager.account())?;
ICON_NET_ID.save(deps.storage, &icon_asset_manager.nid())?;

//TODO: save the details
Ok(Response::default())
}

Expand Down Expand Up @@ -236,7 +240,7 @@ mod exec {
};

let xcall_msg = WasmMsg::Execute {
contract_addr: source_xcall,
contract_addr: source_xcall.to_string(),
msg: to_binary(&xcall_message)?,
funds: info.funds,
};
Expand Down Expand Up @@ -274,8 +278,8 @@ mod exec {
data: Vec<u8>,
) -> Result<Response, ContractError> {
let xcall = SOURCE_XCALL.load(deps.storage)?;
let x_call_addr = deps.api.addr_validate(&xcall)?;
let x_network = X_NETWORK_ADDRESS.load(deps.storage)?;
let x_call_addr = deps.api.addr_validate(xcall.as_ref())?;
let x_network = X_CALL_NETWORK_ADDRESS.load(deps.storage)?;

if info.sender != x_call_addr {
return Err(ContractError::OnlyXcallService);
Expand All @@ -300,7 +304,7 @@ mod exec {
DecodedStruct::WithdrawTo(data_struct) => {
//TODO: Check if _from is ICON Asset manager contract
let icon_am = ICON_ASSET_MANAGER.load(deps.storage)?;
if from != icon_am.to_string() {
if from != icon_am {
return Err(ContractError::OnlyIconAssetManager {});
}

Expand Down Expand Up @@ -351,9 +355,10 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
}

mod query {
use super::*;
use cw_common::asset_manager_msg::{ConfigureResponse, NetIdResponse, OwnerResponse};

use super::*;

pub fn query_get_owner(deps: Deps) -> StdResult<OwnerResponse> {
let owner = OWNER.load(deps.storage)?;
Ok(OwnerResponse { owner })
Expand Down Expand Up @@ -391,9 +396,6 @@ pub fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> Result<Response, Contract

#[cfg(test)]
mod tests {
use super::*;
use crate::contract::exec::configure_network;

use cosmwasm_std::{
testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier},
ContractResult, MemoryStorage, OwnedDeps, SystemResult, Uint128, WasmQuery,
Expand All @@ -403,6 +405,10 @@ mod tests {
use cw_common::xcall_data_types::DepositRevert;
use cw_common::{asset_manager_msg::InstantiateMsg, xcall_data_types::WithdrawTo};

use crate::contract::exec::setup;

use super::*;

//similar to fixtures
fn test_setup() -> (
OwnedDeps<MemoryStorage, MockApi, MockQuerier>,
Expand All @@ -413,19 +419,9 @@ mod tests {
let mut deps = mock_dependencies();
let env = mock_env();
let info = mock_info("user", &[]);

let instantiated_resp =
instantiate(deps.as_mut(), env.clone(), info.clone(), InstantiateMsg {}).unwrap();

//to pretend us as xcall contract during handle call execution testing
let xcall = "xcall";

let configure_msg = ExecuteMsg::ConfigureXcall {
source_xcall: xcall.to_owned(),
destination_asset_manager: "0x01.icon/cxc2d01de5013778d71d99f985e4e2ff3a9b48a66c"
.to_owned(),
};

// mocking response for external query i.e. allowance
deps.querier.update_wasm(|r: &WasmQuery| match r {
WasmQuery::Smart {
Expand All @@ -448,7 +444,17 @@ mod tests {
_ => todo!(),
});

execute(deps.as_mut(), env.clone(), info.clone(), configure_msg).unwrap();
let instantiated_resp = instantiate(
deps.as_mut(),
env.clone(),
info.clone(),
InstantiateMsg {
source_xcall: xcall.to_owned(),
destination_asset_manager: "0x01.icon/cxc2d01de5013778d71d99f985e4e2ff3a9b48a66c"
.to_owned(),
},
)
.unwrap();

(deps, env, info, instantiated_resp)
}
Expand Down Expand Up @@ -662,21 +668,19 @@ mod tests {
assert_eq!(response, Response::default());

// Verify the saved values
let saved_source_xcall: String = SOURCE_XCALL.load(deps.as_ref().storage).unwrap();
let saved_source_xcall: String = SOURCE_XCALL
.load(deps.as_ref().storage)
.unwrap()
.to_string();
let icon_am = ICON_ASSET_MANAGER.load(deps.as_ref().storage).unwrap();
let saved_destination_asset_manager = icon_am.to_string();

assert_eq!(saved_source_xcall, source_xcall);
assert_eq!(saved_destination_asset_manager, destination_asset_manager);

// Verify that only the owner can configure the network
let other_info = mock_info("other_sender", &[]);
let res = configure_network(
deps.as_mut(),
other_info,
source_xcall,
destination_asset_manager,
);
let _other_info = mock_info("other_sender", &[]);
let res = setup(deps.as_mut(), source_xcall, destination_asset_manager);

//check for error
assert!(res.is_err());
Expand Down
12 changes: 8 additions & 4 deletions contracts/core-contracts/cw-asset-manager/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::error::ContractError;
use cosmwasm_std::{Addr, DepsMut};
use cw_common::xcall_data_types::{DepositRevert, WithdrawTo};
use rlp::{DecoderError, Rlp};

use cw_common::xcall_data_types::{DepositRevert, WithdrawTo};

use crate::error::ContractError;

#[derive(Debug)]
pub enum DecodedStruct {
WithdrawTo(WithdrawTo),
Expand Down Expand Up @@ -81,10 +83,12 @@ pub fn validate_archway_address(deps: &DepsMut, address: &str) -> (Option<Addr>,

#[cfg(test)]
mod tests {
use super::*;
use cw_common::xcall_data_types::Deposit;
use rlp::Encodable;

use cw_common::xcall_data_types::Deposit;

use super::*;

#[test]
fn test_encode_decode_withdraw_to() {
let withdraw_to = WithdrawTo {
Expand Down
10 changes: 5 additions & 5 deletions contracts/core-contracts/cw-asset-manager/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use cosmwasm_std::Addr;
use cw_common::network_address::{NetId, NetworkAddress};
use cw_storage_plus::Item;

use cw_common::network_address::{NetId, NetworkAddress};

pub const OWNER: Item<Addr> = Item::new("contract_owner");

pub const SOURCE_XCALL: Item<String> = Item::new("source_xcall_address");
pub const X_NETWORK_ADDRESS: Item<NetworkAddress> = Item::new("source_xcall_network_address");
pub const SOURCE_XCALL: Item<Addr> = Item::new("source_xcall_address");
pub const X_CALL_NETWORK_ADDRESS: Item<NetworkAddress> = Item::new("source_xcall_network_address");
pub const NID: Item<NetId> = Item::new("network_id");

pub const ICON_ASSET_MANAGER: Item<NetworkAddress> =
Item::new("icon_asset_manager_network_address");
pub const ICON_ASSET_MANAGER: Item<Addr> = Item::new("icon_asset_manager_network_address");
pub const ICON_NET_ID: Item<NetId> = Item::new("icon_asset_manager_network_id");
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ fn deposit_cw20_token(mut ctx: TestContext, msg: ExecuteMsg) -> TestContext {

let resp = ctx
.app
.execute_contract(ctx.sender.clone(), ctx.get_assetmanager_app(), &msg, &[]);
.execute_contract(ctx.sender.clone(), ctx.get_asset_manager_app(), &msg, &[]);

println!("deposit execution resp: {:?}", resp);
ctx
}

fn increase_allowance(mut ctx: TestContext, amount: Uint128) -> (TestContext, Uint128) {
let relay = ctx.get_xcall_connection();
let am_addr = ctx.get_assetmanager_app();
let am_addr = ctx.get_asset_manager_app();

let spoke_addr = ctx.get_cw20token_app();
let token = Cw20Contract(ctx.get_cw20token_app());
Expand Down
6 changes: 5 additions & 1 deletion contracts/core-contracts/cw-asset-manager/tests/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,11 @@ pub fn init_asset_manager(mut ctx: TestContext) -> TestContext {
.instantiate_contract(
code_id,
ctx.sender.clone(),
&InstantiateMsg {},
&InstantiateMsg {
source_xcall: Addr::unchecked("x_call").into_string(),
destination_asset_manager: "0x01.icon/cx7866543210fedcba9876543210fedcba987654df"
.to_owned(),
},
&[],
"XCall",
None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::str::FromStr;

fn execute_handle_msg_on_asset_manager_from_relayer(mut ctx: TestContext) -> TestContext {
let relay = Addr::unchecked("relayer");
let asset_manager = ctx.get_assetmanager_app();
let asset_manager = ctx.get_asset_manager_app();

// ---------------------------- execution flow from RELAYER------> XCALL --------------------------------------------

Expand All @@ -36,7 +36,8 @@ fn execute_handle_msg_on_asset_manager_from_relayer(mut ctx: TestContext) -> Tes
let msg_typ: u64 = 1;

//destination asset manager
let from = NetworkAddress("0x01.icon/cx7866543210fedcba9876543210fedcba987654df".to_owned());
let from =
NetworkAddress::from_str("0x01.icon/cx7866543210fedcba9876543210fedcba987654df").unwrap();

//construct encoded CallServiceMessageRequest
let mut stream = RlpStream::new();
Expand Down
Loading

0 comments on commit 2320ccc

Please sign in to comment.