簡體   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