I’m trying to create a contract that lets people choose to pay for their transactions with either ETH, or another ERC20 Token - one that I’m creating and for now calling “DummyCoin”.
So basically when the user makes a transaction they can choose to pay for it with either ETH or DummyCoin.
Note that DummyCoin is a totally standard ERC20 Token created using OpenZeppelin’s library - it’s basic cookie-cutter stuff, easy-peasy, works perfectly.
I’ve got most of this working thus far:
-When a User selects DummyCoin as their method of payment, they of course first need to grant permission to the Main-Contract to spend DummyCoin on their (the User’s) behalf - and I’ve got that part working.
Here's the MetaMask screen showing the approval process for DummyCoin:
The problem is that when I then call a function from the Main contract, MetaMask opens but this time it does NOT show DummyCoin as the method of payment - it shows ETH as the method of payment - and I don’t understand why, as I think I’ve done everything correctly:
Here’s the code of function that's executing the transaction - note that I’m simply passing in a currencyID
argument to it so it knows which currency the user chose to pay with:
function mintNFT(uint tokenID, uint numTokensRequested, uint8 currencyID) public payable whenNotPaused {
if(currencyID == 1) {
// Paying with ETH:
require(msg.value >= (basePriceInETH * numTokensRequested), "'mintNFT()' ERROR: INSUFFICIENT amount of ETH sent!");
}
else {
// Paying with DummyCoin:
require(msg.value >= (basePriceInDummies * numTokensRequested), "'mintNFT()' ERROR: INSUFFICIENT amount of DUMMY sent!");
dummyCoinContract.transferFrom(msg.sender, address(this), basePriceInDummies * numTokensRequested);
}
}
That last line -> dummyCoinContract.transferFrom(...)
- that's the one that's supposed to be triggering the DummyCoin transaction.
I've been researching this for a while and have seen other versions, where it's suggested to use IERC20
in the code:
IERC20(dummyCoinContractAddress).transferFrom(msg.sender, address(this), basePriceInDummies * numTokensRequested);
But that doesn't work either - MetaMask still shows ETH as the method of payment.
I guess the last piece of this is that I'm importing DummyCoin.sol
into the main contract:
import "./DummyCoin.sol";
I then create a reference variable to the deployed Dummy-Contract:
DummyCoin public dummyCoinContract;
And then assign it a value in the main-contract's constructor
:
dummyCoinContract = DummyCoin(dummyCoinContractAddress);
Where-in dummyCoinContractAddress
gets passed into the main contract by the deployment code of both contracts:
(I'm using HARDHAT + Ethers.js)
async function main () {
// DEPLOYING the ERC-20 Contract first, then passing it's ADDRESS to the MAIN-Contract:
// 1. DummyCoin Deployment:
const DummyCoinContract = await ethers.getContractFactory("DummyCoin");
const DummyCoinContractInstance = await DummyCoinContract.deploy();
await DummyCoinContractInstance.deployed();
console.log(">FINISHED!\n\n-'DummyCoinContractInstance' deployed to:", DummyCoinContractInstance.address, "\n\n.");
// 2. Main-Contract Deployment:
const MinterContract = await ethers.getContractFactory("Minter");
const MinterContractInstance = await MinterContract.deploy(DummyCoinContractInstance.address);
await MinterContractInstance.deployed();
console.log(">FINISHED!\n\n-'MinterContractInstance' deployed to:", MinterContractInstance.address, "\n\n.");
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
So, any idea what's going on here and how I might trouble-shoot this?
require
statement altogether to just take it out of the mix entirely - made no difference. The same thing keeps happening: the Tx defaults to using ETH...Approval
of my Token works (see screenshot), so thesending
(ortransferring
) of the coin should works as well.