1

Can we have a smart contract that when an amount is deposited into it, it will automatically transfer it to the owner's wallet address? I mean, as soon as the amount is received, the smart contract will automatically transfer and we don't have to call the method manually?

If it is possible to transfer automatically to one address, is it possible to divide the received amount and transfer it automatically to two addresses?

If this is possible, what is the gas fee and who pays?

Edit: I need this for USDT token in BSC or TRON.

3 Answers 3

2

When you send ETH to a smart contract, you're actually calling its receive() function (https://docs.soliditylang.org/en/v0.8.17/contracts.html#receive-ether-function). If that function contains logic, it gets executed upon sending ETH to the smart contract, so yes, making a contract forward ETH that is sent to it (or do anything with it, actually, including dividing it and sending it to multiple addresses) is perfectly possible. In that case, the user sending the ETH in the first place is the one paying for the gas (smart contracts can't pay gas on their own). Below is a very simple example contract that forwards any ETH sent to it to the address that deployed it, and reverts the transaction ( = sends the ETH back to the sender) if for some reason it can't.

contract Forwarder {
    address owner;
    constructor() {
        owner = msg.sender;
    }
    receive() external payable {
        (bool s,) = payable(owner).call{value: msg.value}(new bytes(0));
        require(s);
    }
}

Note that it works that way only for ETH ( when i say "ETH" i mean the native token of the chain you're on, so ETH on ethereum mainnet, but BNB on the BSC, MATIC on polygon, etc..). ERC20 tokens work differently, and you can't do that with them.

EDIT : As Safi explained, USDT (or any ERC20 tokens) transfer are different in nature than ETH transfers, and therefore can't be treated the same way. Basically, sending ETH calls your contract, and sending USDT doesnt. From there, you have two options. If you have a frontend people are going to use to send you USDT, you can do :

// The IERC20 interface, to allow your contract to interact with ERC20 contracts. 
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
contract Forwarder {
    address owner;
    address USDTContract =....; //  Well, the usdt contract address
    constructor() {
        owner = msg.sender;
    }
    // To receive ETH, people just need to send ETH to the address as they would do to any address, just clicking metamask's send button. 
    receive() external payable {
        (bool s,) = payable(owner).call{value: msg.value}(new bytes(0));
        require(s);
    }
    /* For USDT, the control flow is reversed, since an address sending ERC20 tokens to your contract
     doesnt trigger any kind of execution, if we need to act upon receiving ERC20s, 
we instead take the USDT from the users wallet and then do stuff with it. 
In that case, the user would need to call this function, they can't do that by just using mm's send button. */
    function transferUsdtToOwner(uint amount) external {
        IERC20(USDTAddress).transferFrom(msg.sender, owner, amount);
    }
}

Your other option is to have the users send USDT to your contract, and then transfer it yourself to your address (you can let the USDT accumulate inside the contract and just do it once in a while)

// User sends USDT to the contract and then you call that function 
function withdrawUSDT() external {
    IERC20(USDTAddress).transfer(owner, IERC20(USDTAddress).balanceOf(address(this));
}

If you really don't want to do it yourself, you could also incentivize external actors to do it for you, for example by giving them a small share of what's in there if they do :

function withdrawUSDT() external {
    IERC20(USDTAddress).transfer(msg.sender, IERC20(USDTAddress).balanceOf(address(this)) / 100); // The caller would get 1%, you'd get the rest
    IERC20(USDTAddress).transfer(owner, IERC20(USDTAddress).balanceOf(address(this)));
}
6
  • Great thanks, I need this for USDT token in BSC network, what should I do for it? @foxxxey
    – softweng
    Commented Jan 15, 2023 at 5:17
  • Can we have a contract similar to this for USDT? @foxxxey
    – softweng
    Commented Jan 15, 2023 at 6:54
  • Unfortunately no. Edited my answer for more details
    – Foxxxey
    Commented Jan 15, 2023 at 19:19
  • Thanks.@foxxxey
    – softweng
    Commented Jan 15, 2023 at 20:36
  • 1
    Complete project here: github.com/farirat/solidity-forwarder-wallet
    – zfou
    Commented Jan 24, 2023 at 15:36
0

@Foxxxe and @Safi are right, yet if this is your killer feature could be worth investigating this alternative path.

The ERC777 standard allows ti implements a tokensReceived() hook that will trigger when you receive the tokens. It means that you can receive the tokens and make with them whatever you want.

The point here is how we convert our ERC20 to ERC777 to be able to implement this feature??

In my case, I am using the SuperTokens of Superfluid ,the Supertokens are ERC777 and ERC20 compatible and along all of the stream features they allow you to convert between erc20<-->supertoken(erc777). The flow should be in a schematic view then like this:

  1. In frontend user converts erc20 to erc777 calling superToken.upgrade()
  2. In frontend the user calls the send() functionality of the eC777
  3. The contract receives in the tokensReceived() the ERC777 tokens, then call superToken.downgrade() and has already the ERC20 available.

I know, it is not the straightest way forward, but is feasible, in the use cases I've implemented, it works perfectly.

0

This only works for native token deposit as described by @Foxxxey. While someone transfer USDT the wallet is actually interacting with the USDT contract not with the receiving smart contract so receiving smart contract does not know about this.

The only way for this is to use service like node js to listen the transfer Event of USDT and if the receiver is your contract then you can call some function using front end to send USDT to the owner. And of course this will require gas fee from your wallet. It is same like manually interacting with your contract.

2
  • Great thanks, I'm a little confused, This is how I found out that if the destination address is the address of the smart contract, when we send the native token, its receive function is executed, but if another token is like USDT, the receive function of the USDT contract is executed, is this correct? Can the USDT contract be override similarly to @foxxxey Forwarder contract?
    – softweng
    Commented Jan 15, 2023 at 6:50
  • Receive function is a fallback function meaning if none of the other methods are called the default method called is the receive. In case of any token the transfer or transferFrom function is called whenever there is any transfer of the token so, you can not override that in any ERC20 token smart contract. If you define receive fallback function in your token ERC20 smart contract then your ERC20 contract will be able to receive ether, if there is no receive fallback function then your ERC20 smart contract can not receive ether.
    – Safi
    Commented Jan 15, 2023 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.