Is there any guide or code that can serve as an example to implement the functionality where a smart contract receives and sends USDT to other addresses.
I appreciate your help
Is there any guide or code that can serve as an example to implement the functionality where a smart contract receives and sends USDT to other addresses.
I appreciate your help
The token balance is stored in the token contract (in this case USDT), not in yours. So sending tokens is a straightforward process - you just execute the correct function on the token contract. Mind that your contract needs to hold at least the amount it's about to send, otherwise the transaction would revert.
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);
}
}
But because the balance is stored in the external contract, you can't just make a user send you tokens by executing a function in your contract. See my other answer that shows an example how this could be misused if it were possible (just replace approve
to transfer
, but the logic is the same).
Some token standards (such as ERC-1155 or ERC-721) allow sending a hook to your contract when your contract receives tokens. The hook function names and required parameters are in the linked documents. But whether the token contract sends you a hook, that depends on
fallback()
which would work in some cases)You can ask your users to approve some USDT to be spent by your address, and then your contract can execute the transferFrom()
function of the USDT contract (where the "from" is the user who approved you to spend their tokens). However, the approval needs to be done outside of your contract, as the linked other answer suggests.
You can also have an off-chain app that listens to event logs emitted by the token contract (in your case Transfer()
event on the USDT contract). The event logs contain the transfer information including the receiver and amount. So your (off-chain) app can filter only events where your address is the receiver, and perform some action when it handles the event log.
/**
and ending with */
- or replace it with single-line comments like I just did in the question. –
Pretrice transfer()
from your contract only if you're transferring tokens from your contract address. If you want to transfer tokens from the user address, they need to approve()
your contract as spender first, and then you can use transferFrom()
. –
Pretrice transferFrom()
is sufficient on the side of your contract. However, before executing this function, the subscriber
also needs to execute approve(yourContract, amount)
on the token
contract directly (not through your contract as an intemediary). –
Pretrice token
variable is of type IERC20
that does not define the safeTransferFrom()
function... You need to change your token
variable to type safeERC20
that defines this function. –
Pretrice pay
function you mean, however the user needs to invoke the approve()
function directly - so for example through your UI. Not through your contract. –
Pretrice token.approve()
from your smart contract - only from the UI. In other words, the approve()
function needs to be executed by the user directly, not through your contract. –
Pretrice When I use the code above, I got an error
Error: Transaction reverted: function selector was not recognized and there's no fallback function
and I have no idea why
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);
}
}
I deployed the USDT(TetherToken.sol) to my ethereum dev node.
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());
});
});
The transfer method works pretty good with truffle test, but when test the contract with hardhat, it failed.
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);
});
© 2022 - 2024 — McMap. All rights reserved.