First I'm deploying Cafe contract and get deployedId from it and then deploy CAFToken contract with deployedId of cafe contract. I've also added deploy script and test case, I guess everything is going correctly but somehow getting ERC20: insufficient allowance error while calling sendToken function. May be I miss something can you please guide me on this.
Cafe Contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract Cafe is Ownable {
address public cafeToken;
function setCafeToken(address _cafeToken) public onlyOwner {
cafeToken = _cafeToken;
}
//send token to other receipent
function sendToken(address _receiverAddress, uint _tokenAmount) public {
require(_tokenAmount > 0, "token should be more than 0");
IERC20(cafeToken).transferFrom(
address(this),
_receiverAddress,
_tokenAmount
);
}
// Get rewards of user has 10 or more than 10 tokens
function getRewards() public returns (bool) {
require(
IERC20(cafeToken).balanceOf(msg.sender) >= 10,
"Not enough token for rewards!"
);
IERC20(cafeToken).transferFrom(msg.sender, address(this), 10);
return true;
}
}
Cafe Token Contract (ERC20 token)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract CAFToken is ERC20 {
constructor(
uint256 initialSupply,
address cafeAddress
) ERC20("Cafe", "CAF") {
_mint(cafeAddress, initialSupply); // mint intial supply to cafe contract
}
}
Deploy script:
const { ethers } = require("hardhat");
const hre = require("hardhat");
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
async function main() {
const Cafe = await hre.ethers.getContractFactory("Cafe");
const cafeContract = await Cafe.deploy();
await cafeContract.deployed();
const Token = await hre.ethers.getContractFactory("CAFToken");
const cafeToken = await Token.deploy(
ethers.utils.parseEther("100000"),
cafeContract.address
);
await cafeToken.deployed();
console.log(`deployed to cafe contract ${cafeContract.address}`);
console.log("Token deployed to:", cafeToken.address);
/////////////// Verification ////////////////////
console.log("Wait for verifying...");
await delay(5000);
// verify cafe contract
await await hre.run("verify:verify", {
address: cafeContract.address,
constructorArguments: [],
contract: "contracts/Cafe.sol:Cafe",
});
// verify cafe token
await await hre.run("verify:verify", {
address: cafeToken.address,
constructorArguments: [
ethers.utils.parseEther("100000"),
cafeContract.address,
],
contract: "contracts/CAFToken.sol:CAFToken",
});
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Test case:
const { expect, assert } = require("chai");
const { ethers } = require("hardhat");
describe("Initial Test case", () => {
let cafeContract, cafeToken, accounts;
beforeEach(async () => {
const Cafe = await ethers.getContractFactory("Cafe");
cafeContract = await Cafe.deploy();
await cafeContract.deployed();
const Token = await ethers.getContractFactory("CAFToken");
cafeToken = await Token.deploy(
ethers.utils.parseEther("100000"),
cafeContract.address
);
await cafeToken.deployed();
accounts = await ethers.getSigners();
});
describe("first", async () => {
it("check", async () => {
// Before transaction initial logs and balances
console.log("Balance", await cafeToken.totalSupply());
// Send token to another address
await cafeContract.setCafeToken(cafeToken.address);
await cafeToken.allowance(cafeToken.address, cafeContract.address);
// Approve transaction
await cafeToken.approve(
cafeContract.address,
ethers.utils.parseEther("10000")
);
await cafeContract.sendToken(
accounts[1].address,
ethers.utils.parseEther("10")
);
// await token.transfer();
console.log("--after transaction--");
const balance11 = await cafeToken.balanceOf(accounts[1].address);
console.log("Balance-11", balance11.toString());
assert.equal(balance11.toString(), ethers.utils.parseEther("10"));
});
});
});