-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: vanguardNFT gas price(unfinished)
- Loading branch information
1 parent
a942d65
commit 4461a03
Showing
5 changed files
with
251 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// SPDX-License-Identifier: MIT | ||
// Compatible with OpenZeppelin Contracts ^5.0.0 | ||
pragma solidity ^0.8.20; | ||
|
||
import {ERC721NonTransferrableUpgradable} from "../NFT/ERC721NonTransferrableUpgradable.sol"; | ||
import {GovernorRootstockCollective} from "../GovernorRootstockCollective.sol"; | ||
|
||
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; | ||
import "hardhat/console.sol"; | ||
|
||
contract VanguardNFTRootstockCollective is ERC721NonTransferrableUpgradable { | ||
using Strings for uint256; | ||
|
||
event IpfsFolderChanged(uint256 newNumFiles, string newIpfs); | ||
|
||
error VanguardCannotMint(); | ||
error MintError(string reason); | ||
|
||
GovernorRootstockCollective public governor; | ||
// Counter for the total number of minted tokens | ||
uint256 private _totalMinted; | ||
// number of metadata files in the IPFS directory | ||
uint256 private _maxSupply; | ||
// IPFS CID of the tokens metadata directory | ||
string private _folderIpfsCid; | ||
|
||
/// @custom:oz-upgrades-unsafe-allow constructor | ||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize( | ||
address initialOwner, | ||
GovernorRootstockCollective governorAddress, | ||
uint256 maxSupply, | ||
string calldata ipfsFolderCid | ||
) public initializer { | ||
require(address(governorAddress) != address(0), "VanguardNFTRootstockCollective: No governor address"); | ||
__ERC721UpgradableBase_init("VanguardNFTRootstockCollective", "VanNFT", initialOwner); | ||
governor = governorAddress; | ||
setIpfsFolder(maxSupply, ipfsFolderCid); | ||
} | ||
|
||
/** | ||
* @dev Sets a new IPFS folder and updates the maximum supply of tokens that can be minted. | ||
* This function is meant to be called by an admin when the metadata folder on IPFS is updated. | ||
* It ensures that the new maximum supply is greater than the previous one. | ||
* @param newMaxSupply The new maximum number of tokens that can be minted. | ||
* @param newIpfsCid The new IPFS CID for the metadata folder. | ||
*/ | ||
function setIpfsFolder(uint256 newMaxSupply, string calldata newIpfsCid) public virtual onlyOwner { | ||
require(newMaxSupply >= _maxSupply, "VanguardNFTRootstockCollective: Invalid max supply"); | ||
_maxSupply = newMaxSupply; | ||
_folderIpfsCid = newIpfsCid; | ||
emit IpfsFolderChanged(newMaxSupply, newIpfsCid); | ||
} | ||
|
||
function mint() external virtual { | ||
address caller = _msgSender(); | ||
|
||
try governor.proposalCount() returns (uint count) { | ||
uint8 counter = 10; | ||
bool hasEverVoted = false; | ||
|
||
while (counter != 0) { | ||
(uint256 proposalId, , , , ) = governor.proposalDetailsAt(count - counter); | ||
|
||
bool hasVoted = governor.hasVoted(proposalId, caller); | ||
|
||
if (hasVoted) { | ||
hasEverVoted = hasVoted; | ||
break; | ||
} | ||
|
||
counter--; | ||
} | ||
|
||
if (!hasEverVoted) { | ||
revert VanguardCannotMint(); | ||
} | ||
|
||
//here we mint | ||
uint256 tokenId = ++_totalMinted; | ||
string memory fileName = string.concat(tokenId.toString(), ".json"); // 1.json, 2.json ... | ||
_safeMint(caller, tokenId); | ||
_setTokenURI(tokenId, fileName); | ||
} catch Error(string memory reason) { | ||
revert MintError(reason); | ||
} | ||
} | ||
|
||
/** | ||
* @dev Returns the number of tokens available for minting | ||
*/ | ||
function tokensAvailable() public view virtual returns (uint256) { | ||
if (_totalMinted >= _maxSupply) return 0; | ||
return _maxSupply - _totalMinted; | ||
} | ||
|
||
/** | ||
* @dev Returns the token ID for a given owner address. | ||
* This is a simplified version of the `tokenOfOwnerByIndex` function without the index | ||
* parameter, since a community member can only own one token. | ||
*/ | ||
function tokenIdByOwner(address owner) public view virtual returns (uint256) { | ||
return tokenOfOwnerByIndex(owner, 0); | ||
} | ||
|
||
/** | ||
* @dev Returns the token IPFS URI for the given owner address. | ||
* This utility function combines two view functions. | ||
*/ | ||
function tokenUriByOwner(address owner) public view virtual returns (string memory) { | ||
return tokenURI(tokenIdByOwner(owner)); | ||
} | ||
|
||
function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,6 +80,9 @@ const config: HardhatUserConfig = { | |
}, | ||
], | ||
}, | ||
mocha: { | ||
timeout: 100000000, | ||
}, | ||
} | ||
|
||
export default config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' | ||
|
||
export const VanguardNFTModule = buildModule('VanguardNFT', m => { | ||
// deploy implementation | ||
const implementation = m.contract('VanguardNFTRootstockCollective', [], { id: 'Implementation' }) | ||
|
||
// initializer parameters | ||
const deployer = m.getAccount(0) | ||
const governor = m.getParameter('governor') | ||
const maxSupply = m.getParameter('maxSupply') | ||
const ipfsFolderCid = m.getParameter('ipfsFolderCid') | ||
|
||
// deploy proxy | ||
const proxy = m.contract('ERC1967Proxy', [ | ||
implementation, | ||
m.encodeFunctionCall(implementation, 'initialize', [deployer, governor, maxSupply, ipfsFolderCid], { | ||
id: 'Proxy', | ||
}), | ||
]) | ||
const VanguardNFT = m.contractAt('VanguardNFTRootstockCollective', proxy, { | ||
id: 'Contract', | ||
}) | ||
|
||
return { VanguardNFT } | ||
}) | ||
|
||
export default VanguardNFTModule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"VanguardNFT": { | ||
"governor": "0x2109FF4a9D5548a21F877cA937Ac5847Fde49694", | ||
"maxSupply": 20, | ||
"ipfsFolderCid": "QmPaCP36tFjXp7xqcPi4ggatL7w4dsWKGTv1kpaSVkv9KW" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { ethers, ignition } from 'hardhat' | ||
import { GovernorRootstockCollective, VanguardNFTRootstockCollective } from '../typechain-types' | ||
import VanguardNFTModule from '../ignition/modules/VanguardNFTModule' | ||
import { expect } from 'chai' | ||
import { HDNodeWallet, Wallet } from 'ethers' | ||
|
||
const deployVanguard = async () => { | ||
const governor = await ethers.getContractAt( | ||
'GovernorRootstockCollective', | ||
'0x91a8E4A070B4BA4bf2e2a51Cb42BdeDf8FFB9b5a', | ||
) | ||
|
||
const vanguardNFT = await ethers.getContractAt( | ||
'VanguardNFTRootstockCollective', | ||
'0x6c8A59784aD6a2BBcFe4940A587D88DeF24b6A32', | ||
) | ||
|
||
// const ipfsFolderCid = 'QmPaCP36tFjXp7xqcPi4ggatL7w4dsWKGTv1kpaSVkv9KW' | ||
|
||
const address = await governor.getAddress() | ||
console.log('address', address) | ||
|
||
// const contract = await ignition.deploy(VanguardNFTModule, { | ||
// parameters: { | ||
// VanguardNFT: { | ||
// governor: address, | ||
// maxSupply: 20, | ||
// ipfsFolderCid, | ||
// }, | ||
// }, | ||
// }) | ||
// const vanguardNFT = contract.VanguardNFT as unknown as VanguardNFTRootstockCollective | ||
|
||
console.log('vanguardNFT address', await vanguardNFT.getAddress()) | ||
|
||
return { governor, vanguardNFT } | ||
} | ||
|
||
describe('NFT GAS CHECK', () => { | ||
let vanguardNFT: VanguardNFTRootstockCollective | ||
let governor: GovernorRootstockCollective | ||
|
||
before(async () => { | ||
try { | ||
;({ governor, vanguardNFT } = await deployVanguard()) | ||
} catch (err) { | ||
console.log('ERROR IN ASYNC', err) | ||
} | ||
}) | ||
|
||
it('should successfully deploy', async () => { | ||
expect(await vanguardNFT.getAddress()).to.be.properAddress | ||
expect(await governor.getAddress()).to.be.properAddress | ||
}) | ||
|
||
it('should not mint', async () => { | ||
const provider = ethers.getDefaultProvider() | ||
const signer = new Wallet('b15963931c7e8bdb293596040e86dd18e4c885868c5ffffc1d91ff2d0fd84f07', provider) | ||
console.log('signer address', await signer.getAddress()) | ||
const tx = await vanguardNFT.connect(signer).mint() | ||
|
||
await expect(tx).to.be.revertedWithCustomError({ interface: vanguardNFT.interface }, 'VanguardCannotMint') | ||
}) | ||
|
||
// it('should fetch proposal count', async () => { | ||
// proposalCount = await governor.proposalCount() | ||
// console.log('proposalCount', proposalCount) | ||
// expect(proposalCount).to.be.greaterThan(0n) | ||
// }) | ||
|
||
// it('should be able to fetch proposalDetails by index', async () => { | ||
// const proposalDetails = await governor.proposalDetailsAt(proposalCount - 1n) | ||
// expect(typeof proposalDetails[0]).to.equal(typeof 0n) | ||
// }) | ||
|
||
// it('check gas', async () => { | ||
// const proposalsHasVoted = [] | ||
|
||
// await Promise.all( | ||
// [10n, 9n, 8n, 7n, 6n, 5n, 4n, 3n, 2n, 1n].map(async i => { | ||
// const proposalDetails = await governor.proposalDetailsAt(proposalCount - i) | ||
// const hasVoted = await governor.hasVoted( | ||
// proposalDetails[0], | ||
// '0x0C48e53E5852780Cb0a5Bf168eb92DE3B88Ebe89', | ||
// ) | ||
// proposalsHasVoted.push({ id: proposalDetails[0], hasVoted }) | ||
// }), | ||
// ) | ||
|
||
// console.log('proposalsHasVoted', proposalsHasVoted, proposalsHasVoted.length) | ||
|
||
// proposalsHasVoted.forEach(obj => { | ||
|
||
// }) | ||
// }) | ||
}) |