I want to make a smart contract that burns tokens that are transferred to it.
My token contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract GameToken is ERC20, ERC20Burnable, Ownable {
uint256 public totalBurned;
constructor() ERC20("Invader Pixel Token", "IPX") Ownable(msg.sender) {
_mint(msg.sender, 0 * 10 ** 18);
}
function mintBySwapContract(address to, uint256 amount) external {
require(msg.sender == swapContract, "Not authorized to mint");
_mint(to, amount);
}
function mintByOwner(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}
function burn(uint256 amount) public override {
super.burn(amount);
totalBurned += amount;
}
function burnFrom(address account, uint256 amount) public override {
super.burnFrom(account, amount);
totalBurned += amount;
}
address public swapContract;
function setSwapContract(address _swapContract) external onlyOwner {
swapContract = _swapContract;
}
}
My contract which will burn them
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./GameToken.sol";
contract BurnContract {
GameToken public gameToken;
struct BurnRecord {
address sender;
uint256 tokenAmount;
}
BurnRecord[] public burnRecords;
constructor(GameToken _gameToken) {
gameToken = _gameToken;
}
fallback() external {
uint256 tokensToBurn = gameToken.balanceOf(address(this));
require(tokensToBurn > 0, "No tokens to burn");
gameToken.burn(tokensToBurn);
burnRecords.push(
BurnRecord({
sender: msg.sender,
tokenAmount: tokensToBurn
})
);
}
function getBurnRecordsByAddress(
address _address
) external view returns (uint256 totalTokensBurnt) {
uint256 tokensBurntByAddress = 0;
for (uint256 i = 0; i < burnRecords.length; i++) {
if (burnRecords[i].sender == _address) {
tokensBurntByAddress += burnRecords[i].tokenAmount;
}
}
return tokensBurntByAddress;
}
}
The tokens are sent to the contract but they arent being burned. I dont know what's causing the problem. I can view tokens in this contract in explorer. tokens gets reduced from sender but the burn doesnt happen. Is the error with fallback function?
My nextjs where transfer function is used
const tokenContract = new ethers.Contract(gameTokenAddress, gameTokenABI, signer);
const tokenAmount = ethers.utils.parseEther(burnAmount.toString());
const gasLimit = ethers.utils.parseUnits('10', 'gwei');
const transferTx = await tokenContract.transfer(burnContractAddress, tokenAmount, {
gasLimit: gasLimit,
});
const receipt = await transferTx.wait();
setHash(await receipt.transactionHash)
You cannot have a fallback when tokens are transferred to your contract. The fallback function you have there will only be called if someone transfers ETH to the contract. In short there is not way to do automatically with and off-the-self ERC20.
If you deploy the ERC20 yourself and you want to to be automatic then you have to add that callback to the ERC20 to call your
BurnContract
but that is a customisation that you will have to add.This is because for you contract to do something someone has to send a transaction to it and a token transfer is a transaction on the token contract and not the recipient address/contract whereas the ETH transfer is a transaction to the receiver address which is why you can have the callback there. In short you
BurnContract
does not know that someone send it tokens unless someone calls it in which case it can check its own balance.