In the following minimum viable test I'm failing to mock the allowance so that the ReceiverContract can transfer ERC20 tokens. The expected use-case would be a user (=externally-owned account) interacts with the ReceiverContract
- if conditions are passed the contract transfers ERC20 tokens from the user wallet to the contract itself.
In this example with DAI ERC20 tokens the test fails with Dai/insufficient-allowance
(using the mainnet fork mechanism of Forge).
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "forge-std/console.sol";
import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
using stdStorage for StdStorage;
contract ReceiverContract {
address public contractAddress;
constructor() {
contractAddress = address(this);
}
function sendErc20ToContract(address _tokenAddress, uint256 amount) public {
IERC20 token = IERC20(_tokenAddress);
require(token.balanceOf(msg.sender) >= amount);
require(token.allowance(msg.sender, contractAddress) >= amount);
token.transferFrom(msg.sender, contractAddress, amount);
}
}
contract TestReceiverContract is Test {
ReceiverContract testReceiver;
function setUp() public {
testReceiver = new ReceiverContract();
}
function addErc20TokenBalance(address who, address token, uint256 amount) internal {
deal(address(token), who, amount);
vm.prank(msg.sender);
IERC20(token).approve(testReceiver.contractAddress(), amount);
uint256 allowanceAmount = IERC20(token).allowance(msg.sender, testReceiver.contractAddress());
emit log_named_uint("allowance amount from external ERC20", allowanceAmount);
}
function testTransfer() public {
address daiTokenAddress = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
uint16 amount = 2342;
addErc20TokenBalance(msg.sender, daiTokenAddress, amount);
vm.prank(msg.sender);
testReceiver.sendErc20ToContract(daiTokenAddress, amount);
}
}
What I've tried:
- setting the value in the ERC20 allowance mapping "manually" using
stdstore.target(token).sig(IERC20(token).allowance.selector
-> didn't work - changing the allowance to different addresses, changing msg.sender in all the places, etc
Is there a bug in my test or is the code conceptually correct? Any hints highly appreciated!