繁体   English   中英

如何在智能合约中接收和发送 USDT?

[英]How to receive and send USDT in a smart contract?

是否有任何指南或代码可以作为示例来实现智能合约接收 USDT 并将其发送到其他地址的功能。

我感谢您的帮助

代币余额存储在代币合约(在本例中为 USDT)中,而不是您的。 所以发送代币是一个简单的过程——你只需在代币合约上执行正确的 function 即可。 请注意,您的合约至少需要保留即将发送的金额,否则交易将恢复。

pragma solidity ^0.8;

interface IERC20 {
    function transfer(address _to, uint256 _value) external returns (bool);
    
    // don't need to define other functions, only using `transfer()` in this case
}

contract MyContract {
    // Do not use in production
    // This function can be executed by anyone
    function sendUSDT(address _to, uint256 _amount) external {
         // This is the mainnet USDT contract address
         // Using on other networks (rinkeby, local, ...) would fail
         //  - there's no contract on this address on other networks
        IERC20 usdt = IERC20(address(0xdAC17F958D2ee523a2206206994597C13D831ec7));
        
        // transfers USDT that belong to your contract to the specified address
        usdt.transfer(_to, _amount);
    }
}

但是由于余额存储在外部合约中,你不能通过在你的合约中执行 function 来让用户向你发送代币。 请参阅我的另一个答案,该答案显示了一个示例,如果可能的话,如何滥用它(只需将approve替换为transfer ,但逻辑是相同的)。

一些代币标准(例如ERC-1155ERC-721 )允许在您的合约收到代币时向您的合约发送挂钩。 挂钩 function 名称和所需参数在链接文档中。 但是代币合约是否给你发送了一个钩子,这取决于

  • 代币合约的实施(特别是 USDT 没有实施)
  • 您的合同(对于您想要接收的所有令牌标准,您必须实施钩子 function - 或者至少在某些情况下可以使用通用的fallback()
  • 有时也在发件人身上。

您可以要求您的用户批准您的地址使用一些 USDT,然后您的合约可以执行 USDT 合约的transferFrom() function(其中“from”是批准您使用其代币的用户)。 但是,正如链接的其他答案所暗示的那样,批准需要在您的合同之外完成。

您还可以拥有一个链下应用程序来侦听令牌合约发出的事件日志(在您的例子中是 USDT 合约上的Transfer()事件)。 事件日志包含转账信息,包括接收方和金额。 因此,您的(链下)应用程序只能过滤您的地址是接收者的事件,并在处理事件日志时执行一些操作。

当我使用上面的代码时,我得到了一个错误

错误:事务已恢复:function 选择器未被识别并且没有后备 function

我不知道为什么

pragma solidity ^0.8.0;

import "hardhat/console.sol";

interface IERC20 {
    function transfer(address _to, uint256 _value) external returns (bool);
}

contract Greeter {

  string greeting;

  constructor(string memory _greeting) {
    console.log("Deploying a Greeter with greeting:", _greeting);
    greeting = _greeting;
  }

  function sendUSDT(address _to, uint256 _amount) external {
         // This is the mainnet USDT contract address
         // Using on other networks (rinkeby, local, ...) would fail
         //  - there's no contract on this address on other networks
    IERC20 usdt = IERC20(address(0x5FbDB2315678afecb367f032d93F642f64180aa3));
        
        // transfers USDT that belong to your contract to the specified address
    usdt.transfer(_to, _amount);
  }
}

我将 USDT(TetherToken.sol) 部署到我的以太坊开发节点。

const TetherToken = artifacts.require("TetherToken"); 

contract('TetherToken',accounts => {
    before(async () => {
        let tetherToken = await TetherToken.at("0x5FbDB2315678afecb367f032d93F642f64180aa3");
        //this address is the same as signers[1].address in hardhat
        tetherToken.transfer("0x70997970c51812dc3a010c7d01b50e0d17dc79c8", web3.utils.toBN("1000000000"));
        let b = await tetherToken.balanceOf("0x70997970c51812dc3a010c7d01b50e0d17dc79c8")
        console.log(b.toString());
    });

});

transfer 方法在 truffle 测试中效果很好,但是在使用安全帽测试合约时,它失败了。

const { ethers, upgrades } = require("hardhat");

async function main() {

  const signers = await ethers.getSigners();

  const Greeter = await hre.ethers.getContractFactory("Greeter");
  const greeter = await Greeter.deploy("Hello, Hardhat!");

  await greeter.deployed();

  let overrides = {

    // The maximum units of gas for the transaction to use
    gasLimit: 2100000,

    // The price (in wei) per unit of gas
    gasPrice: ethers.utils.parseUnits('8.0', 'gwei')

  };

  await greeter.connect(signers[1]).sendUSDT(signers[2].address, ethers.utils.parseUnits('100.00', 'mwei'), overrides);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM