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

能否在一笔交易中同时发送1155/731 NFT与ERC-20代币?求示例

单笔交易同时转账NFT(ERC-721/ERC-1155)与ERC-20代币的可行性及实现

可行性说明

完全可行。区块链交易的本质是向链上发送包含一系列指令的数据包,只要这些指令符合合约调用规则,就能在同一笔交易内依次执行多个操作——比如完成ERC-20代币转账后,再执行ERC-721/ERC-1155 NFT的转账,核心是通过合约批量调用或聚合合约来实现。

实现方式及示例

方式1:自定义聚合合约(推荐)

编写一个简单的智能合约,在合约内封装ERC-20和NFT的转账逻辑,用户只需调用聚合合约的一个方法,就能在单笔交易中完成所有操作。

Solidity合约示例

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC20 {
    function transfer(address to, uint256 amount) external returns (bool);
}

interface IERC721 {
    function transferFrom(address from, address to, uint256 tokenId) external;
}

interface IERC1155 {
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
}

contract BatchTransfer {
    // 同时转账ERC-20和ERC-721
    function transferERC20And721(
        address erc20Addr,
        address erc721Addr,
        address recipient,
        uint256 erc20Amount,
        uint256 nftTokenId
    ) external {
        require(IERC20(erc20Addr).transfer(recipient, erc20Amount), "ERC20转账失败");
        IERC721(erc721Addr).transferFrom(msg.sender, recipient, nftTokenId);
    }

    // 同时转账ERC-20和ERC-1155
    function transferERC20And1155(
        address erc20Addr,
        address erc1155Addr,
        address recipient,
        uint256 erc20Amount,
        uint256 nftId,
        uint256 nftAmount,
        bytes calldata data
    ) external {
        require(IERC20(erc20Addr).transfer(recipient, erc20Amount), "ERC20转账失败");
        IERC1155(erc1155Addr).safeTransferFrom(msg.sender, recipient, nftId, nftAmount, data);
    }
}

调用聚合合约的Ethers.js示例

const { ethers } = require("ethers");

const provider = new ethers.providers.JsonRpcProvider("你的RPC节点地址");
const signer = new ethers.Wallet("你的私钥", provider);

// 部署后的聚合合约地址
const batchTransferAddr = "0x...";
const batchTransferAbi = [
    "function transferERC20And721(address erc20Addr, address erc721Addr, address recipient, uint256 erc20Amount, uint256 nftTokenId)"
];

const batchContract = new ethers.Contract(batchTransferAddr, batchTransferAbi, signer);

// 转账参数
const erc20Addr = "0x...";
const erc721Addr = "0x...";
const recipient = "0x...";
const erc20Amount = ethers.utils.parseUnits("100", 18); // 假设ERC-20是18位小数
const nftTokenId = 123;

async function executeBatchTransfer() {
    const tx = await batchContract.transferERC20And721(
        erc20Addr, erc721Addr, recipient, erc20Amount, nftTokenId
    );
    await tx.wait();
    console.log("批量转账完成,交易哈希:", tx.hash);
}

executeBatchTransfer();

方式2:使用通用多调用合约

借助链上通用的多调用合约(如以太坊主网的Multicall),在单笔交易中执行多个独立的合约调用。

Ethers.js调用Multicall示例

const { ethers } = require("ethers");

const provider = new ethers.providers.JsonRpcProvider("你的RPC节点地址");
const signer = new ethers.Wallet("你的私钥", provider);

// 以太坊主网Multicall合约地址
const multicallAddr = "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696";
const multicallAbi = [
    "function aggregate(tuple(address target, bytes callData)[] calls) returns (uint256 blockNumber, bytes[] returnData)"
];

const multicallContract = new ethers.Contract(multicallAddr, multicallAbi, signer);

// 构建调用数据
const erc20Addr = "0x...";
const erc721Addr = "0x...";
const recipient = "0x...";
const erc20Amount = ethers.utils.parseUnits("100", 18);
const nftTokenId = 123;

// ERC-20 transfer调用数据
const erc20TransferData = new ethers.utils.Interface(["function transfer(address,uint256)"])
    .encodeFunctionData("transfer", [recipient, erc20Amount]);

// ERC-721 transferFrom调用数据
const erc721TransferData = new ethers.utils.Interface(["function transferFrom(address,address,uint256)"])
    .encodeFunctionData("transferFrom", [signer.address, recipient, nftTokenId]);

// 多调用数组
const calls = [
    { target: erc20Addr, callData: erc20TransferData },
    { target: erc721Addr, callData: erc721TransferData }
];

async function executeMulticall() {
    const tx = await multicallContract.aggregate(calls);
    await tx.wait();
    console.log("多调用完成,交易哈希:", tx.hash);
}

executeMulticall();

注意事项

  • NFT转账前,调用者需拥有NFT所有权,或已通过approve/setApprovalForAll获得转账授权。
  • ERC-20转账需确保调用者余额充足,且合约无转账限制。
  • 单笔交易总Gas消耗不能超过区块Gas上限,否则交易会失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:30:51