Injective | Documentation
InjectiveGithub
Injective | 中文文档
Injective | 中文文档
  • 关于 Injective
  • 快速入门
    • 钱包
      • 创建钱包
      • 账户
      • 质押
      • 治理
      • 拍卖
    • 代币标准
      • INJ 代币
      • Token Factory
      • CW20 标准
    • 交易
      • Gas 和 Fees
  • 指南
    • 创建钱包
    • 桥接
      • From Ethereum
      • Using Wormhole
      • Using IBC
      • From Solana
    • 发布代币
    • 发布市场
    • Denom 元数据
    • 获取INJ
  • 工具包
    • injectived
      • 安装 injectived
      • 使用 injectived
      • 指令
    • Injective TS SDK
    • Injective Go SDK
    • Injective Python SDK
    • Injective CW SDK
    • The Graph
  • 参考
  • 术语表
  • 开发者
    • 快速入门
      • 指南
        • 测试网提案
        • 转换地址
        • 计算
          • 最低价格刻度
          • 最低数量刻度
    • 交易所开发者
      • 构建 DEX
      • 预言机提供方
    • Cosmwasm 开发者
      • 您的首个智能合约
      • 指南
        • 本地开发
        • 主网开发
        • 给部署地址白名单
        • 创建您的 Swap 合约
        • 创建 UIs
      • CW20 适配器
      • Injective Test Tube
    • 模块
      • Injective
        • 拍卖(Auction)
          • State
          • 消息
          • EndBlock
          • 事件
          • 参数
        • 交易所(Exchange)
          • 衍生品市场概念
          • 现货市场概念
          • 二元期权市场概念
          • 其他概念
          • 状态
          • 状态转换
          • 消息
          • 提案
          • BeginBlock
          • EndBlock
          • 事件
          • 参数
          • MsgPrivilegedExecuteContract
        • 保险(Insurance)
          • 状态
          • 状态转换
          • 消息
          • EndBlock
          • 事件
          • 参数
          • 改进
        • OCR
          • 概念
          • 状态
          • 消息
          • 提案
          • BeginBlock
          • 钩子(Hooks)
          • 事件
          • 参数
        • 预言机(Oracle)
          • 状态
          • Keeper
          • 消息
          • 提案
          • 事件
          • 改进
        • Peggy
          • 定义
          • 工作流
          • 状态
          • 消息
          • 处罚
          • EndBlock
          • 事件
          • 参数
          • 中继语义
          • 改进
        • 权限(Permissions)
          • 概念
          • 状态
          • 状态转换
        • 代币工厂(TokenFactory)
          • 概念
          • 状态
          • 消息
          • 事件
          • 参数
        • WasmX
          • 概念
          • 数据
          • 提案
          • 消息
          • 参数
      • 核心
        • Auth
        • AuthZ
        • 银行(Bank)
        • 共识(Consensus)
        • 危机(Crisis)
        • 分发(Distribution)
        • 证据(Evidence)
        • 费用授权(Feegrant)
        • 治理(Gov)
        • 群组(Group)
        • 铸造(Mint)
        • NFT
        • 参数(Params)
        • 惩罚(Slashing)
        • 质押(Staking)
        • 升级(Upgrade)
        • Circuit
        • Genutils
    • dApps 开发文档
  • 节点
    • 快速入门
      • 和节点交互
      • 运行节点
        • 设置密钥环
        • 加入网络
        • Cosmovisor
        • 升级您的节点
    • 验证者
      • 主网
        • Peggo
        • 规范链升级
          • Upgrade to 10002-rc1
          • Upgrade to 10002-rc2
          • Upgrade to 10003-rc1
          • Upgrade to 10004-rc1
          • Upgrade to 10004-rc1-patch
          • Upgrade to 10005-rc1
          • Upgrade to 10006-rc1
          • Upgrade to 10007-rc1
          • Upgrade to 10008 - Camelot
          • Upgrade to 10009
          • Upgrade to v1.10
          • Upgrade to v1.11
          • Upgrade to v1.12.0 - Volan
          • Upgrade to v1.12.1
          • Upgrade to v1.13.0 - Altaris
          • Upgrade to v1.13.2
          • Upgrade to v1.13.3
          • Upgrade to v1.14.0
          • Upgrade to v1.14.1
      • 测试网
        • 测试网 Peggo
    • 公共端点
    • 高级端点
    • Injective 索引器设置
  • 交易员
    • 快速入门
    • 文档
    • API 参考
  • 常用链接
    • Injective 101
    • Injective Hub
    • Injective 浏览器
    • Chain API Reference
    • Indexer API Reference
    • 测试网水龙头
Powered by GitBook
On this page
  • 背景
  • Messages
Export as PDF
  1. 开发者
  2. Cosmwasm 开发者

CW20 适配器

Previous创建 UIsNextInjective Test Tube

Last updated 2 months ago

在本文档中,我们将解释 CW20 适配器合约,该合约允许将 CW-20 代币交换为 Injective 发行的原生代币(使用 TokenFactory 模块),反之亦然。关于 CW-20 适配器的 GitHub 仓库,请见。

背景

CW-20 是 CosmWasm 中的一种可替代代币规范, loosely 基于 ERC-20 规范。它允许在 CosmWasm 中创建和处理任意的可替代代币,指定用于创建、铸造、销毁和在账户之间转移这些代币的方法。适配器合约将确保只有授权的源 CW-20 合约可以铸造代币(以避免创建“伪造”代币)。

虽然 CW-20 标准相对成熟且完整,但这些代币仅存在于 CosmWasm 上下文中,并完全由发行合约管理(包括跟踪账户余额)。这意味着它们无法直接与 Injective 的原生模块交互(例如,无法通过 Injective 交易模块进行交易,或者在不涉及发行合约的情况下进行转移)。

考虑到上述情况,需要提供一个解决方案,作为 CW-20 和 Injective 银行模块之间的桥梁。

合约的工作流程如下:

  1. 注册一个新的 CW-20 代币。

  2. 将 X 数量的 CW-20 代币兑换为 Y 数量的 TokenFactory 代币(原始 CW-20 代币将由合约持有)。

  3. 将 Y 数量的 TF 代币兑换回 X 数量的 CW-20 代币(CW-20 代币被释放,TokenFactory 代币被销毁)。

Messages

RegisterCw20Contract { addr: Addr }

注册一个新的 CW-20 合约(地址),该合约将由适配器处理,并创建一个新的 TokenFactory 代币,格式为 factory/{adapter_contract}/{cw20_contract}。

ExecuteMsg::RegisterCw20Contract { addr } => execute_register::handle_register_msg(deps, env, info, addr)

pub fn handle_register_msg(
    deps: DepsMut<InjectiveQueryWrapper>,
    env: Env,
    info: MessageInfo,
    addr: Addr,
) -> Result<Response<InjectiveMsgWrapper>, ContractError> {
    if is_contract_registered(&deps, &addr) {
        return Err(ContractError::ContractAlreadyRegistered);
    }
    let required_funds = query_denom_creation_fee(&deps.querier)?;
    if info.funds.len() > required_funds.len() {
        return Err(ContractError::SuperfluousFundsProvided);
    }

    let mut provided_funds = info.funds.iter();

    for required_coin in &required_funds {
        let pf = provided_funds
           .find(|c| -> bool { c.denom == required_coin.denom })
           .ok_or(ContractError::NotEnoughBalanceToPayDenomCreationFee)?;

        match pf.amount.cmp(&required_coin.amount) {
            Ordering::Greater => return Err(ContractError::SuperfluousFundsProvided),
            Ordering::Less => return Err(ContractError::NotEnoughBalanceToPayDenomCreationFee),
            Ordering::Equal => {}
        }
    }

    let create_denom_msg = register_contract_and_get_message(deps, &env, &addr)?;
    Ok(Response::new().add_message(create_denom_msg))
}

Receive { sender: String, amount: Uint128, msg: Binary }

CW-20 接收者接口的实现。

必须仅由 CW-20 合约调用。

ExecuteMsg::Receive { sender, amount, msg: _ } => execute_receive::handle_on_received_cw20_funds_msg(deps, env, info, sender, amount)

pub fn handle_on_received_cw20_funds_msg(
    deps: DepsMut<InjectiveQueryWrapper>,
    env: Env,
    info: MessageInfo,
    recipient: String,
    amount: Uint128,
) -> Result<Response<InjectiveMsgWrapper>, ContractError> {
    if!info.funds.is_empty() {
        return Err(ContractError::SuperfluousFundsProvided);
    }
    let mut response = Response::new();
    let token_contract = info.sender;
    if!is_contract_registered(&deps, &token_contract) {
        ensure_sufficient_create_denom_balance(&deps, &env)?;
        response = response.add_message(register_contract_and_get_message(deps, &env, &token_contract)?);
    }
    let master = env.contract.address;

    let denom = get_denom(&master, &token_contract);
    let coins_to_mint = Coin::new(amount.u128(), denom);
    let mint_tf_tokens_message = create_mint_tokens_msg(master, coins_to_mint, recipient);

    Ok(response.add_message(mint_tf_tokens_message))
}

RedeemAndTransfer { recipient: Option<String> }

赎回附加的 TokenFactory 代币并将 CW-20 代币转移给接收者。如果未提供接收者,则代币将发送给消息发送者。

RedeemAndSend { recipient: String, submessage: Binary }

赎回附加的 TokenFactory 代币并将 CW-20 代币发送到接收者合约。调用者可以提供可选的子消息。

ExecuteMsg::RedeemAndTransfer { recipient } => execute_redeem::handle_redeem_msg(deps, env, info, recipient, None)

ExecuteMsg::RedeemAndSend { recipient, submsg } => execute_redeem::handle_redeem_msg(deps, env, info, Some(recipient), Some(submsg))

pub fn handle_redeem_msg(
    deps: DepsMut<InjectiveQueryWrapper>,
    env: Env,
    info: MessageInfo,
    recipient: Option<String>,
    submessage: Option<Binary>,
) -> Result<Response<InjectiveMsgWrapper>, ContractError> {
    let recipient = recipient.unwrap_or_else(|| info.sender.to_string());

    if info.funds.len() > 1 {
        return Err(ContractError::SuperfluousFundsProvided);
    }
    let tokens_to_exchange = info
       .funds
       .iter()
       .find_map(|c| -> Option<AdapterCoin> {
            match AdapterDenom::new(&c.denom) {
                Ok(denom) => Some(AdapterCoin { amount: c.amount, denom }),
                Err(_) => None,
            }
        })
       .ok_or(ContractError::NoRegisteredTokensProvided)?;

    let cw20_addr = tokens_to_exchange.denom.cw20_addr.clone();
    let is_contract_registered = CW20_CONTRACTS.contains(deps.storage, &tokens_to_exchange.denom.cw20_addr);
    if!is_contract_registered {
        return Err(ContractError::NoRegisteredTokensProvided);
    }

    let burn_tf_tokens_message = create_burn_tokens_msg(env.contract.address, tokens_to_exchange.as_coin());

    let cw20_message: WasmMsg = match submessage {
        None => WasmMsg::Execute {
            contract_addr: cw20_addr,
            msg: to_binary(&Cw20ExecuteMsg::Transfer {
                recipient,
                amount: tokens_to_exchange.amount,
            })?,
            funds: vec![],
        },
        Some(msg) => WasmMsg::Execute {
            contract_addr: cw20_addr,
            msg: to_binary(&Cw20ExecuteMsg::Send {
                contract: recipient,
                amount: tokens_to_exchange.amount,
                msg,
            })?,
            funds: vec![],
        },
    };
    Ok(Response::new().add_message(cw20_message).add_message(burn_tf_tokens_message))
}

UpdateMetadata { addr : Addr}

将查询 CW-20 地址(如果已注册)的元数据,并使用 TokenFactory 访问方法调用银行模块中的 setMetadata。

ExecuteMsg::UpdateMetadata { addr } => execute_metadata::handle_update_metadata(deps, env, addr)

pub fn handle_update_metadata(
    deps: DepsMut<InjectiveQueryWrapper>,
    env: Env,
    cw20_addr: Addr,
) -> Result<Response<InjectiveMsgWrapper>, ContractError> {
    let is_contract_registered = CW20_CONTRACTS.contains(deps.storage, cw20_addr.as_str());
    if!is_contract_registered {
        return Err(ContractError::ContractNotRegistered);
    }
    let token_metadata = fetch_cw20_metadata(&deps, cw20_addr.as_str())?;

    let denom = get_denom(&env.contract.address, &cw20_addr);
    let set_metadata_message = create_set_token_metadata_msg(denom, token_metadata.name, token_metadata.symbol, token_metadata.decimals);

    Ok(Response::new().add_message(set_metadata_message))
}

Queries
RegisteredContracts {}
Return a list of registered CW-20 contracts.

QueryMsg::RegisteredContracts {} => to_binary(&query::registered_contracts(deps)?)

pub fn registered_contracts(deps: Deps<InjectiveQueryWrapper>) -> StdResult<Vec<Addr>> {}

NewDenomFee {}
Returns a fee required to register a new tokenFactory denom.

QueryMsg::NewDenomFee {} => to_binary(&query::new_denom_fee(deps)?)

pub fn new_denom_fee(deps: Deps<InjectiveQueryWrapper>) -> StdResult<Uint128> {}
此处