diff --git a/contracts/main/voice/src/contract.rs b/contracts/main/voice/src/contract.rs index 498f58a..ea90146 100644 --- a/contracts/main/voice/src/contract.rs +++ b/contracts/main/voice/src/contract.rs @@ -1,9 +1,9 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - from_json, instantiate2_address, to_json_binary, to_json_vec, Binary, CodeInfoResponse, - ContractResult, Deps, DepsMut, Env, MessageInfo, Response, StdResult, SubMsg, SystemResult, - Uint64, WasmMsg, + from_json, instantiate2_address, to_json_binary, to_json_vec, Binary, CanonicalAddr, + CodeInfoResponse, ContractResult, Deps, DepsMut, Env, MessageInfo, Response, StdResult, SubMsg, + SystemResult, Uint64, WasmMsg, }; use cw2::set_contract_version; @@ -13,7 +13,9 @@ use polytone::ibc::{Msg, Packet}; use crate::error::ContractError; use crate::ibc::{ACK_GAS_NEEDED, REPLY_FORWARD_DATA}; use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; -use crate::state::{BLOCK_MAX_GAS, PROXY_CODE_ID, SENDER_TO_PROXY}; +use crate::state::{ + SenderInfo, BLOCK_MAX_GAS, CONTRACT_ADDR_LEN, PROXY_CODE_ID, PROXY_TO_SENDER, SENDER_TO_PROXY, +}; const CONTRACT_NAME: &str = "crates.io:polytone-voice"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -35,13 +37,20 @@ pub fn instantiate( return Err(ContractError::GasLimitsMismatch); } + let contract_addr_len = msg.contract_addr_len.unwrap_or(32); + if contract_addr_len == 0 { + return Err(ContractError::ContractAddrLenCantBeZero); + } + PROXY_CODE_ID.save(deps.storage, &msg.proxy_code_id.u64())?; BLOCK_MAX_GAS.save(deps.storage, &msg.block_max_gas.u64())?; + CONTRACT_ADDR_LEN.save(deps.storage, &contract_addr_len)?; Ok(Response::default() .add_attribute("method", "instantiate") .add_attribute("proxy_code_id", msg.proxy_code_id) - .add_attribute("block_max_gas", msg.block_max_gas)) + .add_attribute("block_max_gas", msg.block_max_gas) + .add_attribute("contract_addr_len", contract_addr_len.to_string())) } #[cfg_attr(not(feature = "library"), entry_point)] @@ -104,17 +113,33 @@ pub fn execute( let contract = deps.api.addr_canonicalize(env.contract.address.as_str())?; let code_id = PROXY_CODE_ID.load(deps.storage)?; + let addr_len = CONTRACT_ADDR_LEN.load(deps.storage)?; let CodeInfoResponse { checksum, .. } = deps.querier.query_wasm_code_info(code_id)?; let salt = salt(&connection_id, &counterparty_port, &sender); - let proxy = deps.api.addr_humanize(&instantiate2_address( - &checksum, &contract, &salt, - )?)?; + let init2_addr_data: CanonicalAddr = + instantiate2_address(&checksum, &contract, &salt)?.to_vec() + [0..addr_len as usize] + .into(); + let proxy = deps.api.addr_humanize(&init2_addr_data)?; SENDER_TO_PROXY.save( deps.storage, - (connection_id, counterparty_port, sender.clone()), + ( + connection_id.clone(), + counterparty_port.clone(), + sender.clone(), + ), &proxy, )?; + PROXY_TO_SENDER.save( + deps.storage, + proxy.clone(), + &SenderInfo { + connection_id, + remote_port: counterparty_port, + remote_sender: sender.clone(), + }, + )?; ( Some(WasmMsg::Instantiate2 { admin: None, @@ -171,6 +196,10 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::BlockMaxGas => to_json_binary(&BLOCK_MAX_GAS.load(deps.storage)?), QueryMsg::ProxyCodeId => to_json_binary(&PROXY_CODE_ID.load(deps.storage)?), + QueryMsg::ContractAddrLen => to_json_binary(&CONTRACT_ADDR_LEN.load(deps.storage)?), + QueryMsg::SenderInfoForProxy { proxy } => { + to_json_binary(&PROXY_TO_SENDER.load(deps.storage, deps.api.addr_validate(&proxy)?)?) + } } } @@ -180,6 +209,7 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result { if proxy_code_id.is_zero() { return Err(ContractError::CodeIdCantBeZero); @@ -189,14 +219,20 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result, } #[cw_serde] @@ -35,6 +40,12 @@ pub enum QueryMsg { /// `"proxy_code_id"`. #[returns(Uint64)] ProxyCodeId, + /// Queries the configured contract address length. + #[returns(u8)] + ContractAddrLen, + /// Queries the sender information for a given proxy. + #[returns(SenderInfo)] + SenderInfoForProxy { proxy: String }, } #[cw_serde] @@ -45,5 +56,7 @@ pub enum MigrateMsg { proxy_code_id: Uint64, /// The max gas allowed in a single block. block_max_gas: Uint64, + /// The contract address length used by the chain. + contract_addr_len: u8, }, } diff --git a/contracts/main/voice/src/state.rs b/contracts/main/voice/src/state.rs index 89ffa8b..476b352 100644 --- a/contracts/main/voice/src/state.rs +++ b/contracts/main/voice/src/state.rs @@ -1,9 +1,13 @@ +use cosmwasm_schema::cw_serde; use cosmwasm_std::Addr; use cw_storage_plus::{Item, Map}; /// (connection_id, remote_port, remote_sender) -> proxy pub(crate) const SENDER_TO_PROXY: Map<(String, String, String), Addr> = Map::new("c2p"); +/// proxy -> { connection_id, remote_port, remote_sender } +pub(crate) const PROXY_TO_SENDER: Map = Map::new("p2c"); + /// (channel_id) -> connection_id pub(crate) const CHANNEL_TO_CONNECTION: Map = Map::new("c2c"); @@ -12,3 +16,13 @@ pub(crate) const PROXY_CODE_ID: Item = Item::new("pci"); /// Max gas usable in a single block. pub(crate) const BLOCK_MAX_GAS: Item = Item::new("bmg"); + +/// Contract address length used by the chain. +pub(crate) const CONTRACT_ADDR_LEN: Item = Item::new("cal"); + +#[cw_serde] +pub struct SenderInfo { + pub connection_id: String, + pub remote_port: String, + pub remote_sender: String, +} diff --git a/contracts/main/voice/src/suite_tests/suite.rs b/contracts/main/voice/src/suite_tests/suite.rs index c40abab..c899d7f 100644 --- a/contracts/main/voice/src/suite_tests/suite.rs +++ b/contracts/main/voice/src/suite_tests/suite.rs @@ -1,7 +1,7 @@ use cosmwasm_std::{Addr, Empty, Uint64}; use cw_multi_test::{App, AppResponse, Contract, ContractWrapper, Executor}; -use crate::msg::QueryMsg::{BlockMaxGas, ProxyCodeId}; +use crate::msg::QueryMsg::{BlockMaxGas, ContractAddrLen, ProxyCodeId}; use crate::msg::{InstantiateMsg, MigrateMsg}; pub const CREATOR_ADDR: &str = "creator"; @@ -33,6 +33,7 @@ impl Default for SuiteBuilder { instantiate: InstantiateMsg { proxy_code_id: Uint64::new(9999), block_max_gas: Uint64::new(110_000), + contract_addr_len: None, }, } } @@ -95,6 +96,13 @@ impl Suite { .query_wasm_smart(&self.voice_address, &ProxyCodeId) .unwrap() } + + pub fn query_contract_addr_len(&self) -> u8 { + self.app + .wrap() + .query_wasm_smart(&self.voice_address, &ContractAddrLen) + .unwrap() + } } // migrate @@ -104,6 +112,7 @@ impl Suite { sender: Addr, contract_code_id: u64, block_max_gas: u64, + contract_addr_len: u8, ) -> anyhow::Result { self.app.migrate_contract( sender, @@ -111,6 +120,7 @@ impl Suite { &MigrateMsg::WithUpdate { proxy_code_id: contract_code_id.into(), block_max_gas: block_max_gas.into(), + contract_addr_len: contract_addr_len, }, self.voice_code, ) @@ -128,4 +138,9 @@ impl Suite { let curr = self.query_proxy_code_id(); assert_eq!(curr, val); } + + pub fn assert_contract_addr_len(&self, val: u8) { + let curr = self.query_contract_addr_len(); + assert_eq!(curr, val); + } } diff --git a/contracts/main/voice/src/suite_tests/tests.rs b/contracts/main/voice/src/suite_tests/tests.rs index a2db1d1..df2e276 100644 --- a/contracts/main/voice/src/suite_tests/tests.rs +++ b/contracts/main/voice/src/suite_tests/tests.rs @@ -16,7 +16,7 @@ fn test_update() { let proxy_code_new = suite.store_voice_contract(); suite - .update(Addr::unchecked(CREATOR_ADDR), proxy_code_new, 111_000) + .update(Addr::unchecked(CREATOR_ADDR), proxy_code_new, 111_000, 32) .unwrap(); // assert that both fields updated succesfully @@ -31,7 +31,7 @@ fn test_query_block_max_gas() { suite.assert_block_max_gas(110_000); suite - .update(Addr::unchecked(CREATOR_ADDR), suite.voice_code, 111_000) + .update(Addr::unchecked(CREATOR_ADDR), suite.voice_code, 111_000, 32) .unwrap(); suite.assert_block_max_gas(111_000); @@ -44,12 +44,25 @@ fn test_query_proxy_code_id() { suite.assert_proxy_code(9999); suite - .update(Addr::unchecked(CREATOR_ADDR), 1, 110_000) + .update(Addr::unchecked(CREATOR_ADDR), 1, 110_000, 32) .unwrap(); suite.assert_proxy_code(1); } +#[test] +fn test_query_contract_addr_len() { + let mut suite = SuiteBuilder::default().build(); + + suite.assert_contract_addr_len(32); + + suite + .update(Addr::unchecked(CREATOR_ADDR), 1, 110_000, 20) + .unwrap(); + + suite.assert_contract_addr_len(20); +} + #[test] #[should_panic] fn test_code_id_validation() { @@ -71,7 +84,7 @@ fn test_migrate_validation() { let mut suite = SuiteBuilder::default().build(); let err = suite - .update(Addr::unchecked(CREATOR_ADDR), 0, 110_000) + .update(Addr::unchecked(CREATOR_ADDR), 0, 110_000, 32) .unwrap_err() .downcast::() .unwrap(); @@ -79,7 +92,7 @@ fn test_migrate_validation() { assert_eq!(err, ContractError::CodeIdCantBeZero); let err = suite - .update(Addr::unchecked(CREATOR_ADDR), 1, 0) + .update(Addr::unchecked(CREATOR_ADDR), 1, 0, 32) .unwrap_err() .downcast::() .unwrap(); diff --git a/packages/cw-orch-polytone/src/deploy.rs b/packages/cw-orch-polytone/src/deploy.rs index b2e7e1e..78f7095 100644 --- a/packages/cw-orch-polytone/src/deploy.rs +++ b/packages/cw-orch-polytone/src/deploy.rs @@ -46,6 +46,7 @@ impl Deploy for Polytone { &polytone_voice::msg::InstantiateMsg { proxy_code_id: deployment.proxy.code_id()?.into(), block_max_gas: MAX_BLOCK_GAS.into(), + contract_addr_len: None, }, None, None, diff --git a/tests/simtests/contract.go b/tests/simtests/contract.go index 0559aba..4aa4101 100644 --- a/tests/simtests/contract.go +++ b/tests/simtests/contract.go @@ -16,8 +16,9 @@ type NoteInstantiate struct { } type VoiceInstantiate struct { - ProxyCodeId uint64 `json:"proxy_code_id,string"` - BlockMaxGas uint64 `json:"block_max_gas,string"` + ProxyCodeId uint64 `json:"proxy_code_id,string"` + BlockMaxGas uint64 `json:"block_max_gas,string"` + ContractAddrLen uint8 `json:"contract_addr_len"` } type TesterInstantiate struct { diff --git a/tests/simtests/functionality_suite.go b/tests/simtests/functionality_suite.go index 9f6294b..eb07854 100644 --- a/tests/simtests/functionality_suite.go +++ b/tests/simtests/functionality_suite.go @@ -52,8 +52,9 @@ func SetupChain(t *testing.T, c *ibctesting.Coordinator, index int) Chain { BlockMaxGas: uint64(blockMaxGas), }) voice := Instantiate(t, chain, 2, VoiceInstantiate{ - ProxyCodeId: 3, - BlockMaxGas: uint64(blockMaxGas), + ProxyCodeId: 3, + BlockMaxGas: uint64(blockMaxGas), + ContractAddrLen: 32, }) tester := Instantiate(t, chain, 4, TesterInstantiate{}) diff --git a/tests/strangelove/suite.go b/tests/strangelove/suite.go index f214d60..27d58ca 100644 --- a/tests/strangelove/suite.go +++ b/tests/strangelove/suite.go @@ -190,11 +190,11 @@ func (s *Suite) SetupChain(chain *SuiteChain) { chain.Note = s.Instantiate(cc, user, noteId, NoteInstantiate{}) chain.Voice = s.Instantiate(cc, user, voiceId, VoiceInstantiate{ - ProxyCodeId: uint64(proxyUint), - BlockMaxGas: 100_000_000, + ProxyCodeId: uint64(proxyUint), + BlockMaxGas: 100_000_000, + ContractAddrLen: 32, }) chain.Tester = s.Instantiate(cc, user, testerId, TesterInstantiate{}) - return } func (s *Suite) Instantiate(chain *cosmos.CosmosChain, user *ibc.Wallet, codeId string, msg any) string { diff --git a/tests/strangelove/types.go b/tests/strangelove/types.go index 20f88a8..766e58b 100644 --- a/tests/strangelove/types.go +++ b/tests/strangelove/types.go @@ -15,8 +15,9 @@ type NoteInstantiate struct { } type VoiceInstantiate struct { - ProxyCodeId uint64 `json:"proxy_code_id,string"` - BlockMaxGas uint64 `json:"block_max_gas,string"` + ProxyCodeId uint64 `json:"proxy_code_id,string"` + BlockMaxGas uint64 `json:"block_max_gas,string"` + ContractAddrLen uint8 `json:"contract_addr_len"` } type TesterInstantiate struct {