Compare commits

..

8 Commits

Author SHA1 Message Date
David E. Perez Negron R. fc2c669c3b feat: upgrade to solidity 0.8.28 2025-04-27 19:57:30 -06:00
David E. Perez Negron R. f3cfec4247 fix: update testFail to testRevert a breaking change in foundry 2025-04-27 19:53:12 -06:00
David E. Perez Negron R. 5f22272c7c / 2025-04-27 19:51:50 -06:00
David E. Perez Negron R. a026da5e01 Change private key env name 2024-04-29 17:23:40 -06:00
David E. Perez Negron R. 7df29a2461 Adding format with fmt, env example and deploy.sh script 2024-04-24 20:10:02 -06:00
David E. Perez Negron R. 3e448767d9 Fixing script and adding auto minting to airdrops accounts 2024-04-24 20:05:27 -06:00
David E. Perez Negron R. 065607af5d Update with .env and Cleanup tests 2024-04-24 18:21:13 -06:00
David E. Perez Negron R. 9970ffb6c2 Merge tag '0.1.1' into develop
just the NFTs ERC721 and the testing code
2024-04-10 19:55:10 -06:00
9 changed files with 229 additions and 205 deletions

View File

@ -6,26 +6,44 @@
* **Authors**: p1r0 * **Authors**: p1r0
* **Reviewers**: Itzel * **Reviewers**: Itzel
* **Voting Starts**: - * **Voting Starts**: -
* **Voting Deadline**: - * **Voting Deadline**: -
* **Tasks Deadline**: 2013-11-02 * **Tasks Deadline**: 2013-11-02
## Abstract ## Abstract
A NFT giveaway and non-profit auction DAPP by using the latest web3 trending technologies with the goal to develop a workflow for future projects, use cases for the DECA Protocol, incentivize community participation, and a proof-of-concept airdrop, giveaway, and auction models. A NFT giveaway and non-profit auction DAPP by using the latest web3 trending technologies with the goal to develop a workflow for future projects, use cases for the DECA Protocol, incentivize community participation, and a proof-of-concept airdrop, giveaway, and auction models.
## Specification ## Specification
### Why ### Why
Since we are changing the tools for DAPPs development to YEW, WASM, ETHERS rs and Foundry based frameworks, we will develop the following project that has a simple starting point and low complexity. Second, we intend to improve our web3 research, development skills, test the TEAM's capabilities for the DECA Protocol development. The third is to do a NFTs giveaway to the biggest or longest-time supporters of the DECA Project, which might have an interesting future use case. Last but not least, we will do a non-profit auction of the rarest NFTs so that the collected budget will be donated as a kick-start DECA DAO Vault funding. Since we are changing the tools for DAPPs development to YEW, WASM, ETHERS rs
and Foundry based frameworks, we will develop the following project that has a
simple starting point and low complexity. Second, we intend to improve our web3
research, development skills, test the TEAM's capabilities for the DECA
Protocol development. The third is to do a NFTs giveaway to the biggest or
longest-time supporters of the DECA Project, which might have an interesting
future use case. Last but not least, we will do a non-profit auction of the
rarest NFTs so that the collected budget will be donated as a kick-start DECA
DAO Vault funding.
### What (ToDo) ### What (ToDo)
NFTs giveaway to the biggest or longest-time supporters of the DECA Project: For this, you can develop a smart contract that manages the distribution of NFTs to specific Ethereum addresses. You can use the Ethers rs library to interact with this contract from your DApp, allowing you to send NFTs to the addresses of your project's supporters. The dev.to provides an example of a smart contract for an auction, which you could adapt for your NFT giveaway. NFTs giveaway to the biggest or longest-time supporters of the DECA Project:
For this, you can develop a smart contract that manages the distribution of
NFTs to specific Ethereum addresses. You can use the Ethers rs library to
interact with this contract from your Dapp, allowing you to send NFTs to the
addresses of your project's supporters. The dev.to provides an example of a
smart contract for an auction, which you could adapt for your NFT giveaway.
Non-profit auction of the rarest NFTs to collect funds for DECA DAO Vault: For this goal, you can build on the previous NFT giveaway idea but add an auction functionality to the smart contract. The auction can be set up such that the highest bidder wins the NFT, and the funds collected from the auction can be sent directly to the DECA DAO Vault. The code in dev.to can be a good starting point for building this functionality. Non-profit auction of the rarest NFTs to collect funds for DECA DAO Vault: For
Create/Recover 68 NFTs of the DECA Logo with specific properties as Background Color, Logo Color and a Complement. this goal, you can build on the previous NFT giveaway idea but add an auction
functionality to the smart contract. The auction can be set up such that the
highest bidder wins the NFT, and the funds collected from the auction can be
sent directly to the DECA DAO Vault. The code in dev.to can be a good starting
point for building this functionality. Create/Recover 68 NFTs of the DECA Logo
with specific properties as Background Color, Logo Color and a Complement.
URI Data structure: URI Data structure:
```json ```json
@ -51,7 +69,7 @@ URI Data structure:
``` ```
#### Properties. #### Properties.
* Name: * Name:
* Description: * Description:
* Image: * Image:
* Attributes: * Attributes:
@ -66,7 +84,7 @@ URI Data structure:
- [ ] Setup 2 Projects for WEB3 Frontend(YEW+RUST+Helia+EthersRS) And Backend(Foundry) - [ ] Setup 2 Projects for WEB3 Frontend(YEW+RUST+Helia+EthersRS) And Backend(Foundry)
## Web3 FrontEnd ## Web3 FrontEnd
- [ ] Integrate DCO2_IPFS Version with [ipfs HELIA](https://github.com/ipfs/helia) (JUST FOR TESTING use the DEPERCATED ASSETS and remove Descriptions) - [ ] Integrate DCO2_IPFS Version with [ipfs HELIA](https://github.com/ipfs/helia) (JUST FOR TESTING use the DEPERCATED ASSETS and remove Descriptions)
- [ ] Convert javascript code to rust and convert uris into structures: Use AI and the following [tutorial WASM+RUST](https://www.youtube.com/watch?v=YHJjmsw_Sx0) [!UPDATED we use the following one](https://github.com/rustwasm/rust-webpack-template) - [ ] Convert javascript code to rust and convert uris into structures: Use AI and the following [tutorial WASM+RUST](https://www.youtube.com/watch?v=YHJjmsw_Sx0) [!UPDATED we use the following one](https://github.com/rustwasm/rust-webpack-template)
- [ ] Create a Rust Code extract IPFS Hashes and update Json Files related to the name (check if its possible to do as with WASM+Rust or with helia or just cargo build. - [ ] Create a Rust Code extract IPFS Hashes and update Json Files related to the name (check if its possible to do as with WASM+Rust or with helia or just cargo build.
@ -97,7 +115,16 @@ URI Data structure:
## Rationale ## Rationale
Three years ago NSI intend to do an NFTs Gateway but we had multiple tasks and priorities so that we only left an unfinished project, now we intend to introduce [SBTs](https://vitalik.ca/general/2022/01/26/soulbound.html ) to the DECA Protocol as specified in the [Uses cases document](https://docs.google.com/presentation/d/1H4V5X0X-9jnulwmmQBKk7PiStqKoPh_t_h7F0R3kLw0/edit?usp=sharing) The goal is to use them as Certificates that can record data such as the CCToken offsets and others. Since we are ready to start with the Development of the DECA Protocol we require a project that will give us some experience in the Tools, Technologies and methods that will be implemented with further experience after this project achievements. Three years ago NSI intend to do an NFTs Gateway but we had multiple tasks and
priorities so that we only left an unfinished project, now we intend to
introduce [SBTs](https://vitalik.ca/general/2022/01/26/soulbound.html ) to the
DECA Protocol as specified in the [Uses cases
document](https://docs.google.com/presentation/d/1H4V5X0X-9jnulwmmQBKk7PiStqKoPh_t_h7F0R3kLw0/edit?usp=sharing)
The goal is to use them as Certificates that can record data such as the
CCToken offsets and others. Since we are ready to start with the Development of
the DECA Protocol we require a project that will give us some experience in the
Tools, Technologies and methods that will be implemented with further
experience after this project achievements.
## References ## References

5
deploy.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
. ./.env
forge script script/DCO2s.s.sol:DCO2sScript \
--fork-url $PROVIDER_URL \
--private-key $PRIVATE_KEY --broadcast

73
env.example Normal file
View File

@ -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=

View File

@ -2,7 +2,7 @@
src = "src" src = "src"
out = "out" out = "out"
libs = ["lib"] libs = ["lib"]
solc = "0.8.23" solc = "0.8.28"
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

View File

@ -1,32 +1,53 @@
// SPDX-License-Identifier: UNLICENSED // SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.23; pragma solidity ^0.8.28;
import {Script, console2} from "forge-std/Script.sol"; import {Script, console2} from "forge-std/Script.sol";
import { DCO2s } from "src/DCO2s.sol"; import {DCO2s} from "src/DCO2s.sol";
contract DCO2sScript is Script { contract DCO2sScript is Script {
DCO2s public dco2sc; DCO2s public dco2sc;
address public defaultAdmin;
address public minter;
address[] public airdrops;
string public baseURI; string public baseURI;
string public name;
string public symbol;
string[] public nfts;
function setUp() public { function setUp() public {
baseURI = "https://gateway.decentralizedscience.org/ipfs/"; baseURI = vm.envString("BASE_URI");
dco2sc = new DCO2s(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, defaultAdmin = vm.envAddress("DEFAULT_ADMIN");
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, minter = vm.envAddress("MINTER");
baseURI, name = vm.envString("NAME");
"DCO2s", symbol = vm.envString("SYMBOL");
"DCO2"); // Import nfts array from .env and split by ' '
console2.log("The DCO2s contract address is: ", address(dco2sc)); nfts = vm.envString("nfts", " ");
airdrops = vm.envAddress("airdrops", "\n");
} }
// run is the entry point // run is the entry point
function run() public { function run() public {
// startBroadcast and stopBraodcast will let us execute transactions anything between them // startBroadcast and stopBraodcast will let us execute transactions anything between them
vm.startBroadcast(); uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);
// here we just need to deploy a new contract // here we just need to deploy a new contract
string memory URI = "bafkreibc6p3y36yjmeqqnttqfrpb2yttxa6aonoywxwdxl7nqym4jj3jwa"; dco2sc = new DCO2s(defaultAdmin, minter, baseURI, name, symbol);
dco2sc.safeMint(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, URI); console2.log("The DCO2s contract address is: ", address(dco2sc));
string memory tokenURI = dco2sc.tokenURI(0);
console2.log("Token0 URI is:", tokenURI); // minting all nfts to airdrops accounts
// @notice: uses module for airdrops accounts to distribute the nfts
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];
//dco2sc.safeMint(defaultAdmin, URI);
//string memory tokenURI = dco2sc.tokenURI(0);
//console2.log("Token0 URI is:", tokenURI);
vm.stopBroadcast(); vm.stopBroadcast();
} }
} }

View File

@ -1,22 +1,20 @@
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.23; pragma solidity ^0.8.28;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import { DCO2s } from "./DCO2s.sol"; import {DCO2s} from "./DCO2s.sol";
contract AA is Ownable { contract AA is Ownable {
DCO2s public dco2sc; DCO2s public dco2sc;
string[] nfts; string[] nfts;
mapping (address => bool) public airdropped; mapping(address => bool) public airdropped;
mapping (address => bool) public eligible; mapping(address => bool) public eligible;
constructor(string memory name, constructor(string memory name, string memory symbol, string memory baseURI, string[] memory nftURIs)
string memory symbol, Ownable(msg.sender)
string memory baseURI, {
string [] memory nftURIs dco2sc = new DCO2s(address(this), address(this), baseURI, name, symbol);
) Ownable(msg.sender) {
dco2sc = new DCO2s(address(this),address(this), baseURI, name, symbol);
nfts = nftURIs; nfts = nftURIs;
} }
@ -28,7 +26,7 @@ contract AA is Ownable {
// Mint Function // Mint Function
// Simplify // Simplify
function mintNFT(address to, uint index) external onlyOwner { function mintNFT(address to, uint256 index) external onlyOwner {
require(!airdropped[to], "account already airdropped"); require(!airdropped[to], "account already airdropped");
dco2sc.safeMint(to, nfts[index]); dco2sc.safeMint(to, nfts[index]);
removeNFTAt(index); removeNFTAt(index);
@ -40,10 +38,10 @@ contract AA is Ownable {
if (airdropped[msg.sender] == true) { if (airdropped[msg.sender] == true) {
winner = false; winner = false;
} else if (eligible[msg.sender] == true) { } else if (eligible[msg.sender] == true) {
winner = true; winner = true;
} else { } else {
winner = false; winner = false;
} }
// require( callable until specific date) // require( callable until specific date)
// Activity // Activity
// Longest Holders // Longest Holders
@ -53,7 +51,7 @@ contract AA is Ownable {
} }
// @notice Random giveaway function // @notice Random giveaway function
function airdrop() external { function airdrop() external {
require(!airdropped[msg.sender], "account already airdropped"); require(!airdropped[msg.sender], "account already airdropped");
require(checkIfEligible(), "account not eligible"); require(checkIfEligible(), "account not eligible");
// top 20 is for Auction // top 20 is for Auction
@ -70,21 +68,17 @@ contract AA is Ownable {
require(!airdropped[msg.sender], "account already airdropped"); require(!airdropped[msg.sender], "account already airdropped");
eligible[supporter] = true; eligible[supporter] = true;
} }
// @notice Returns a randon number calculated from previews block randao // @notice Returns a randon number calculated from previews block randao
// @dev This only works after the merge // @dev This only works after the merge
function getRandomNumber() public view returns (uint randomNumber) { function getRandomNumber() public view returns (uint256 randomNumber) {
randomNumber = block.prevrandao; randomNumber = block.prevrandao;
} }
// @notice removes NFT URI from index // @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"); require(index < nfts.length, "nft index out of bounds");
nfts[index] = nfts[nfts.length - 1]; nfts[index] = nfts[nfts.length - 1];
nfts.pop(); nfts.pop();
} }
} }

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0 // SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.23; pragma solidity ^0.8.28;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
@ -12,12 +12,9 @@ contract DCO2s is ERC721, ERC721Enumerable, ERC721URIStorage, AccessControl {
uint256 private _nextTokenId; uint256 private _nextTokenId;
string bURI; string bURI;
constructor( constructor(address defaultAdmin, address minter, string memory baseURI, string memory name, string memory symbol)
address defaultAdmin, ERC721(name, symbol)
address minter, {
string memory baseURI,
string memory name, string memory symbol)
ERC721(name, symbol) {
_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin); _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
_grantRole(MINTER_ROLE, minter); _grantRole(MINTER_ROLE, minter);
bURI = baseURI; bURI = baseURI;
@ -43,19 +40,11 @@ contract DCO2s is ERC721, ERC721Enumerable, ERC721URIStorage, AccessControl {
return super._update(to, tokenId, auth); return super._update(to, tokenId, auth);
} }
function _increaseBalance(address account, uint128 value) function _increaseBalance(address account, uint128 value) internal override(ERC721, ERC721Enumerable) {
internal
override(ERC721, ERC721Enumerable)
{
super._increaseBalance(account, value); super._increaseBalance(account, value);
} }
function tokenURI(uint256 tokenId) function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId); return super.tokenURI(tokenId);
} }

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED // SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.23; pragma solidity ^0.8.28;
import {Test, console} from "forge-std/Test.sol"; import {Test, console} from "forge-std/Test.sol";
import {AA} from "../src/AA.sol"; import {AA} from "../src/AA.sol";
@ -13,7 +13,7 @@ contract AATest is Test {
function setUp() public { function setUp() public {
baseURI = "https://gateway.decentralizedscience.org/ipfs/"; baseURI = "https://gateway.decentralizedscience.org/ipfs/";
// Import nfts array from .env and split by ' ' // Import nfts array from .env and split by ' '
nfts = vm.envString("nfts", ' '); nfts = vm.envString("nfts", " ");
aaContract = new AA("DCO2s", "DCO2", baseURI, nfts); aaContract = new AA("DCO2s", "DCO2", baseURI, nfts);
} }
@ -22,10 +22,10 @@ contract AATest is Test {
address to = address(0x1); address to = address(0x1);
aaContract.mintNFT(to, 0); aaContract.mintNFT(to, 0);
address dco2scAddress = address(aaContract.dco2sc()); address dco2scAddress = address(aaContract.dco2sc());
console.log("{}",dco2scAddress); console.log("{}", dco2scAddress);
//assertEq(aaContract.ownerOf(0), to, "Token should be minted to specified address."); //assertEq(aaContract.ownerOf(0), to, "Token should be minted to specified address.");
} }
// Test mint all NFTs but -20 // Test mint all NFTs but -20
// Test Invite Eligible // Test Invite Eligible
@ -33,6 +33,6 @@ contract AATest is Test {
// test Check If Eligible // test Check If Eligible
// Test Airdrop // Test Airdrop
// Test Others // Test Others
} }

View File

@ -1,40 +1,43 @@
// SPDX-License-Identifier: UNLICENSED // SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.23; pragma solidity ^0.8.28;
import {Test, console} from "forge-std/Test.sol"; import {Test, console} from "forge-std/Test.sol";
import {DCO2s} from "../src/DCO2s.sol"; import {DCO2s} from "../src/DCO2s.sol";
//import {nfts} from "../.env";
contract DCO2sTest is Test { contract DCO2sTest is Test {
DCO2s public dco2sc; DCO2s public dco2sc;
string public name;
string public symbol;
string public baseURI; string public baseURI;
string[] public nfts; string[] public nfts;
function setUp() public { function setUp() public {
baseURI = "https://gateway.decentralizedscience.org/ipfs/"; baseURI = vm.envString("BASE_URI");
dco2sc = new DCO2s(address(this), address(this), baseURI, "DCO2s", "DCO2"); name = vm.envString("NAME");
symbol = vm.envString("SYMBOL");
dco2sc = new DCO2s(address(this), address(this), baseURI, name, symbol);
// Import nfts array from .env and split by ' ' // 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 // @notice this code safe mints an NFT to address 0x1
function testMint() public { function testMint() public {
address to = address(0x1); 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."); assertEq(dco2sc.ownerOf(0), to, "Token should be minted to specified address.");
} }
// @notice: here we test getting the Base and full URIS // @notice: here we test getting the Base and full URIS
function testGetURI68() public { function testGetURI15() public {
dco2sc.safeMint(address(0x1), nfts[68]); dco2sc.safeMint(address(0x1), nfts[15]);
string memory tokenURI = dco2sc.tokenURI(0); string memory tokenURI = dco2sc.tokenURI(0);
//console.log(tokenURI); //console.log(tokenURI);
assertEq(tokenURI, string.concat(baseURI, nfts[68])); assertEq(tokenURI, string.concat(baseURI, nfts[15]));
} }
// @notice: checkFailed token Index // @notice: checkFailed token Index
function testFailTokenIndex() view public { function testRevertTokenIndex() public {
vm.expectRevert();
dco2sc.tokenURI(0); dco2sc.tokenURI(0);
} }
@ -50,165 +53,77 @@ contract DCO2sTest is Test {
function testEnumerableTotalSupply() public { function testEnumerableTotalSupply() public {
string[5] memory mintedNFTs; string[5] memory mintedNFTs;
for(uint i = 0; i < 5; i++){ for (uint256 i = 0; i < 5; i++) {
mintedNFTs[i] = nfts[i]; mintedNFTs[i] = nfts[i];
} }
// mint 5 nfts // 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]); dco2sc.safeMint(address(1), mintedNFTs[i]);
} }
assertEq(mintedNFTs.length, dco2sc.totalSupply()); assertEq(mintedNFTs.length, dco2sc.totalSupply());
} }
// @notice use the basic Enumerable property tokenByIndex // @notice: use the basic Enumerable property tokenByIndex
// @notice: All nfts in the .env
function testEnumerableTokenByIndex() public { function testEnumerableTokenByIndex() public {
string[5] memory nftsSlice; for (uint256 i; i < nfts.length; i++) {
dco2sc.safeMint(address(1), nfts[i]);
for(uint i = 0; i < 5; i++){
nftsSlice[i] = nfts[i];
} }
for(uint i; i < nftsSlice.length; i++){ assertEq(nfts.length, dco2sc.totalSupply());
dco2sc.safeMint(address(1), nftsSlice[i]);
}
assertEq(nftsSlice.length, dco2sc.totalSupply());
// Test for token By Index 4 // Test for token By Index 4
uint tokenID = dco2sc.tokenByIndex(4); uint256 tokenID = dco2sc.tokenByIndex(4);
assertEq(nftsSlice[4], nftsSlice[tokenID]); assertEq(nfts[4], nfts[tokenID]);
// Test for token By Index 3 // Test for token By Index 3
tokenID = dco2sc.tokenByIndex(3); tokenID = dco2sc.tokenByIndex(3);
assertEq(nftsSlice[3], nftsSlice[tokenID]); assertEq(nfts[3], nfts[tokenID]);
} }
// @notice use the basic Enumerable property TokenOfOwnerByIndex // @notice use the basic Enumerable property TokenOfOwnerByIndex
// @notice: All nfts in the .env
function testEnumerableTokenOfOwnerByIndex() public { function testEnumerableTokenOfOwnerByIndex() public {
string[5] memory nftsSlice; // mints pair to address 1
for (uint256 i; i < nfts.length; i++) {
for(uint i = 0; i < 5; i++){ if (i % 2 == 0) {
nftsSlice[i] = nfts[i]; dco2sc.safeMint(address(1), nfts[i]);
}
for(uint i; i < nftsSlice.length; i++){
if(i % 2 == 0) {
dco2sc.safeMint(address(1), nftsSlice[i]);
} else { } else {
dco2sc.safeMint(address(2), nftsSlice[i]); dco2sc.safeMint(address(2), nfts[i]);
} }
} }
// Get the balance of NFTs of the account 1 // 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, 3); 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 // get the TokenID from account NFTs Index
uint token_id = dco2sc.tokenOfOwnerByIndex(address(1), i); uint256 token_id = dco2sc.tokenOfOwnerByIndex(address(1), i);
// console.log("Token ID ", token_id, " has URI: ", dco2sc.tokenURI(token_id)); assertEq(dco2sc.tokenURI(token_id), string.concat(baseURI, nfts[token_id]));
assertEq(dco2sc.tokenURI(token_id), string.concat(baseURI, nftsSlice[token_id]));
} }
} }
// @notice: testFailMintToZeroAddress test that cannot safe mint to address 0 // @notice: testFailMintToZeroAddress test that cannot safe mint to address 0
function testFailMintToZeroAddress() public { function testRevertMintToZeroAddress() public {
vm.expectRevert();
dco2sc.safeMint(address(0), nfts[0]); dco2sc.safeMint(address(0), nfts[0]);
} }
// // @notice testMintAll mints all the NFTs URIS and distribute to wallets // @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 // then it assertEq that it is properly minted to the wallet and the correct URI
// function testMintAll() public { function testMintAll() public {
// string[68] memory mintedNFTs; //assign to nfts.lenght addresses each one 1 NFT
for (uint256 i; i < nfts.length; i++) {
// for(uint i = 0; i < 68; i++){ dco2sc.safeMint(address(uint160(i + 1)), nfts[i]);
// mintedNFTs[i] = nfts[i]; }
// } // assert that each NFT gets minted with the proper URI
// //= ["bafkreibc6p3y36yjmeqqnttqfrpb2yttxa6aonoywxwdxl7nqym4jj3jwa", // and address
// // "bafkreidcf5baqb5wevs6avyd7dtd3j7rzrq65uyqasj4dbkcy6na4ig3ay", for (uint256 i; i < nfts.length; i++) {
// // "bafkreibffiehtv4ntajq5vjwpl7q44i6cjbg54lm5hkoa665ue2taspiyu", uint256 token_id = dco2sc.tokenOfOwnerByIndex(address(uint160(i + 1)), 0);
// // "bafkreifqztiwfutjik4wfs3gyfdyrff7cugi4mcctluunrrbp5cgareisq", assertEq(string.concat(baseURI, nfts[i]), dco2sc.tokenURI(token_id));
// // "bafkreiglyvpxwrxdvruit3oiw2lvkxqqxn7ojquw4gl7ck6szewz6t6cam", }
// // "bafkreiakd4xtuw3toe4wnez2ndmdadqv3oszaoffoha4tw2hqr3sjnsmge", }
// // "bafkreigx2isd63yflf6toeg7nfqw33hf6vvllcxfnzn7ymd7u4okflivbi",
// // "bafkreidrsjlcajbz35crgs6dpog6ophcochrgrrqgejxfye4m6lbw5mdde",
// // "bafkreihwi7xoak3p3mmofdln4pc4wqkkbdwyyz2yxbpfvpzvvxa2ogbaxi",
// // "bafkreiclhcy3n5iq3ka2jwxhvedpdewonwoujgu77y7rgnkddheioemcsi",
// // "bafkreic3vdshhst65qtzkwfbqzfpmuqbsyizxguarixobrp3scwaiq5jre",
// // "bafkreifv5xyis2kuveyfoc662zxeol2zdyiue4h3sznosef7ihrsmjexwm",
// // "bafkreifqyk6255h2ppobog33fzifsosbcnn2tanqi3ezjcwis6gya4sfoi",
// // "bafkreigend4j42oanbjxltwuyizmufdhqbngf6fbe5hgnlxs3yhzgpvay4",
// // "bafkreiextgvmtg23rx3lq2s6psebqln6ojlgosc544jch72baq3yt3dryu",
// // "bafkreihlkfwt5ntpnwf3c37d4lsf4y6czxojyffqet5ujvzw374x7ainoi",
// // "bafkreievuhvdru7p3lxht3of67xdri6urrrsjxr2e6rzulwg2574ye3dji",
// // "bafkreidqa6xuekp34iu7cqmngdbe7knzia47s7gwn3zczr5vwso57nrtx4",
// // "bafkreiglo5jhcem4ogswylqi37bx2wmn65cy6blwbwxcvuzklpfr6vhmke",
// // "bafkreibz353bqq76gjvswt7eebyffi3nkke5bzrvsjzem3is6x4ptpnqvi",
// // "bafkreif2dohcblqea4t4z5qjfxtdzz6vmtxs4325yuf6jz6e2sdxf366ni",
// // "bafkreib265gzsjgprktabq4c3glrdl5noebegibwupchwuwbswohum3ap4",
// // "bafkreicfaqdpgnrnebvqxyvg7s7eqgipbw5bg3hdticvghcpivjmvjx364",
// // "bafkreiabmontlvf2ah3vngpaf3cmg5ejinyqe6yl5pcl4lfrtvduwnuqcq",
// // "bafkreidvyf5txqmcizexdexdaqsbr4fxclcpfn6npgkngm6rclaszjll4q",
// // "bafkreib4wysvkug2bbzfpuey7hazqkezqtstv2n3yzccw7z77n2urcb6ye",
// // "bafkreiailtryy3cg7anain2evahiaox6babpxd4dp4kl67jqeoabh6ndwi",
// // "bafkreid32knw3kptbognoamqxcu5a2r3hzlzcb5a4tbouzfob5j2hhww6y",
// // "bafkreifprm74saobjxnang72smgtrevwvsxyps46kbc6ehhk3veqqpprte",
// // "bafkreif6wbrqmlqihivdasweh5opjjixinupsqfqmyflo2he3tdibx26mq",
// // "bafkreig75yruw2hkfqdfhmjm7lfenojvgv6emxfgkwolajhnjsokcc3vv4",
// // "bafkreihxvojrjrzigupwtncsrwsswju4cwh2sz5z2evqt6qlgcd7siptqi",
// // "bafkreifmcjsvyou6ml6khq7d7iglchh4a4clqvzf7t4ky6sxyoml6ixvj4",
// // "bafkreieyrrsp4lgoqqfrynp64cdif2jrnnzwc3lv4j5wlm4glszhjltp24",
// // "bafkreicpw7ytfbzakmg23wkuhrpumcdtoh75po7j6fu627vru3hgl6kpay",
// // "bafkreifrdsfw2vazhleexjkcd6f6t73aqvrobq5nwyeqa2rmykqtsef2o4",
// // "bafkreicdmr2bet7omb3u5zrgvubq2nxwbzlo6kqkjy6swey4u5yavqsf3y",
// // "bafkreihupkyebtf3rybziatp7p242gbyza7rf7s6noj3wun6fwd2sr6qhq",
// // "bafkreibrlybbkiiutohvwj3q6j3drs7llaxliz7dhiflipq34e4guzcbhu",
// // "bafkreieuseajoxy4ouo2u2upxz7lssoivcb63r64ada6n6pbxtupwnp6fa",
// // "bafkreid53wwrea4erd5hm7gjgkgpp6oddjqnctffewf3nay2grs2nhmh5y",
// // "bafkreigzrzugp7aqn6u6yqyaeu7v5lou4ldvkc5gfstr3p3otaf4afg56y",
// // "bafkreibqdmemeh57bkszki7oypxelqlihuy26eaeoi664epsqr5543q3je",
// // "bafkreiga4wd7vxjn46eovsktpmg2ugrd545sckdu2ibytvyjmj44rxjo5a",
// // "bafkreibef52rjpwrhfoaewbb4x7w5nthexsxzanoh5g7l3wzikubw6t4j4",
// // "bafkreihbkxbmbxk5xcujr3vwoo3qnnkubqmrkytjml76f2be4rfdi3kwiy",
// // "bafkreibh5fgjwuzcnyrpdcyxzpcjndrppeelgrjccfq2s7jg52dvcmk4cy",
// // "bafkreiea7k7u6kq76a4zysht5ri62jabvbuf6uk2emptxua2lkfmpleqqu",
// // "bafkreibietep53mtdq5kpk442x5djcaiwkirgltemomaaa6in6j375agfe",
// // "bafkreifwho3vue5x3yus3bcl2vs46b2ehgnhokmk4363dyptcqkcjuwtwm",
// // "bafkreicb662izefhwuvv7u6yh4rav76od4r4nkm6h7mgkflb77bt5wkimm",
// // "bafkreihlls4pkcjtjaasxmvctafrslucawm5lrffz5ho57azdaiapo2evq",
// // "bafkreih4ncyemyptx3nxe5qvxn6keiv7m36avhg5t2z6uvohs22he6q5zi",
// // "bafkreibxx4deq65og67be3oliqz2u4j6tacczarf74lbusbblflnp3c46a",
// // "bafkreibyegb4yn3yzxsnq5rggwra2x4nnd4eojvzdtxnl6lixq4f7cbdmm",
// // "bafkreiaygw7455yt6siqsqjs5bfhrrbxa5ezlktcwdnyeqikuq66irm5me",
// // "bafkreiaqj7xiukqacs6genv7s5bewucuag3d2lnn6kwqmkcnsngtrn2p5i",
// // "bafkreigm4czjurpcdgqapwj3ilzg7o3qx6wiyfd74hitm5hklyxbx52ujy",
// // "bafkreifgtz7hpaeuendeah37ny363ppx3klctkycol665lk65nkolvtj7q",
// // "bafkreicje4abjqh52oz35ble2yvasjkxemsptjnvla73greqzz5jwfkhiu",
// // "bafkreiebelxzjwxdvyvvj6cmqcn6cdnetrfxnw4bf4zaqkbh4myvu3a6qu",
// // "bafkreibg5fatnupr4u66zp5xabgyav65aik3bwv7ms73xjig37qz7ffura",
// // "bafkreigkgv36pc4gc35vlm7axlrtvbpwxl54pnq6mjovvre7n6vsqyfrp4",
// // "bafkreiekiefyw55qxsoqvbv2zbrjhbvrybo5qsamhsvk6rst4kzxmrxioq",
// // "bafkreifv2zmtj54mezqqbdfcc6z2anexctcumvs64abo2cvqgo47d6qk4q",
// // "bafkreibjlhludpjooxikum7cjw7c6rczgwbekaiusjm4xu5nyodwr3zjnm",
// // "bafkreib5z3fllsfv32fjhgvkao3csi4r2dhsegji52aqmfp4x2s6qb7734",
// // "bafkreiajnquwgsapxpesee4yyjz3hbwkopbr5pkpydbhjo4iwcpxolzrfy"];
// //assign to 68 addresses
// for ( uint i = 0; i < mintedNFTs.length; i++) {
// dco2sc.safeMint(address(this), mintedNFTs[i]);
// }
// // assert that each NFT gets minted with the proper URI
// // and addrress
// for ( uint i; i < mintedNFTs.length; i++) {
// assertEq(mintedNFTs[i], dco2sc.tokenURI(token_id));
// }
// }
} }