如何在智能合约中接收和发送 USDT?
How to receive and send USDT in a smart contract?
是否有任何指南或代码可以作为示例来实现智能合约接收和发送 USDT 到其他地址的功能。
感谢您的帮助
代币余额存储在代币合约中(在本例中为 USDT),而不是您的。因此发送代币是一个简单的过程——您只需在代币合约上执行正确的功能即可。请注意,您的合约至少需要保留即将发送的金额,否则交易将恢复。
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);
}
}
但是因为余额存储在外部合约中,你不能仅仅通过执行合约中的函数让用户向你发送代币。请参阅我的 ,该示例显示了如果可能的话如何滥用它(只需将 approve
替换为 transfer
,但逻辑是相同的)。
一些代币标准(例如ERC-1155 or ERC-721)允许在您的合约收到代币时向您的合约发送一个钩子。挂钩函数名称和所需参数在链接文档中。但是token合约是否给你发hook,那要看
- 代币合约的实现(特别是 USDT 没有实现)
- 你的合同(你必须为你想要接收的所有代币标准实现挂钩函数——或者至少是一个通用的
fallback()
,这在某些情况下是可行的)
- 有时也会出现在发件人身上。
你可以要求你的用户批准你的地址花费一些USDT,然后你的合约可以执行USDT合约的transferFrom()
功能(其中“from”是批准你的用户花费他们的代币)。但是,正如链接的其他答案所建议的那样,批准需要在您的合同之外进行。
你也可以有一个链下应用程序来监听代币合约发出的事件日志(在你的例子中是 USDT 合约上的 Transfer()
事件)。事件日志包含转账信息,包括收款人和金额。因此,您的(链下)应用程序只能过滤您的地址是接收者的事件,并在处理事件日志时执行一些操作。
当我使用上面的代码时,出现错误
错误:事务已还原:函数选择器未被识别且没有回退函数
我不知道为什么
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());
});
});
转移方法在松露测试中效果很好,
但是当用安全帽测试合约时,它失败了。
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);
});
是否有任何指南或代码可以作为示例来实现智能合约接收和发送 USDT 到其他地址的功能。
感谢您的帮助
代币余额存储在代币合约中(在本例中为 USDT),而不是您的。因此发送代币是一个简单的过程——您只需在代币合约上执行正确的功能即可。请注意,您的合约至少需要保留即将发送的金额,否则交易将恢复。
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);
}
}
但是因为余额存储在外部合约中,你不能仅仅通过执行合约中的函数让用户向你发送代币。请参阅我的 approve
替换为 transfer
,但逻辑是相同的)。
一些代币标准(例如ERC-1155 or ERC-721)允许在您的合约收到代币时向您的合约发送一个钩子。挂钩函数名称和所需参数在链接文档中。但是token合约是否给你发hook,那要看
- 代币合约的实现(特别是 USDT 没有实现)
- 你的合同(你必须为你想要接收的所有代币标准实现挂钩函数——或者至少是一个通用的
fallback()
,这在某些情况下是可行的) - 有时也会出现在发件人身上。
你可以要求你的用户批准你的地址花费一些USDT,然后你的合约可以执行USDT合约的transferFrom()
功能(其中“from”是批准你的用户花费他们的代币)。但是,正如链接的其他答案所建议的那样,批准需要在您的合同之外进行。
你也可以有一个链下应用程序来监听代币合约发出的事件日志(在你的例子中是 USDT 合约上的 Transfer()
事件)。事件日志包含转账信息,包括收款人和金额。因此,您的(链下)应用程序只能过滤您的地址是接收者的事件,并在处理事件日志时执行一些操作。
当我使用上面的代码时,出现错误
错误:事务已还原:函数选择器未被识别且没有回退函数
我不知道为什么
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());
});
});
转移方法在松露测试中效果很好, 但是当用安全帽测试合约时,它失败了。
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);
});