I'm getting the following error when trying to transfer an IERC20 token from an account to a contract:
Error: Returned error: VM Exception while processing transaction: revert ds-math-sub-underflow -- Reason given: ds-math-sub-underflow.
(it fails at the pair.transferFrom
line).
But if I try to transfer from account to account it works, it only fails when I try to transfer from an account to the contract:
const PAIR = "0x397ff1542f962076d0bfe58ea045ffa2d347aca0";
const PAIR_WHALE = "0x7ac049b7d78bc930e463709ec5e77855a5dca4c4";
const pair = await IERC20.at(PAIR);
const myContract = await MyContract.deployed();
// const addr = accounts[0]; // Works!!!
const addr = myContract.address; // Fails with error above
let whaleBal = await pair.balanceOf(PAIR_WHALE);
await pair.approve(addr, whaleBal, { from: PAIR_WHALE });
await pair.transferFrom(PAIR_WHALE, addr, whaleBal);
My setup for running this:
PAIR
is the address from the USDC-WETH
pair from sushiswapPAIR_WHALE
unlocked via ganachetruffle test
pair.approve(addr, whaleBal, { from: PAIR_WHALE });
On this line, the PAIR_WHALE
(transaction sender) approves the contract address (the value of addr
) to spend their tokens.
pair.transferFrom(PAIR_WHALE, addr, whaleBal)
But on this line, the accounts[0]
(the default transaction sender) is trying to spend the PAIR_WHALE
's tokens. But the accounts[0]
is not approved to do this.
When you assigned the value of accounts[0]
to addr
in the commented line, the PAIR_WHALE
effectively approved the accounts[0]
to spend their tokens, which caused the transferFrom()
function to pass.
You cannot send a transaction on behalf of the contract address, as its private key is unknown.
But if you want to transfer the PAIR_WHALE
tokens to the contract address, you can simply invoke the transfer()
function from the PAIR_WHALE
address.
// transfers `whaleBal` of `pair` tokens
// from the `PAIR_WHALE` address
// to the `myContract.address` address
pair.transfer(myContract.address, whaleBal, {from: PAIR_WHALE});