MultiversX区块链Rust实现USDT转EGLD兑换及合约问题修复
问题解决与功能实现方案
一、"invalid contract code (not found)" 报错排查
这个错误核心原因是调用的交易所合约地址无效,按以下步骤排查:
- 确认
mx-exchange-sc合约地址匹配当前链环境(测试网/主网):- 测试网、主网的交易所地址不同,需通过MultiversX区块浏览器查询正确地址,避免跨环境使用或复制错误。
- 检查代理接口的
getAmountOut参数顺序与交易所实际接口完全一致:- 多数UniswapV2兼容交易所的
getAmountOut参数顺序为amountIn、tokenIn、tokenOut,需严格对应。
- 多数UniswapV2兼容交易所的
- 确保合约依赖的
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
相关产品推荐
相关产品推荐

