-
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.
feat: added External Contributors NFT collection
- Loading branch information
1 parent
92f735e
commit 7b4bf07
Showing
5 changed files
with
171 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,28 @@ | ||
// SPDX-License-Identifier: MIT | ||
// Compatible with OpenZeppelin Contracts ^5.0.0 | ||
pragma solidity ^0.8.20; | ||
|
||
import {ERC721UpgradableAirdroppable} from "./ERC721UpgradableAirdroppable.sol"; | ||
|
||
contract ExternalContributorsEcosystemPartner is ERC721UpgradableAirdroppable { | ||
/// @custom:oz-upgrades-unsafe-allow constructor | ||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize( | ||
string calldata contractName, | ||
string calldata symbol, | ||
address initialOwner, | ||
uint256 maxNftSupply | ||
) public initializer { | ||
__ERC721Airdroppable_init(maxNftSupply); | ||
__ERC721UpgradableBase_init(contractName, symbol, initialOwner); | ||
} | ||
|
||
function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner {} | ||
|
||
function _baseURI() internal pure override returns (string memory) { | ||
return "ipfs://"; | ||
} | ||
} |
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,35 @@ | ||
import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' | ||
|
||
export const extContributersEpProxyModule = buildModule('ExtContributorsEP', m => { | ||
// deploy implementation | ||
const implementation = m.contract('ExternalContributorsEcosystemPartner', [], { id: 'Implementation' }) | ||
|
||
// initializer parameters | ||
const contractName = m.getParameter('contractName') | ||
const contractSymbol = m.getParameter('symbol') | ||
const deployer = m.getAccount(0) | ||
const maxNftSupply = m.getParameter('maxNftSupply') | ||
|
||
// deploy proxy | ||
const proxy = m.contract('ERC1967Proxy', [ | ||
implementation, | ||
m.encodeFunctionCall( | ||
implementation, | ||
'initialize', | ||
[contractName, contractSymbol, deployer, maxNftSupply], | ||
{ id: 'Proxy' }, | ||
), | ||
]) | ||
const ExtContributorsEP = m.contractAt('ExternalContributorsEcosystemPartner', proxy, { | ||
id: 'Contract', | ||
}) | ||
|
||
// Airdrop | ||
const ipfsCids = m.getParameter('ipfsCids') | ||
const airdropAddresses = m.getParameter('airdropAddresses') | ||
m.call(ExtContributorsEP, 'airdrop', [ipfsCids, airdropAddresses]) | ||
|
||
return { ExtContributorsEP } | ||
}) | ||
|
||
export default extContributersEpProxyModule |
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,9 @@ | ||
{ | ||
"ExtContributorsEP": { | ||
"contractName": "ExternalContributorsEcosystemPartner", | ||
"symbol": "ECEP", | ||
"maxNftSupply": 5, | ||
"ipfsCids": [], | ||
"airdropAddresses": [] | ||
} | ||
} |
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,21 @@ | ||
{ | ||
"ExtContributorsEP": { | ||
"contractName": "ExternalContributorsEcosystemPartner", | ||
"symbol": "ECEP", | ||
"maxNftSupply": 5, | ||
"ipfsCids": [ | ||
"QmeGNJxhSToWYvHucUMX4D2fX8Uk2aL8CujwFuGw2Moy9U", | ||
"QmPFcgjgqCMoEbBmkbnvwaknENTH3WckjCGYekQhXJFVzn", | ||
"Qme6NCykZUUv78jXydTgmmehHThVXpJHFxAbZvEJkkPk5o", | ||
"QmUrqydS9kLYDJtv6dY7suhT5m5UPxJe1K1yq9b7QoY1VD", | ||
"QmcbYfu8CuhHRfRmDHwc8P8vqpgnYSCuzLcwtr5n4afMKb" | ||
], | ||
"airdropAddresses": [ | ||
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8", | ||
"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", | ||
"0x90F79bf6EB2c4f870365E785982E1f101E93b906", | ||
"0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", | ||
"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" | ||
] | ||
} | ||
} |
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,78 @@ | ||
import { expect } from 'chai' | ||
import hre, { ethers, ignition } from 'hardhat' | ||
import { ExternalContributorsEcosystemPartner } from '../typechain-types' | ||
import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers' | ||
import { extContributersEpProxyModule } from '../ignition/modules/ExternalContributorsEcosystemPartner' | ||
import deployParams from '../params/ExtContributorsEP/testnet.json' | ||
|
||
describe('ExternalContributorsEcosystemPartner NFT', () => { | ||
let deployer: SignerWithAddress | ||
let alice: SignerWithAddress | ||
const oldGangsters: SignerWithAddress[] = [] | ||
let extContEP: ExternalContributorsEcosystemPartner | ||
|
||
before(async () => { | ||
;[deployer, alice] = await ethers.getSigners() | ||
const contract = await ignition.deploy(extContributersEpProxyModule, { | ||
parameters: deployParams, | ||
}) | ||
// impersonating airdrop receivers | ||
for (let i = 0; i < deployParams.ExtContributorsEP.airdropAddresses.length; i++) { | ||
const senderAddr = deployParams.ExtContributorsEP.airdropAddresses[i] | ||
await hre.network.provider.request({ | ||
method: 'hardhat_impersonateAccount', | ||
params: [senderAddr], | ||
}) | ||
const sender = await ethers.getSigner(senderAddr) | ||
oldGangsters.push(sender) | ||
} | ||
extContEP = contract.ExtContributorsEP as unknown as ExternalContributorsEcosystemPartner | ||
}) | ||
|
||
describe('Upon deployment', () => { | ||
it('should set up proper NFT name and symbol', async () => { | ||
expect(await extContEP.connect(deployer).name()).to.equal(deployParams.ExtContributorsEP.contractName) | ||
expect(await extContEP.symbol()).to.equal(deployParams.ExtContributorsEP.symbol) | ||
}) | ||
|
||
it('should have performed airdrop during deployment', async () => { | ||
const ipfsCids = deployParams.ExtContributorsEP.ipfsCids | ||
for (let i = 0; i < oldGangsters.length; i++) { | ||
expect(await extContEP.ownerOf(i + 1)).to.equal(oldGangsters[i].address) | ||
expect(await extContEP.tokenURI(i + 1)).to.equal(`ipfs://${ipfsCids[i]}`) | ||
} | ||
}) | ||
}) | ||
|
||
describe('Transfer functionality is disabled', () => { | ||
it('transfers should be forbidden after airdrop', async () => { | ||
await Promise.all( | ||
oldGangsters.map(async (sender, i) => { | ||
await expect( | ||
extContEP.connect(sender).transferFrom(sender.address, alice.address, i + 1), | ||
).to.be.revertedWithCustomError(extContEP, 'TransfersDisabled') | ||
}), | ||
) | ||
}) | ||
|
||
it('approvals should be forbidden', async () => { | ||
await Promise.all( | ||
oldGangsters.map(async (sender, i) => { | ||
await expect( | ||
Check warning on line 61 in test/ExtContributorsEP.test.ts GitHub Actions / test
|
||
extContEP.connect(sender).approve(alice.address, i + 1), | ||
).to.be.revertedWithCustomError(extContEP, 'TransfersDisabled') | ||
}), | ||
) | ||
}) | ||
|
||
it('setApprovalForAll should be forbidden', async () => { | ||
await Promise.all( | ||
oldGangsters.map(async sender => { | ||
await expect( | ||
extContEP.connect(sender).setApprovalForAll(alice.address, true), | ||
).to.be.revertedWithCustomError(extContEP, 'TransfersDisabled') | ||
}), | ||
) | ||
}) | ||
}) | ||
}) |