You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MultiversX区块链Rust实现USDT转EGLD兑换及合约问题修复

问题解决与功能实现方案

一、"invalid contract code (not found)" 报错排查

这个错误核心原因是调用的交易所合约地址无效,按以下步骤排查:

  1. 确认mx-exchange-sc合约地址匹配当前链环境(测试网/主网):
    • 测试网、主网的交易所地址不同,需通过MultiversX区块浏览器查询正确地址,避免跨环境使用或复制错误。
  2. 检查代理接口的getAmountOut参数顺序与交易所实际接口完全一致:
    • 多数UniswapV2兼容交易所的getAmountOut参数顺序为amountIn、tokenIn、tokenOut,需严格对应。
  3. 确保合约依赖的multiversx-sc版本与链上交易所合约版本兼容,避免ABI不匹配导致识别失败。

二、完整功能实现代码

以下是符合需求的Rust智能合约代码,包含所有逻辑步骤:

1. 依赖与代理接口定义

use multiversx_sc::imports::*;

// 定义mx-exchange-sc的view接口,匹配getAmountOut方法
#[multiversx_sc::proxy]
pub trait IMxExchangeSc {
    #[view(getAmountOut)]
    fn get_amount_out(&self, amount_in: &BigUint, token_in: &TokenIdentifier, token_out: &TokenIdentifier) -> BigUint;
}

#[multiversx_sc::contract]
pub trait CustomTokenSaleContract {
    // 初始化合约,传入USDT、EGLD代币ID,以及交易所合约地址
    #[init]
    fn init(
        &self,
        usdt_token_id: TokenIdentifier,
        egld_token_id: TokenIdentifier,
        exchange_address: ManagedAddress
    ) {
        self.usdt_token_id().set(&usdt_token_id);
        self.egld_token_id().set(&egld_token_id);
        self.exchange_address().set(&exchange_address);
        // 预设代币单价:0.005 USDT(对应6位小数的5_000_000单位)
        self.token_price_usdt().set(&BigUint::from(5_000_000u64));
    }

    // -------------------------- 存储变量 --------------------------
    #[view(getUsdtTokenId)]
    #[storage_mapper("usdt_token_id")]
    fn usdt_token_id(&self) -> SingleValueMapper<TokenIdentifier>;

    #[view(getEgldTokenId)]
    #[storage_mapper("egld_token_id")]
    fn egld_token_id(&self) -> SingleValueMapper<TokenIdentifier>;

    #[view(getExchangeAddress)]
    #[storage_mapper("exchange_address")]
    fn exchange_address(&self) -> SingleValueMapper<ManagedAddress>;

    #[view(getTokenPriceUsdt)]
    #[storage_mapper("token_price_usdt")]
    fn token_price_usdt(&self) -> SingleValueMapper<BigUint>;

    // -------------------------- 核心购买逻辑 --------------------------
    #[payable("EGLD")]
    #[endpoint(buyToken)]
    fn buy_token(&self, desired_token_amount: BigUint) {
        // 1. 获取用户支付的EGLD金额与调用者地址
        let received_egld = self.call_value().egld_value();
        let caller = self.blockchain().get_caller();

        // 2. 计算所需总USDT金额:购买数量 × 0.005 USDT(转换为6位小数单位)
        let usdt_per_token = self.token_price_usdt().get();
        let total_usdt_required = &desired_token_amount * &usdt_per_token;

        // 3. 调用交易所获取对应EGLD金额
        let usdt_id = self.usdt_token_id().get();
        let egld_id = self.egld_token_id().get();
        let exchange_addr = self.exchange_address().get();

        // 创建代理并执行view调用
        let exchange_proxy = self.proxy::<IMxExchangeSc>(&exchange_addr);
        let required_egld = exchange_proxy
            .get_amount_out(&total_usdt_required, &usdt_id, &egld_id)
            .execute_on_dest_context();

        // 4. 校验支付金额是否匹配
        require!(received_egld == required_egld, "EGLD amount mismatch");

        // 5. 向用户转账自定义代币(假设自定义代币为合约自身的内置代币)
        let custom_token_id = self.blockchain().get_sc_address().into();
        self.send().direct(&caller, &custom_token_id, 0, &desired_token_amount);
    }
}

2. 关键注意事项

  • 代币ID设置:USDT在MultiversX测试网的代币ID为USDT-8d4068,主网为USDT-a6481,需根据部署环境正确传入。
  • 小数精度处理:USDT为6位小数,EGLD为18位小数,getAmountOut返回的EGLD金额已自动转换为18位单位,可直接与用户支付的EGLD比较。
  • 代理调用方式:getAmountOut是view方法,必须使用execute_on_dest_context()执行,而非交易型的execute()。

内容的提问来源于stack exchange,提问作者Neon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:07:50