Skip to content

Commit 4461a03

Browse files
test: vanguardNFT gas price(unfinished)
1 parent a942d65 commit 4461a03

File tree

5 files changed

+251
-0
lines changed

5 files changed

+251
-0
lines changed

contracts/test/VanguardNFT.sol

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// SPDX-License-Identifier: MIT
2+
// Compatible with OpenZeppelin Contracts ^5.0.0
3+
pragma solidity ^0.8.20;
4+
5+
import {ERC721NonTransferrableUpgradable} from "../NFT/ERC721NonTransferrableUpgradable.sol";
6+
import {GovernorRootstockCollective} from "../GovernorRootstockCollective.sol";
7+
8+
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
9+
import "hardhat/console.sol";
10+
11+
contract VanguardNFTRootstockCollective is ERC721NonTransferrableUpgradable {
12+
using Strings for uint256;
13+
14+
event IpfsFolderChanged(uint256 newNumFiles, string newIpfs);
15+
16+
error VanguardCannotMint();
17+
error MintError(string reason);
18+
19+
GovernorRootstockCollective public governor;
20+
// Counter for the total number of minted tokens
21+
uint256 private _totalMinted;
22+
// number of metadata files in the IPFS directory
23+
uint256 private _maxSupply;
24+
// IPFS CID of the tokens metadata directory
25+
string private _folderIpfsCid;
26+
27+
/// @custom:oz-upgrades-unsafe-allow constructor
28+
constructor() {
29+
_disableInitializers();
30+
}
31+
32+
function initialize(
33+
address initialOwner,
34+
GovernorRootstockCollective governorAddress,
35+
uint256 maxSupply,
36+
string calldata ipfsFolderCid
37+
) public initializer {
38+
require(address(governorAddress) != address(0), "VanguardNFTRootstockCollective: No governor address");
39+
__ERC721UpgradableBase_init("VanguardNFTRootstockCollective", "VanNFT", initialOwner);
40+
governor = governorAddress;
41+
setIpfsFolder(maxSupply, ipfsFolderCid);
42+
}
43+
44+
/**
45+
* @dev Sets a new IPFS folder and updates the maximum supply of tokens that can be minted.
46+
* This function is meant to be called by an admin when the metadata folder on IPFS is updated.
47+
* It ensures that the new maximum supply is greater than the previous one.
48+
* @param newMaxSupply The new maximum number of tokens that can be minted.
49+
* @param newIpfsCid The new IPFS CID for the metadata folder.
50+
*/
51+
function setIpfsFolder(uint256 newMaxSupply, string calldata newIpfsCid) public virtual onlyOwner {
52+
require(newMaxSupply >= _maxSupply, "VanguardNFTRootstockCollective: Invalid max supply");
53+
_maxSupply = newMaxSupply;
54+
_folderIpfsCid = newIpfsCid;
55+
emit IpfsFolderChanged(newMaxSupply, newIpfsCid);
56+
}
57+
58+
function mint() external virtual {
59+
address caller = _msgSender();
60+
61+
try governor.proposalCount() returns (uint count) {
62+
uint8 counter = 10;
63+
bool hasEverVoted = false;
64+
65+
while (counter != 0) {
66+
(uint256 proposalId, , , , ) = governor.proposalDetailsAt(count - counter);
67+
68+
bool hasVoted = governor.hasVoted(proposalId, caller);
69+
70+
if (hasVoted) {
71+
hasEverVoted = hasVoted;
72+
break;
73+
}
74+
75+
counter--;
76+
}
77+
78+
if (!hasEverVoted) {
79+
revert VanguardCannotMint();
80+
}
81+
82+
//here we mint
83+
uint256 tokenId = ++_totalMinted;
84+
string memory fileName = string.concat(tokenId.toString(), ".json"); // 1.json, 2.json ...
85+
_safeMint(caller, tokenId);
86+
_setTokenURI(tokenId, fileName);
87+
} catch Error(string memory reason) {
88+
revert MintError(reason);
89+
}
90+
}
91+
92+
/**
93+
* @dev Returns the number of tokens available for minting
94+
*/
95+
function tokensAvailable() public view virtual returns (uint256) {
96+
if (_totalMinted >= _maxSupply) return 0;
97+
return _maxSupply - _totalMinted;
98+
}
99+
100+
/**
101+
* @dev Returns the token ID for a given owner address.
102+
* This is a simplified version of the `tokenOfOwnerByIndex` function without the index
103+
* parameter, since a community member can only own one token.
104+
*/
105+
function tokenIdByOwner(address owner) public view virtual returns (uint256) {
106+
return tokenOfOwnerByIndex(owner, 0);
107+
}
108+
109+
/**
110+
* @dev Returns the token IPFS URI for the given owner address.
111+
* This utility function combines two view functions.
112+
*/
113+
function tokenUriByOwner(address owner) public view virtual returns (string memory) {
114+
return tokenURI(tokenIdByOwner(owner));
115+
}
116+
117+
function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner {}
118+
}

hardhat.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ const config: HardhatUserConfig = {
8080
},
8181
],
8282
},
83+
mocha: {
84+
timeout: 100000000,
85+
},
8386
}
8487

8588
export default config

ignition/modules/VanguardNFTModule.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'
2+
3+
export const VanguardNFTModule = buildModule('VanguardNFT', m => {
4+
// deploy implementation
5+
const implementation = m.contract('VanguardNFTRootstockCollective', [], { id: 'Implementation' })
6+
7+
// initializer parameters
8+
const deployer = m.getAccount(0)
9+
const governor = m.getParameter('governor')
10+
const maxSupply = m.getParameter('maxSupply')
11+
const ipfsFolderCid = m.getParameter('ipfsFolderCid')
12+
13+
// deploy proxy
14+
const proxy = m.contract('ERC1967Proxy', [
15+
implementation,
16+
m.encodeFunctionCall(implementation, 'initialize', [deployer, governor, maxSupply, ipfsFolderCid], {
17+
id: 'Proxy',
18+
}),
19+
])
20+
const VanguardNFT = m.contractAt('VanguardNFTRootstockCollective', proxy, {
21+
id: 'Contract',
22+
})
23+
24+
return { VanguardNFT }
25+
})
26+
27+
export default VanguardNFTModule

params/VanguardNFT/testnet.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"VanguardNFT": {
3+
"governor": "0x2109FF4a9D5548a21F877cA937Ac5847Fde49694",
4+
"maxSupply": 20,
5+
"ipfsFolderCid": "QmPaCP36tFjXp7xqcPi4ggatL7w4dsWKGTv1kpaSVkv9KW"
6+
}
7+
}

test/gasCheckForNFT.test.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { ethers, ignition } from 'hardhat'
2+
import { GovernorRootstockCollective, VanguardNFTRootstockCollective } from '../typechain-types'
3+
import VanguardNFTModule from '../ignition/modules/VanguardNFTModule'
4+
import { expect } from 'chai'
5+
import { HDNodeWallet, Wallet } from 'ethers'
6+
7+
const deployVanguard = async () => {
8+
const governor = await ethers.getContractAt(
9+
'GovernorRootstockCollective',
10+
'0x91a8E4A070B4BA4bf2e2a51Cb42BdeDf8FFB9b5a',
11+
)
12+
13+
const vanguardNFT = await ethers.getContractAt(
14+
'VanguardNFTRootstockCollective',
15+
'0x6c8A59784aD6a2BBcFe4940A587D88DeF24b6A32',
16+
)
17+
18+
// const ipfsFolderCid = 'QmPaCP36tFjXp7xqcPi4ggatL7w4dsWKGTv1kpaSVkv9KW'
19+
20+
const address = await governor.getAddress()
21+
console.log('address', address)
22+
23+
// const contract = await ignition.deploy(VanguardNFTModule, {
24+
// parameters: {
25+
// VanguardNFT: {
26+
// governor: address,
27+
// maxSupply: 20,
28+
// ipfsFolderCid,
29+
// },
30+
// },
31+
// })
32+
// const vanguardNFT = contract.VanguardNFT as unknown as VanguardNFTRootstockCollective
33+
34+
console.log('vanguardNFT address', await vanguardNFT.getAddress())
35+
36+
return { governor, vanguardNFT }
37+
}
38+
39+
describe('NFT GAS CHECK', () => {
40+
let vanguardNFT: VanguardNFTRootstockCollective
41+
let governor: GovernorRootstockCollective
42+
43+
before(async () => {
44+
try {
45+
;({ governor, vanguardNFT } = await deployVanguard())
46+
} catch (err) {
47+
console.log('ERROR IN ASYNC', err)
48+
}
49+
})
50+
51+
it('should successfully deploy', async () => {
52+
expect(await vanguardNFT.getAddress()).to.be.properAddress
53+
expect(await governor.getAddress()).to.be.properAddress
54+
})
55+
56+
it('should not mint', async () => {
57+
const provider = ethers.getDefaultProvider()
58+
const signer = new Wallet('b15963931c7e8bdb293596040e86dd18e4c885868c5ffffc1d91ff2d0fd84f07', provider)
59+
console.log('signer address', await signer.getAddress())
60+
const tx = await vanguardNFT.connect(signer).mint()
61+
62+
await expect(tx).to.be.revertedWithCustomError({ interface: vanguardNFT.interface }, 'VanguardCannotMint')
63+
})
64+
65+
// it('should fetch proposal count', async () => {
66+
// proposalCount = await governor.proposalCount()
67+
// console.log('proposalCount', proposalCount)
68+
// expect(proposalCount).to.be.greaterThan(0n)
69+
// })
70+
71+
// it('should be able to fetch proposalDetails by index', async () => {
72+
// const proposalDetails = await governor.proposalDetailsAt(proposalCount - 1n)
73+
// expect(typeof proposalDetails[0]).to.equal(typeof 0n)
74+
// })
75+
76+
// it('check gas', async () => {
77+
// const proposalsHasVoted = []
78+
79+
// await Promise.all(
80+
// [10n, 9n, 8n, 7n, 6n, 5n, 4n, 3n, 2n, 1n].map(async i => {
81+
// const proposalDetails = await governor.proposalDetailsAt(proposalCount - i)
82+
// const hasVoted = await governor.hasVoted(
83+
// proposalDetails[0],
84+
// '0x0C48e53E5852780Cb0a5Bf168eb92DE3B88Ebe89',
85+
// )
86+
// proposalsHasVoted.push({ id: proposalDetails[0], hasVoted })
87+
// }),
88+
// )
89+
90+
// console.log('proposalsHasVoted', proposalsHasVoted, proposalsHasVoted.length)
91+
92+
// proposalsHasVoted.forEach(obj => {
93+
94+
// })
95+
// })
96+
})

0 commit comments

Comments
 (0)