Open
Conversation
10 tasks
28efa8b to
7b51ceb
Compare
This was
linked to
issues
Feb 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposal: Enable IBC Token Trading via Governance
Overview
This proposal enables the trading of Native and IBC Tokens in the Gonka Liquidity Pool and Community Sale contract by introducing a dedicated governance approval workflow. This is specifically designed to support stablecoin representations in the Cosmos ecosystem (such as
USDCorUSDT) as alternative to CW20 bridge wrapper.Core Design Principles
ibc_wrapped_token.go) and uses separate messages (MsgApproveIbcTokenForTrading).LiquidityPoolApprovedTokensMap). This ensures the existingApprovedTokensForTradequery automatically returns both CW20 and IBC tokens to UIs.ValidateIbcTokenForTrade) for IBC tokens, acknowledging that their metadata lives in the Bank module, not the Bridge store.Changes
1. Chain Logic (
inference-chain)A. New Protocol Definitions
MsgApproveIbcTokenForTradingChainId="ibc",ContractAddress="ibc/HASH"(or native denom).ValidateIbcTokenForTradeB. Implementation (
x/inference/keeper)We introduce new files to mirror the existing bridge functionality but adapted for IBC:
ibc_wrapped_token.go: Handles storage of approvals (allowing/in regex).query_ibc_token.go: Handles validation logic.BankKeeper.GetDenomMetaData(ctx, denom)exists (ensuring UI has decimals/symbol).LiquidityPoolApprovedTokensMap.msg_server_register_ibc_token_metadata.go: Handles dual-writing of metadata.WrappedTokenMetadataMapfor bridge-specific logic.BankKeeper.SetDenomMetaDatato ensure the IBC token decimals and symbol are visible via standard Cosmos bank queries and explorers.C. Contract Migration Integration (
app/upgrades/v0_2_11)Plan.Infofield for a JSON string containingcommunity_sale_addressandnew_code_id. Utilizingwasmkeeper, it safely executes the contract migration, automatically triggering the update payload to enable new configurationallow_all_trade_tokens.2. Contract Logic (
liquidity-pool)A. Dynamic Token Validation
validate_wrapped_token_for_tradeandvalidate_ibc_token_for_tradePAYMENT_TOKENSmap has been removed. The contract will now dynamically detect the token type and validate it against the chain module at the moment of purchase:ValidateWrappedTokenForTrade.ValidateIbcTokenForTrade.B. Native Token Purchase & Fund Accumulation
ExecuteMsg::PurchaseWithNativeand CW20Receiveinfo.funds(strictly 1 coin).adminaccount immediately, both CW20 and Native/IBC tokens safely accumulate in the contract's balance. This design change was necessary because the governance (admin) account does not have the ability to sign and execute CW20 smart contract transfer messages. If forwarded directly to governance, CW20 tokens would become permanently stuck. Administrators can withdraw funds using dedicated withdrawal functions.C. Direct Token Querying
QueryMsg::TestApprovedTokens(superseding local state queries)ApprovedTokensForTrade(which automatically returns both lists due to the shared state inLiquidityPoolApprovedTokensMap).3. Contract Logic (
community-sale)A. IBC Payment Support
ExecuteMsg::PurchaseWithNativeB. Dynamic Multi-Token Support (
allow_all_trade_tokens)ExecuteMsg::UpdateAllowAllTradeTokens&Configstructural changes.allow_all_trade_tokensconfiguration boolean. When enabled, the contract bypasses checks for a single strictly definedaccepted_ibc_denomoraccepted_eth_contract. Instead, it mirrors theliquidity-poolbehavior by independently validating any received token dynamically against the on-chain governance allowlist (viaValidateWrappedTokenForTradeandValidateIbcTokenForTradequeries).C. Migration Support
migrateentry point that allows existing contract instances (like the one funded in Proposal 14) to be safely upgraded to this new version.Bridge Audit Fixes Included in This PR
The following security findings from Certik bridge audit have been resolved as part of this change set:
community-saleContractcommunity-sale/src/contract.rswithdraw()inwrapped-tokenContractcontracts/wrapped-token/src/contract.rsInstantiateMsg.marketingIs Ignoredcontracts/wrapped-token/src/contract.rsIsBridgeContractAddress()keeper/bridge_native.goMigrateAllWrappedTokenContracts()keeper/bridge_wrapped_token.gomsg.AmountBeing Positive inMsgRequestBridgeWithdrawaltypes/message_request_bridge_withdrawal.goSummary of Fixes
withdraw()now validates thatdestination_addressconforms to the Ethereum address format (0x + 40 hex chars) to prevent permanent fund loss from invalid destinations.marketingfield fromInstantiateMsg— marketing info is hardcoded and governed on-chain via the governance module.IsBridgeContractAddress()now takeschainIdas a parameter and checks the exact(chainId, address)pair, preventing cross-chain address collisions with CREATE2/deterministic deployments.MigrateAllWrappedTokenContracts()now correctly uses the governance address (matching how contracts were instantiated) instead of the inference module address, resolving the authorization mismatch that caused DoS.MsgRequestBridgeWithdrawal.ValidateBasic()now parses and validates thatAmountis a positive integer usingmath.NewIntFromString, rejecting zero, negative, and non-numeric values.