USDT = new ethers.Contract(
    mywallet // wallet is fine, can call send transaction  normally to other signers and total supply from erc20, balance returns 10000 ETH, 
let tc = await tokenB.totalSupply();
let value = await mywallet.getBalance();
console.log(`USDT supply:${tc.toString()} ETH balance: ${ethers.utils.formatEther(value)}`);
const tsc = await USDT.transfer(mywallet.address, 0);

I know this question has been rehashed many times however most errors seem to be with either a faulty framework or insufficient funds, none of which seem to be the case here. This is a rinkeby hardhat testnet fork

  • What's the contract address? Do you have a failed transaction hash? Some libraries display that generic error message when the transaction fails. For the real error you have to check the transaction receipt and/or trace the transaction.
    – Ismael
    Aug 11, 2021 at 4:58
  • rinkeby.etherscan.io/tx/…. Doing some research, the issue seems to be with the sender value however, as you can see, it doesn't seem to be the case.
    – alex234
    Aug 12, 2021 at 17:33

1 Answer 1


If you search the contract source for the error message reported in the transaction

ERC20: transfer amount exceeds balance

It is in the _transfer function

function _transfer(address sender, address recipient, uint256 amount) internal {
    require(sender != address(0), "ERC20: transfer from the zero address");
    require(recipient != address(0), "ERC20: transfer to the zero address");

    _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
    _balances[recipient] = _balances[recipient].add(amount);
    emit Transfer(sender, recipient, amount);

The sender is trying to send more than the available balance.

Looking at the sender ERC20 history they never received the tokens they are trying to send (0x3b00ef435fa4fcff5c209a37d1f3dcff37c705ad).

  • Wait, but didn't the open zeppelin docs mention that there were only 2 arguments?docs.openzeppelin.com/contracts/2.x/api/token/erc20, reciever and amount? So I would assume that the token address must be the first argument then?
    – alex234
    Aug 15, 2021 at 13:21
  • @alex234 I'm quoting is the internal function ` _transfer` (with an underscore), it is not the public one. The names are quite clear: sender (the account that owns the tokens), recipient (the account that will receive the tokens), amount (the token amount).
    – Ismael
    Aug 15, 2021 at 15:32
  • Thanks a lot for your time. But if I'm understanding this correctly now, how do I get tokens from an established contract if I have none to start with?
    – alex234
    Aug 15, 2021 at 17:45
  • @alex234 I got the error from the transaction link in the comment: Fail with error 'ERC20: transfer amount exceeds balance'. Then searched the contract code on etherscan for that string and found in the internal _transfer function. It shows where the error comes from: the sender is trying to transfer funds that it doesn't have so it will never work. This contract has a mint function that seems to allow minting yourself some tokens. In any case it is a test network so you can deploy your own copy of the contract if that doesn't work.
    – Ismael
    Aug 15, 2021 at 17:51
  • Thank you for the explanation, I already minted some new tokens for myself and thank you for taking time out of your day to assist me.
    – alex234
    Aug 16, 2021 at 8:38

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.