I have write a simple smart contract ERC1155 allow ppl to mint NFTs and everything was ok except for the mint function. The transaction was ok but when i checked the balanceOf it always returned 0 even after minting
This is my token contract code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155SupplyUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract TopSevenPlayer is Initializable, ERC1155Upgradeable, AccessControlUpgradeable, PausableUpgradeable, ERC1155BurnableUpgradeable, ERC1155SupplyUpgradeable, UUPSUpgradeable {
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize() initializer public {
__ERC1155_init("https://staging-topseven.web.app/meta/{id}");
__AccessControl_init();
__Pausable_init();
__ERC1155Burnable_init();
__ERC1155Supply_init();
__UUPSUpgradeable_init();
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(PAUSER_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
_grantRole(UPGRADER_ROLE, msg.sender);
}
function pause() public onlyRole(PAUSER_ROLE) {
_pause();
}
function unpause() public onlyRole(PAUSER_ROLE) {
_unpause();
}
function mint(address account, uint256 id, uint256 amount, bytes memory data)
public
onlyRole(MINTER_ROLE)
{
_mint(account, id, amount, data);
}
function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data)
public
onlyRole(MINTER_ROLE)
{
_mintBatch(to, ids, amounts, data);
}
function _beforeTokenTransfer(address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data)
internal
whenNotPaused
override(ERC1155Upgradeable, ERC1155SupplyUpgradeable)
{
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
}
function _authorizeUpgrade(address newImplementation)
internal
onlyRole(UPGRADER_ROLE)
override
{}
// The following functions are overrides required by Solidity.
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC1155Upgradeable, AccessControlUpgradeable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Minter contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import '@openzeppelin/contracts/access/Ownable.sol';
import './TopSevenPlayer.sol';
contract PublicMinter is Ownable {
TopSevenPlayer private token;
address private contractAddress;
bool public IS_FREE_MINT = true;
uint256 public BASE_PRICE = 500000000 gwei;
event Log(uint256 amount, uint256 gas);
event ResultsFromCall(bool success, bytes data);
constructor() {}
receive() external payable {}
fallback() external payable {}
/**
***************************
Public
***************************
*/
function mint(
address to,
uint256 tokenId
) public payable {
if (!IS_FREE_MINT) {
require(msg.value >= BASE_PRICE, "Need to send more MATIC");
}
token.mint(to, tokenId, 1, '');
emit Log(msg.value, gasleft());
}
/**
***************************
Customization for the contract
***************************
*/
function setContractAddress(address payable _address) external onlyOwner {
contractAddress = _address;
token = TopSevenPlayer(_address);
}
function withdraw() external onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, 'No amount left to withdraw');
(bool success, bytes memory data) = (msg.sender).call{value: balance}('');
require(success, 'Withdrawal failed');
emit ResultsFromCall(success, data);
}
function setIsFreeMint(bool _isFreeMint) public onlyOwner {
IS_FREE_MINT = _isFreeMint;
}
function setBasePrice(uint256 _basePrice) public onlyOwner {
BASE_PRICE = _basePrice;
}
}
the test run ok as well:
token contract test
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { expect } = require('chai');
const { ethers, upgrades } = require('hardhat');
describe('TopSevenPlayer', function () {
// We define a fixture to reuse the same setup in every test.
// We use loadFixture to run this setup once, snapshot that state,
// and reset Hardhat Network to that snapshopt in every test.
async function deployTopSevenPlayerFixture() {
const [owner, otherAccount] = await ethers.getSigners();
const TopSevenPlayer = await ethers.getContractFactory('TopSevenPlayer');
const token = await upgrades.deployProxy(TopSevenPlayer);
await token.deployed();
return { token, owner, otherAccount };
}
describe('Deployment', function () {
it('Should set the right owner', async function () {
const { token, owner } = await loadFixture(deployTopSevenPlayerFixture);
const isAdmin = await token.hasRole(
await token.DEFAULT_ADMIN_ROLE(),
owner.address
);
expect(isAdmin).to.equal(true);
});
it('Should get correct balance', async function () {
const { token } = await loadFixture(deployTopSevenPlayerFixture);
expect(await ethers.provider.getBalance(token.address)).to.equal(0);
});
});
});
minter contract test
const { assert } = require('chai');
require('chai').use(require('chai-as-promised')).should();
const { ethers, upgrades } = require('hardhat');
const BASE_PRICE = 1e18;
describe('PublicMinter', function () {
let accounts, token, minter;
beforeEach(async function () {
accounts = await ethers.getSigners();
const TopSevenPlayer = await ethers.getContractFactory('TopSevenPlayer');
const PublicMinter = await ethers.getContractFactory('PublicMinter');
token = await upgrades.deployProxy(TopSevenPlayer);
minter = await PublicMinter.deploy();
await minter.setContractAddress(token.address);
await token.grantRole(await token.MINTER_ROLE(), minter.address);
});
describe('deployment', async () => {
it('deploys successfully', async () => {
const tokenAddress = token.address;
assert.notEqual(tokenAddress, 0x0);
assert.notEqual(tokenAddress, '');
assert.notEqual(tokenAddress, null);
assert.notEqual(tokenAddress, undefined);
const minterAddress = minter.address;
assert.notEqual(minterAddress, 0x0);
assert.notEqual(minterAddress, '');
assert.notEqual(minterAddress, null);
assert.notEqual(minterAddress, undefined);
});
});
describe('minting', async () => {
it('free mint successfully', async () => {
const account = accounts[0];
await minter.mint(account.address, 1);
const totalSupply = await token.totalSupply(1);
assert.equal(totalSupply, 1);
const balance = await token.balanceOf(account.address, 1);
assert.equal(balance, 1);
});
it('free mint failed', async () => {
const account = accounts[0];
await minter.setIsFreeMint(false);
minter
.mint(account.address, 1)
.should.be.rejectedWith('Need to send more MATIC');
});
it('mint successfully', async () => {
const account = accounts[0];
await minter.setIsFreeMint(false);
const value = BASE_PRICE.toString();
await minter.mint(account.address, 1, {
from: account.address,
value,
});
const totalSupply = await token.totalSupply(1);
assert.equal(totalSupply, 1);
const balance = await token.balanceOf(account.address, 1);
assert.equal(balance, 1);
});
it('mint failed due to not enough matic', async () => {
const account = accounts[0];
await minter.setIsFreeMint(false);
const value = (BASE_PRICE * 1e-3).toString(); // not enough
minter
.mint(account.address, 1, {
from: account.address,
value,
})
.should.be.rejectedWith('Need to send more MATIC');
});
});
});
This is my token contract on mumbai scan: https://mumbai.polygonscan.com/address/0xA64c09eAECC403b12D97852E3089a5F4670AB120#readProxyContract
and the minter contract, you can see i have mint transaction ok with tokenId = 1 https://mumbai.polygonscan.com/address/0x200643AC0DD4D043AA0Cd9036770066517C8aaFC
Im struggling with it in 2 days, its really weird when the tests run ok but the result after deploying is not ok
Every suggestion and explanation is appreciated, thank you guys