Cosmos Coin Wrapper Paths

Cosmos Wrapper Paths enable wrapping between BitBadges tokens and native Cosmos SDK coin (x/bank) asset types, making tokens IBC-compatible. These paths automatically mint and burn tokens when transferring to/from specific wrapper addresses.

This is used to generate a 1:1 compatible mapping between our standard tokens and native Cosmos SDK coins. Note that this does not use an existing IBC denom, but rather creates a custom generated denomination.

Use cases could include:

  • Using our standard tokens for time-dependent logic but eventually making them native Cosmos SDK coins

  • Compatibility with existing Cosmos services and chains like Osmosis, Juno, etc.

Important: Since wrapper addresses are uncontrollable (no private keys), approval design requires careful consideration. You must override the wrapper address's user-level approvals where necessary using collection approvals to ensure wrapping/unwrapping functions properly.

Core Concept

Wrapper paths create special addresses that convert our standard tokens to native Cosmos SDK coins:

  • Wrapping: Send our standard tokens to wrapper address β†’ receive native coins (tokens are burned, x/bank coins are minted)

  • Unwrapping: Send native coins to wrapper address β†’ receive our standard tokens (x/bank coins are burned, tokens are minted)

// Collection with wrapper path
const collection: MsgCreateCollection = {
    creator: 'bb1kj9kt5y64n5a8677fhjqnmcc24ht2vy9atmdls',
    collectionId: '0', // 0 for new collection
    validTokenIds: [{ start: 1n, end: 100n }],
    cosmosCoinWrapperPathsToAdd: [
        {
            denom: 'utoken',
            conversion: {
                sideA: {
                    amount: '1', // Required: amount of wrapped coin
                },
                sideB: [
                    {
                        amount: 1n,
                        tokenIds: [{ start: 1n, end: 100n }],
                        ownershipTimes: [
                            { start: 1n, end: 18446744073709551615n },
                        ],
                    },
                ],
            },
            symbol: 'TOKEN',
            denomUnits: [
                {
                    decimals: 6n,
                    symbol: 'TOKEN',
                    isDefaultDisplay: true,
                },
            ],
            allowOverrideWithAnyValidToken: false,
            metadata: { uri: '', customData: '' }, // Optional metadata
        },
    ],
    aliasPathsToAdd: [
        {
            denom: 'utoken-alias',
            conversion: {
                sideA: {
                    amount: '1', // Required: amount of wrapped coin
                },
                sideB: [
                    {
                        amount: 1n,
                        tokenIds: [{ start: 1n, end: 100n }],
                        ownershipTimes: [
                            { start: 1n, end: 18446744073709551615n },
                        ],
                    },
                ],
            },
            symbol: 'ALIAS',
            denomUnits: [
                {
                    decimals: 6n,
                    symbol: 'ALIAS',
                    isDefaultDisplay: true,
                },
            ],
            metadata: { uri: '', customData: '' }, // Optional metadata
        },
    ],
    // ... other fields
};

Wrapper Paths vs Alias Paths

The system now distinguishes between two separate path types:

Cosmos Coin Wrapper Paths

Used for actual wrapping/unwrapping with minting and burning:

  • Purpose: Convert tokens to native Cosmos SDK coins and vice versa

  • Behavior: Tokens are burned when wrapping, coins are minted. Coins are burned when unwrapping, tokens are minted

  • Use case: IBC transfers, converting tokens to native coins for Cosmos ecosystem compatibility

  • Storage: Stored in cosmosCoinWrapperPaths array

  • Features: Includes address field (wrapper address) and allowOverrideWithAnyValidToken option

Alias Paths

Used for compatibility with existing Cosmos SDK interfaces without actual wrapping:

  • Purpose: Alias denomination support (e.g., badgeslp:COLLECTION_ID:denom)

  • Behavior: No minting/burning occurs, only an alias for information purposes

  • Use case: Compatibility with liquidity pools, DeFi protocols that expect sdk.Coin format

  • Storage: Stored in aliasPaths array (separate from wrapper paths)

  • See: Alias Compatibility for details

  • Note: Does not include address or allowOverrideWithAnyValidToken fields

Wrapper Address Generation

Wrapper addresses are auto-generated based on the denom:

Note: The address is generated from the custom denom, not the full badges:collectionId:denom format.

Conversion Structure

Wrapper paths and alias paths use a structured conversion format to define the relationship between wrapped/alias units and badge tokens:

ConversionWithoutDenom

Used by wrapper paths and alias paths (denom stored separately):

Key Points:

  • sideA.amount: The amount of wrapped/alias coin units (required, must be specified)

  • sideB: Array of Balance objects that define the tokens involved in the conversion

  • The denom is stored at the path level, not in the conversion (hence "WithoutDenom")

  • Conversion rate: sideA.amount wrapped/alias units = sideB[] tokens

Example:

  • If sideA.amount = "1" and sideB = [{ amount: 1n, tokenIds: [...], ... }]

  • Then: 1 wrapped coin = 1 token (1:1 conversion)

Example with different rate:

  • If sideA.amount = "100" and sideB = [{ amount: 1n, tokenIds: [...], ... }]

  • Then: 100 wrapped coins = 1 token (100:1 conversion)

Configuration Fields

Denom

The base denomination for the wrapped coin. The full Cosmos denomination will be badges:collectionId:denom. Note that badges: is different from the badgeslp: format used for aliases elsewhere.

Conversion

Defines the conversion rate between wrapped coins and tokens using a structured conversion format:

Conversion rate: conversion.sideA.amount wrapped coin = conversion.sideB[] tokens

Key Points:

  • sideA.amount is required and must be specified (cannot be "0" or nil)

  • sideB contains the Balances[] that define which tokens participate in wrapping

  • The denom is stored separately at the path level (not in the conversion)

Denomination Units

Multiple denomination units allow different display formats:

System:

  • utoken = base unit (0 decimals)

  • mtoken = 1,000 utoken (3 decimals)

  • TOKEN = 1,000,000 utoken (6 decimals, default display)

Note: Each DenomUnit now includes an optional metadata field of type PathMetadata for additional information.

Allow Override With Any Valid Token

When true, allows the wrapper to accept any SINGLE valid token ID from the collection's validTokenIds range:

How it works:

  1. User transfers token ID 5 to wrapper

  2. System validates token ID 5 is in validTokenIds

  3. System temporarily overrides conversion.sideB[].tokenIds with [{ start: 5n, end: 5n }] ignoring the values set in the sideB array

  4. Conversion proceeds with token ID 5

{id} Placeholder Support

You can use {id} in the denom to dynamically replace it with the actual token ID:

Example: Transferring token ID 5 results in denom utoken5.

Metadata

Both wrapper paths and alias paths support optional metadata using the standard metadata structure:

The hosted JSON at the URI typically contains { name, image, description }, though the image is the primary use case. The on-chain symbol field is used for identification, not the metadata name.

Note: Metadata is optional. It's also available on DenomUnit objects for additional per-unit metadata.

Transferability Requirements

Wrapper addresses are subject to the same transferability requirements as any other address. You can user-gate, rate-limit, or apply custom logic:

Conversion Process

Token to Coin (Wrapping)

  1. User transfers tokens to wrapper address

  2. System processes denom (replaces {id} if present, validates override if enabled)

  3. System burns tokens from user's balance

  4. System mints equivalent native coins

  5. Coins credited to user's account

Coin to Token (Unwrapping)

Unwrapping still uses MsgTransferTokens. You initiate a transfer on behalf of the wrapper address:

  1. User initiates MsgTransferTokens with wrapper address as from

  2. System processes denom (replaces {id} if present, validates override if enabled)

  3. System burns native coins from wrapper address

  4. System mints equivalent tokens

  5. Tokens credited to user's balance

Use Cases

IBC Transfers

Enable cross-chain transfers of wrapped tokens:

DeFi Integration

Use wrapped tokens in Cosmos DeFi protocols:

Permission Control

Adding new cosmos coin wrapper paths to a collection is controlled by the canAddMoreCosmosCoinWrapperPaths permission. This permission allows you to control when managers can add new wrapper paths.

Default Behavior

  • Empty/Nil Permissions: When canAddMoreCosmosCoinWrapperPaths is empty or nil, adding paths is allowed (neutral state)

  • Migration: Collections migrated from v21 will have empty permissions, meaning adding paths is allowed by default

Permission Structure

The permission uses the ActionPermission type with time-based controls:

Usage Examples

Allow adding paths at all times:

Lock adding paths forever:

Allow adding paths only during specific period:

Permission Check

When using MsgUniversalUpdateCollection to add wrapper paths via cosmosCoinWrapperPathsToAdd, the system checks the canAddMoreCosmosCoinWrapperPaths permission before processing the paths. If the permission check fails, the transaction will be rejected with an appropriate error message.

Note: The permission is checked before paths are added, but the permission itself can be updated at the end of the transaction (if updateCollectionPermissions is set to true).

Differences from IBC Backed Paths

Feature
Wrapper Path
IBC Backed Path

Minting

Minting/burning of new denom

No minting/burning (uses existing IBC)

Denom Source

Generated denom

Existing IBC denom

Configuration

Can add paths, no edits

Collection invariant

Mint Address

Enabled

Disabled

Last updated