Weird issue with ERC1155

Viewed 14

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

0 Answers
Related