I'm pretty new to solidity and struggling with some pretty simple stuff so I was hoping somebody would be able to help me out. Basically, I want to be able to send an existing ERC20 token (ie: USDT) to a contract. I think I understand that you have to approve the funds then initiate the transfer.

function fund(address sender, uint256 amount) public {
        IERC20(i_assetAddress).approve(address(this), amount);
        IERC20(i_assetAddress).transferFrom(sender, address(this), amount);
        s_funders[sender] = amount;

I set the address to the USDT contract address: 0xC2C527C0CACF457746Bd31B2a698Fe89de2b6d49 and ensured that my deploying account had enough funds in it to make the transfer. No matter which ways I tweak it I am always getting the same error on the transaction when I run the fund() function: Fail with error 'ERC20: transfer amount exceeds balance'. I know I'm definitely pretty off-base so hopefully someone can help me figure this out. Here's the relevant typescript code in my testing function:

describe("FundMe Staging Tests", function () {
          let accounts: SignerWithAddress[], deployer: SignerWithAddress, user: SignerWithAddress
          const fundValue: BigNumber = ethers.utils.parseEther("0.00001")
          let fundMeContract: FundMe, fundMe: FundMe
          const chainId = network.config.chainId || 31337

          beforeEach(async () => {
              accounts = await ethers.getSigners()
              deployer = accounts[0]

              fundMeContract = await ethers.getContract("FundMe", deployer)

              fundMe = fundMeContract.connect(deployer)

          it("correctly adds a funder", async function () {
              fundMe = fundMeContract.connect(deployer)

              await fundMe.fund(deployer.address, fundValue)
              const fundAmount = await FundMe.getFundAmount(deployer.address)

              console.log(`fundAmount: ${fundAmount} | fundValue: ${fundValue}`)
              assert.equal(fundAmount.toString(), fundValue.toString())
  • The deployer has to approve USDT in the amount of fundValue to the fundMeContract. In the contract you're having fundMeContract approve itself. In your testing, you need to have the deployer approve
    – Ryan Sea
    Aug 31, 2022 at 19:55
  • Ok, I think I get that now but I can't figure out the best way to actually get the token using ethers. I tried doing const assetTokenContract = ethers.getContractAt( networkConfig[chainId].assetName!, networkConfig[chainId].assetAddress! ) assetToken = (await assetTokenContract).connect(deployer) with assetName as "TetherToken" and assetAddress as the token address above, but I'm getting the error "Error: cannot find artifact "TetherToken" so I guess that isn't the actual name of the token contract.
    – l1nkm4rine
    Aug 31, 2022 at 20:07
  • So is there a better way to access the existing token contract?
    – l1nkm4rine
    Aug 31, 2022 at 20:10
  • getContractAt is a hardhat command for local contracts. const tokenContract = new ethers.Contract(address, abi, signer) is how you typically get a contract to call. You need to find or make an ERC-20 ABI. In general it'll probably be easier if you create your own token contracts for testing
    – Ryan Sea
    Aug 31, 2022 at 22:43


Your Answer

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