Sway 智能合约 Mint to Address:向地址铸造资产的完整指南

Sway 智能合约 Mint to Address:向地址铸造资产的完整指南 Sway 智能合约 Mint to Address向地址铸造资产的完整指南【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway铸造Mint是 Sway 智能合约中最核心的资产操作之一。本文以官方参考文档 Mint to Address 为骨架讲解如何在 Fuel 链上使用标准库std::asset::mint_to铸造指定数量的资产并将其直接转移给一个Address账户地址。读完本文你将掌握mint_to的导入方式、参数语义、Address/Identity/SubId三个关键类型的用法以及该函数在 sway-lib-std/src/asset.sw 中从mint指令到transfer转移的完整底层调用链并了解铸造到地址时的回滚revert条件与安全注意事项。一、核心概念Address、Identity 与 SubId在讲解具体代码之前需要先理清三个与铸造地址密切相关的类型。1.AddressUTXO 模型中的输出地址在 Fuel 的 UTXO 模型中每一个输出output都对应一个地址。Address是一个包含b256值的结构体其官方定义如下见 namespace 代码锚点pub struct Address { bits: b256, }Address的值是对以下二者之一的哈希一个公钥public key一个 Predicate谓词脚本需要注意Address与ContractId是完全分离的两种类型不应用Address来表示一个已部署合约的地址。Address与b256之间可以互相转换let variable1 0x000000000000000000000000000000000000000000000000000000000000002A; let my_address Address::from(variable1); let variable2: b256 my_address.into(); // variable1 variable22.Identity统一处理地址与合约的统一枚举mint_to的接收方参数类型是Identity而不是Address。Identity是一个枚举其定义见 sway-lib-std/src/identity.swpub enum Identity { Address: Address, ContractId: ContractId, }Identity的作用是让开发者能够以统一的方式处理转移给地址与转移给合约两类场景。当我们要铸造给某个Address时就用Identity::Address(user)将其包装起来。3.SubId子标识符SubIdsub identifier用于在同一合约下区分不同的资产。同一合约通过ContractId::this()与不同的SubId组合可以派生出不同的AssetId。铸造时通常使用SubId::zero()表示默认子标识。二、导入mint_to函数mint_to位于标准库的资产模块中。使用前需要显式导入use std::asset::mint_to;此导入语句与文档中的mint_to_import锚点一致见 asset_operations 示例代码。三、铸造到地址完整示例铸造资产并发送到指定Address时需要指定两个关键参数amount希望铸造的数量接收方封装为Identity::Address的目标地址。以下是文档与示例代码asset_operations 示例代码中的完整写法fn minting_to_address() { let amount 10; let address 0x0000000000000000000000000000000000000000000000000000000000000001; let user Address::from(address); mint_to(Identity::Address(user), SubId::zero(), amount); }逐行解读let amount 10;—— 定义铸造数量为 10。let address 0x...0001;—— 定义一个b256字面量作为目标地址。let user Address::from(address);—— 将b256转换为Address类型。mint_to(Identity::Address(user), SubId::zero(), amount);—— 以Identity::Address包装user以SubId::zero()作为子标识铸造amount数量的资产并转移给该地址。参数签名与含义根据 sway-lib-std/src/asset.sw 中的定义mint_to的完整签名为pub fn mint_to(to: Identity, sub_id: SubId, amount: u64)参数类型含义toIdentity接收资产的账户身份可以是Identity::Address(addr)或Identity::ContractId(id)sub_idSubId要铸造的资产的子标识符amountu64铸造的币数量四、底层实现剖析从mint到transfer的两步调用链mint_to之所以能做到铸造并转移是因为它在内部执行了两次操作。源码实现如下sway-lib-std/src/asset.swpub fn mint_to(to: Identity, sub_id: SubId, amount: u64) { mint(sub_id, amount); transfer(to, AssetId::new(ContractId::this(), sub_id), amount); }第一步mint—— 通过 Sway 汇编指令铸造mint将资产铸造到当前合约自身的余额中其实现直接调用了 Fuel 虚拟机VM的mint指令sway-lib-std/src/asset.swpub fn mint(sub_id: SubId, amount: u64) { asm(r1: amount, r2: sub_id) { mint r1 r2; } }即把amount放入寄存器r1、sub_id放入r2执行mint r1 r2指令。此时新铸造的资产由当前合约持有。第二步transfer—— 将资产转移给目标地址紧接着mint_to构造资产 IDAssetId::new(ContractId::this(), sub_id)并调用transfer把刚刚铸造出的资产从合约余额转移给目标Identity。transfer内部按接收方类型分派sway-lib-std/src/asset.swpub fn transfer(to: Identity, asset_id: AssetId, amount: u64) { match to { Identity::Address(addr) transfer_to_address(addr, asset_id, amount), Identity::ContractId(id) force_transfer_to_contract(id, asset_id, amount), }; }当目标是Address时走transfer_to_address分支该函数会遍历当前交易的所有输出outputs寻找一个金额为 0 的未使用OutputVariable找到后通过tro指令完成转移sway-lib-std/src/asset.swfn transfer_to_address(to: Address, asset_id: AssetId, amount: u64) { let mut index 0; let number_of_outputs output_count().as_u64(); while index number_of_outputs { if let Some(Output::Variable) output_type(index) { if let Some(0) output_amount(index) { asm(r1: to.bits(), r2: index, r3: amount, r4: asset_id) { tro r1 r2 r3 r4; }; return; } } index 1; } revert(FAILED_TRANSFER_TO_ADDRESS_SIGNAL); }由此可见铸造到地址的本质是先铸造到合约再通过tro指令转账到地址。这也解释了为何铸造到合约Identity::ContractId与铸造到地址在底层走的是不同的转移路径。五、回滚Revert条件与安全注意事项从源码文档doc comments与实现中可以确认以下回滚条件transfer到地址时sway-lib-std/src/asset.sw当amount大于合约中asset_id对应余额时回滚当amount等于 0 时回滚当交易中没有可用的空闲可变输出free variable output时回滚即上面transfer_to_address中遍历后未找到未使用输出调用revert(FAILED_TRANSFER_TO_ADDRESS_SIGNAL)。transfer到合约时force_transfer_to_contractsway-lib-std/src/asset.sw当amount大于合约余额或等于 0 时回滚。⚠️ 特别警示永久丢失资产的风险mint_to的文档注释明确警告sway-lib-std/src/asset.sw如果to是一个合约即使接收合约没有任何可取回资金的机制例如没有提款功能资产也会被转移过去若使用不当可能导致资产的永久丢失PERMANENT LOSS OF COINS。虽然本文主题是铸造到Address账户地址但在使用mint_to设计业务逻辑时务必意识到同一函数也支持Identity::ContractId需要根据接收方类型谨慎设计。六、与其他铸造方式的关系在 铸造总览文档 中标准库sway-lib-std/src/asset.sw提供了两种铸造函数mint()只铸造资产留在当前合约余额中不进行转移use std::asset::mint; let amount 10; mint(SubId::zero(), amount);mint_to()铸造并转移可指定Identity::Address本文场景或Identity::ContractId。完整的铸造到地址示例代码还包含铸造到合约minting_to_contract与同时铸造到两类目标minting_to的写法均可参考 asset_operations 示例代码。七、实践建议明确目标类型向账户地址铸造时使用Identity::Address(Address::from(b256))向合约铸造时使用Identity::ContractId不要混用Address与ContractId。留意 SubId 与资产 IDmint_to中使用的sub_id与最终资产 ID 的关系是AssetId::new(ContractId::this(), sub_id)同一合约可借助不同SubId铸造多种资产。预留可变输出由于铸造到地址依赖tro指令写入可变输出交易必须包含足够的可变输出数量否则会以FAILED_TRANSFER_TO_ADDRESS_SIGNAL回滚。金额与余额校验确保amount大于 0 且不超过合约在该资产上的余额避免触发回滚。如需深入了解Address的底层定义、ContractId以及Identity的其他辅助方法可继续阅读 Address 参考文档、ContractId 参考文档 与 Identity 源码。【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考