diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..1f664d6 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,5 @@ +#!/bin/sh +. ./.env +forge script script/DCO2s.s.sol:DCO2sScript \ + --fork-url $PROVIDER_URL \ + --private-key $PK0 --broadcast diff --git a/env.example b/env.example new file mode 100644 index 0000000..14aeab2 --- /dev/null +++ b/env.example @@ -0,0 +1,73 @@ +# Deploy +PROVIDER_URL="HTTP://127.0.0.1:8545" +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + + +# ERC721 Constructor +DEFAULT_ADMIN="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +MINTER="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +NAME="DCO2s" +SYMBOL="DCO2" +## BaseURI (IPFS Gateway) +BASE_URI="https://gateway.decentralizedscience.org/ipfs/" + +# Airdrop addresses +airdrops="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +0x70997970C51812dc3A010C7d01b50e0d17dc79C8 +0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC +0x90F79bf6EB2c4f870365E785982E1f101E93b906 +0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 +0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc +0x976EA74026E726554dB657fA54763abd0C3a0aa9 +0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 +0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f +0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" + +# Dapps Testing URIs +nfts="bafkreibc6p3y36yjmeqqnttqfrpb2yttxa6aonoywxwdxl7nqym4jj3jwa +bafkreidcf5baqb5wevs6avyd7dtd3j7rzrq65uyqasj4dbkcy6na4ig3ay +bafkreibffiehtv4ntajq5vjwpl7q44i6cjbg54lm5hkoa665ue2taspiyu +bafkreifqztiwfutjik4wfs3gyfdyrff7cugi4mcctluunrrbp5cgareisq +bafkreiglyvpxwrxdvruit3oiw2lvkxqqxn7ojquw4gl7ck6szewz6t6cam +bafkreiakd4xtuw3toe4wnez2ndmdadqv3oszaoffoha4tw2hqr3sjnsmge +bafkreigx2isd63yflf6toeg7nfqw33hf6vvllcxfnzn7ymd7u4okflivbi +bafkreidrsjlcajbz35crgs6dpog6ophcochrgrrqgejxfye4m6lbw5mdde +bafkreihwi7xoak3p3mmofdln4pc4wqkkbdwyyz2yxbpfvpzvvxa2ogbaxi +bafkreiclhcy3n5iq3ka2jwxhvedpdewonwoujgu77y7rgnkddheioemcsi +bafkreic3vdshhst65qtzkwfbqzfpmuqbsyizxguarixobrp3scwaiq5jre +bafkreifv5xyis2kuveyfoc662zxeol2zdyiue4h3sznosef7ihrsmjexwm +bafkreifqyk6255h2ppobog33fzifsosbcnn2tanqi3ezjcwis6gya4sfoi +bafkreigend4j42oanbjxltwuyizmufdhqbngf6fbe5hgnlxs3yhzgpvay4 +bafkreiextgvmtg23rx3lq2s6psebqln6ojlgosc544jch72baq3yt3dryu +bafkreihlkfwt5ntpnwf3c37d4lsf4y6czxojyffqet5ujvzw374x7ainoi +bafkreievuhvdru7p3lxht3of67xdri6urrrsjxr2e6rzulwg2574ye3dji" + +# Anvil Accounts +ACC0="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +ACC1="0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +ACC2="0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +ACC3="0x90F79bf6EB2c4f870365E785982E1f101E93b906" +ACC4="0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65" +ACC5="0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" +ACC6="0x976EA74026E726554dB657fA54763abd0C3a0aa9" +ACC7="0x14dC79964da2C08b23698B3D3cc7Ca32193d9955" +ACC8="0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f" +ACC9="0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" + + +# Anvil Private Keys +PK0="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +PK1="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" +PK2="0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a" +PK3="0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6" +PK4="0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a" +PK5="0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba" +PK6="0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e" +PK7="0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356" +PK8="0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97" +PK9="0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6" + + +# https://book.getfoundry.sh/tutorials/solidity-scripting?highlight=Private%20key#environment-configuration +# GOERLI_RPC_URL= +# ETHERSCAN_API_KEY= diff --git a/script/DCO2s.s.sol b/script/DCO2s.s.sol index 3d8836c..5563fdd 100644 --- a/script/DCO2s.s.sol +++ b/script/DCO2s.s.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.23; -import { Script, console2 } from "forge-std/Script.sol"; -import { DCO2s } from "src/DCO2s.sol"; +import {Script, console2} from "forge-std/Script.sol"; +import {DCO2s} from "src/DCO2s.sol"; contract DCO2sScript is Script { DCO2s public dco2sc; address public defaultAdmin; address public minter; address[] public airdrops; - string public baseURI; - string public name; + string public baseURI; + string public name; string public symbol; string[] public nfts; @@ -21,8 +21,8 @@ contract DCO2sScript is Script { name = vm.envString("NAME"); symbol = vm.envString("SYMBOL"); // Import nfts array from .env and split by ' ' - nfts = vm.envString("nfts", ' '); - airdrops = vm.envAddress("airdrops", '\n'); + nfts = vm.envString("nfts", " "); + airdrops = vm.envAddress("airdrops", "\n"); } // run is the entry point @@ -31,24 +31,19 @@ contract DCO2sScript is Script { uint256 deployerPrivateKey = vm.envUint("PK0"); vm.startBroadcast(deployerPrivateKey); // here we just need to deploy a new contract - dco2sc = new DCO2s(defaultAdmin, - minter, - baseURI, - name, - symbol); + dco2sc = new DCO2s(defaultAdmin, minter, baseURI, name, symbol); console2.log("The DCO2s contract address is: ", address(dco2sc)); - // minting all nfts to airdrops accounts // @notice: uses module for airdrops accounts to distribute the nfts - for(uint i; i < nfts.length; i++) { + for (uint256 i; i < nfts.length; i++) { dco2sc.safeMint(airdrops[i % airdrops.length], nfts[i]); string memory tokenURI = dco2sc.tokenURI(i); console2.log("Token0 URI is:", tokenURI); - } + } // minting NFT0 to the contract admin - //string memory URI = nfts[0]; + //string memory URI = nfts[0]; //dco2sc.safeMint(defaultAdmin, URI); //string memory tokenURI = dco2sc.tokenURI(0); //console2.log("Token0 URI is:", tokenURI); diff --git a/src/AA.sol b/src/AA.sol index 1b6dbbb..f83b7e7 100644 --- a/src/AA.sol +++ b/src/AA.sol @@ -1,22 +1,20 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { DCO2s } from "./DCO2s.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {DCO2s} from "./DCO2s.sol"; contract AA is Ownable { DCO2s public dco2sc; - string[] nfts; + string[] nfts; - mapping (address => bool) public airdropped; - mapping (address => bool) public eligible; + mapping(address => bool) public airdropped; + mapping(address => bool) public eligible; - constructor(string memory name, - string memory symbol, - string memory baseURI, - string [] memory nftURIs - ) Ownable(msg.sender) { - dco2sc = new DCO2s(address(this),address(this), baseURI, name, symbol); + constructor(string memory name, string memory symbol, string memory baseURI, string[] memory nftURIs) + Ownable(msg.sender) + { + dco2sc = new DCO2s(address(this), address(this), baseURI, name, symbol); nfts = nftURIs; } @@ -28,7 +26,7 @@ contract AA is Ownable { // Mint Function // Simplify - function mintNFT(address to, uint index) external onlyOwner { + function mintNFT(address to, uint256 index) external onlyOwner { require(!airdropped[to], "account already airdropped"); dco2sc.safeMint(to, nfts[index]); removeNFTAt(index); @@ -40,10 +38,10 @@ contract AA is Ownable { if (airdropped[msg.sender] == true) { winner = false; } else if (eligible[msg.sender] == true) { - winner = true; + winner = true; } else { winner = false; - } + } // require( callable until specific date) // Activity // Longest Holders @@ -53,7 +51,7 @@ contract AA is Ownable { } // @notice Random giveaway function - function airdrop() external { + function airdrop() external { require(!airdropped[msg.sender], "account already airdropped"); require(checkIfEligible(), "account not eligible"); // top 20 is for Auction @@ -70,21 +68,17 @@ contract AA is Ownable { require(!airdropped[msg.sender], "account already airdropped"); eligible[supporter] = true; } - // @notice Returns a randon number calculated from previews block randao // @dev This only works after the merge - function getRandomNumber() public view returns (uint randomNumber) { + function getRandomNumber() public view returns (uint256 randomNumber) { randomNumber = block.prevrandao; } // @notice removes NFT URI from index - function removeNFTAt(uint index) public { + function removeNFTAt(uint256 index) public { require(index < nfts.length, "nft index out of bounds"); nfts[index] = nfts[nfts.length - 1]; nfts.pop(); } - } - - diff --git a/src/DCO2s.sol b/src/DCO2s.sol index be7b5e3..7c70bc6 100644 --- a/src/DCO2s.sol +++ b/src/DCO2s.sol @@ -12,12 +12,9 @@ contract DCO2s is ERC721, ERC721Enumerable, ERC721URIStorage, AccessControl { uint256 private _nextTokenId; string bURI; - constructor( - address defaultAdmin, - address minter, - string memory baseURI, - string memory name, string memory symbol) - ERC721(name, symbol) { + constructor(address defaultAdmin, address minter, string memory baseURI, string memory name, string memory symbol) + ERC721(name, symbol) + { _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin); _grantRole(MINTER_ROLE, minter); bURI = baseURI; @@ -43,19 +40,11 @@ contract DCO2s is ERC721, ERC721Enumerable, ERC721URIStorage, AccessControl { return super._update(to, tokenId, auth); } - function _increaseBalance(address account, uint128 value) - internal - override(ERC721, ERC721Enumerable) - { + function _increaseBalance(address account, uint128 value) internal override(ERC721, ERC721Enumerable) { super._increaseBalance(account, value); } - function tokenURI(uint256 tokenId) - public - view - override(ERC721, ERC721URIStorage) - returns (string memory) - { + function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { return super.tokenURI(tokenId); } diff --git a/test/AA.t.sol b/test/AA.t.sol index c23b38f..837aa5c 100644 --- a/test/AA.t.sol +++ b/test/AA.t.sol @@ -13,7 +13,7 @@ contract AATest is Test { function setUp() public { baseURI = "https://gateway.decentralizedscience.org/ipfs/"; // Import nfts array from .env and split by ' ' - nfts = vm.envString("nfts", ' '); + nfts = vm.envString("nfts", " "); aaContract = new AA("DCO2s", "DCO2", baseURI, nfts); } @@ -22,10 +22,10 @@ contract AATest is Test { address to = address(0x1); aaContract.mintNFT(to, 0); address dco2scAddress = address(aaContract.dco2sc()); - console.log("{}",dco2scAddress); + console.log("{}", dco2scAddress); //assertEq(aaContract.ownerOf(0), to, "Token should be minted to specified address."); } - + // Test mint all NFTs but -20 // Test Invite Eligible @@ -33,6 +33,6 @@ contract AATest is Test { // test Check If Eligible // Test Airdrop - + // Test Others } diff --git a/test/DCO2s.t.sol b/test/DCO2s.t.sol index a05ffc5..22db5bf 100644 --- a/test/DCO2s.t.sol +++ b/test/DCO2s.t.sol @@ -6,7 +6,7 @@ import {DCO2s} from "../src/DCO2s.sol"; contract DCO2sTest is Test { DCO2s public dco2sc; - string public name; + string public name; string public symbol; string public baseURI; string[] public nfts; @@ -17,13 +17,13 @@ contract DCO2sTest is Test { symbol = vm.envString("SYMBOL"); dco2sc = new DCO2s(address(this), address(this), baseURI, name, symbol); // Import nfts array from .env and split by ' ' - nfts = vm.envString("nfts", ' '); + nfts = vm.envString("nfts", " "); } // @notice this code safe mints an NFT to address 0x1 function testMint() public { address to = address(0x1); - dco2sc.safeMint(to,nfts[0]); + dco2sc.safeMint(to, nfts[0]); assertEq(dco2sc.ownerOf(0), to, "Token should be minted to specified address."); } @@ -35,9 +35,8 @@ contract DCO2sTest is Test { assertEq(tokenURI, string.concat(baseURI, nfts[15])); } - // @notice: checkFailed token Index - function testFailTokenIndex() view public { + function testFailTokenIndex() public view { dco2sc.tokenURI(0); } @@ -53,31 +52,29 @@ contract DCO2sTest is Test { function testEnumerableTotalSupply() public { string[5] memory mintedNFTs; - for(uint i = 0; i < 5; i++){ + for (uint256 i = 0; i < 5; i++) { mintedNFTs[i] = nfts[i]; } // mint 5 nfts - for(uint i = 0; i < mintedNFTs.length; i++){ + for (uint256 i = 0; i < mintedNFTs.length; i++) { dco2sc.safeMint(address(1), mintedNFTs[i]); } assertEq(mintedNFTs.length, dco2sc.totalSupply()); - } // @notice: use the basic Enumerable property tokenByIndex // @notice: All nfts in the .env function testEnumerableTokenByIndex() public { - - for(uint i; i < nfts.length; i++){ + for (uint256 i; i < nfts.length; i++) { dco2sc.safeMint(address(1), nfts[i]); } assertEq(nfts.length, dco2sc.totalSupply()); // Test for token By Index 4 - uint tokenID = dco2sc.tokenByIndex(4); + uint256 tokenID = dco2sc.tokenByIndex(4); assertEq(nfts[4], nfts[tokenID]); // Test for token By Index 3 @@ -88,10 +85,9 @@ contract DCO2sTest is Test { // @notice use the basic Enumerable property TokenOfOwnerByIndex // @notice: All nfts in the .env function testEnumerableTokenOfOwnerByIndex() public { - // mints pair to address 1 - for(uint i; i < nfts.length; i++){ - if(i % 2 == 0) { + for (uint256 i; i < nfts.length; i++) { + if (i % 2 == 0) { dco2sc.safeMint(address(1), nfts[i]); } else { dco2sc.safeMint(address(2), nfts[i]); @@ -99,44 +95,33 @@ contract DCO2sTest is Test { } // Get the balance of NFTs of the account 1 pairs are 8 - uint account1_balance = dco2sc.balanceOf(address(1)); + uint256 account1_balance = dco2sc.balanceOf(address(1)); assertEq(account1_balance, 8); - for(uint i; i < account1_balance; i++){ + for (uint256 i; i < account1_balance; i++) { // get the TokenID from account NFTs Index - uint token_id = dco2sc.tokenOfOwnerByIndex(address(1), i); + uint256 token_id = dco2sc.tokenOfOwnerByIndex(address(1), i); assertEq(dco2sc.tokenURI(token_id), string.concat(baseURI, nfts[token_id])); } - } - // @notice: testFailMintToZeroAddress test that cannot safe mint to address 0 function testFailMintToZeroAddress() public { dco2sc.safeMint(address(0), nfts[0]); } - // @notice testMintAll mints all the NFTs URIS and distribute to wallets - // then it assertEq that it is properly minted to the wallet and the correct URI - function testMintAll() public { - //string[15] memory mintedNFTs; - - //for(uint i = 0; i < 15; i++){ - // mintedNFTs[i] = nfts[i]; - //} - - //assign to 15 addresses each one 1 NFT - for (uint i; i < nfts.length; i++) { - dco2sc.safeMint(address(uint160(i+1)), nfts[i]); + // @notice testMintAll mints all the NFTs URIS and distribute to wallets + // then it assertEq that it is properly minted to the wallet and the correct URI + function testMintAll() public { + //assign to nfts.lenght addresses each one 1 NFT + for (uint256 i; i < nfts.length; i++) { + dco2sc.safeMint(address(uint160(i + 1)), nfts[i]); } // assert that each NFT gets minted with the proper URI // and address - for (uint i; i < nfts.length; i++) { - uint token_id = dco2sc.tokenOfOwnerByIndex(address(uint160(i+1)), 0); + for (uint256 i; i < nfts.length; i++) { + uint256 token_id = dco2sc.tokenOfOwnerByIndex(address(uint160(i + 1)), 0); assertEq(string.concat(baseURI, nfts[i]), dco2sc.tokenURI(token_id)); } } - } - -