From 70e9c14b05a00c1a98c75e8a283f9a73ac026751 Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Mon, 20 Feb 2023 11:44:59 -0300 Subject: [PATCH] feature: expose last token id function in the contract (#124) * feat: add function to get the last token id * test: add getLastTokenId tests --- contracts/contracts/FleekERC721.sol | 11 ++++ .../foundry/FleekERC721/GetLastTokenId.t.sol | 31 ++++++++++ .../FleekERC721/get-last-token-id.t.ts | 56 +++++++++++++++++++ .../contracts/FleekERC721/helpers/errors.ts | 3 + .../contracts/FleekERC721/helpers/index.ts | 1 + 5 files changed, 102 insertions(+) create mode 100644 contracts/test/foundry/FleekERC721/GetLastTokenId.t.sol create mode 100644 contracts/test/hardhat/contracts/FleekERC721/get-last-token-id.t.ts create mode 100644 contracts/test/hardhat/contracts/FleekERC721/helpers/errors.ts diff --git a/contracts/contracts/FleekERC721.sol b/contracts/contracts/FleekERC721.sol index d84e58a..6272a04 100644 --- a/contracts/contracts/FleekERC721.sol +++ b/contracts/contracts/FleekERC721.sol @@ -9,6 +9,8 @@ import "@openzeppelin/contracts/utils/Strings.sol"; import "./FleekAccessControl.sol"; import "./util/FleekStrings.sol"; +error ThereIsNoTokenMinted(); + contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl { using Strings for uint256; using Counters for Counters.Counter; @@ -173,6 +175,15 @@ contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl { return (app.name, app.description, app.externalURL, app.ENS, app.currentBuild, app.logo, app.color); } + /** + * @dev Returns the last minted tokenId. + */ + function getLastTokenId() public view virtual returns (uint256) { + uint256 current = _appIds.current(); + if (current == 0) revert ThereIsNoTokenMinted(); + return current - 1; + } + /** * @dev See {IERC165-supportsInterface}. */ diff --git a/contracts/test/foundry/FleekERC721/GetLastTokenId.t.sol b/contracts/test/foundry/FleekERC721/GetLastTokenId.t.sol new file mode 100644 index 0000000..926091c --- /dev/null +++ b/contracts/test/foundry/FleekERC721/GetLastTokenId.t.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.17; + +import "./TestBase.sol"; +import "contracts/FleekERC721.sol"; + +contract Test_FleekERC721_GetLastTokenId is Test_FleekERC721_Base { + function setUp() public { + baseSetUp(); + } + + function test_cannotGetLastTokenIdWhenThereIsNoTokenMinted() public { + vm.expectRevert(ThereIsNoTokenMinted.selector); + CuT.getLastTokenId(); + } + + function test_getLastTokenIdForOneToken() public { + uint256 mint = mintDefault(deployer); + + assertEq(mint, CuT.getLastTokenId()); + } + + function test_getLastTokenIdAfterThreeMints() public { + mintDefault(deployer); + mintDefault(deployer); + uint256 lastMint = mintDefault(deployer); + + assertEq(lastMint, CuT.getLastTokenId()); + } +} diff --git a/contracts/test/hardhat/contracts/FleekERC721/get-last-token-id.t.ts b/contracts/test/hardhat/contracts/FleekERC721/get-last-token-id.t.ts new file mode 100644 index 0000000..6f9408f --- /dev/null +++ b/contracts/test/hardhat/contracts/FleekERC721/get-last-token-id.t.ts @@ -0,0 +1,56 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { TestConstants, Fixtures, Errors } from './helpers'; +import { ethers } from 'hardhat'; + +const { MintParams, Roles } = TestConstants; + +describe('FleekERC721.GetLastTokenId', () => { + let fixture: Awaited>; + + const mint = async () => { + const response = await fixture.contract.mint( + fixture.owner.address, + TestConstants.MintParams.name, + TestConstants.MintParams.description, + TestConstants.MintParams.externalUrl, + TestConstants.MintParams.ens, + TestConstants.MintParams.commitHash, + TestConstants.MintParams.gitRepository, + TestConstants.MintParams.logo, + TestConstants.MintParams.color + ); + + return response; + }; + + beforeEach(async () => { + fixture = await loadFixture(Fixtures.default); + }); + + it('should revert if there is no token minted', async () => { + const { contract } = fixture; + await expect(contract.getLastTokenId()).to.be.revertedWithCustomError( + contract, + Errors.ThereIsNoTokenMinted + ); + }); + + it('should return the last token id', async () => { + const { contract } = fixture; + + await mint(); + + expect(await contract.getLastTokenId()).to.be.equal(0); + }); + + it('should return the last token id after minting multiple tokens', async () => { + const { contract } = fixture; + + await mint(); + await mint(); + await mint(); + + expect(await contract.getLastTokenId()).to.be.equal(2); + }); +}); diff --git a/contracts/test/hardhat/contracts/FleekERC721/helpers/errors.ts b/contracts/test/hardhat/contracts/FleekERC721/helpers/errors.ts new file mode 100644 index 0000000..4e9d673 --- /dev/null +++ b/contracts/test/hardhat/contracts/FleekERC721/helpers/errors.ts @@ -0,0 +1,3 @@ +export const Errors = Object.freeze({ + ThereIsNoTokenMinted: 'ThereIsNoTokenMinted', +}); diff --git a/contracts/test/hardhat/contracts/FleekERC721/helpers/index.ts b/contracts/test/hardhat/contracts/FleekERC721/helpers/index.ts index 27cb470..650cdb0 100644 --- a/contracts/test/hardhat/contracts/FleekERC721/helpers/index.ts +++ b/contracts/test/hardhat/contracts/FleekERC721/helpers/index.ts @@ -1,4 +1,5 @@ export * from './constants'; export * from './fixture'; export * from './utils'; +export * from './errors'; export * from './events';