diff --git a/docs/CONTRACT_PACKAGE.md b/docs/CONTRACT_PACKAGE.md index a9f75f0..ae6f00f 100644 --- a/docs/CONTRACT_PACKAGE.md +++ b/docs/CONTRACT_PACKAGE.md @@ -1,4 +1,4 @@ -# DeCleanup Network Smart Contracts +# DeCleanup Network Smart Contracts Package This package provides the smart contracts for the DeCleanup Network, including TypeChain-generated type definitions for type-safe contract interactions. @@ -8,6 +8,91 @@ This package provides the smart contracts for the DeCleanup Network, including T npm install @decleanup/contracts ``` +## Overview + +The DeCleanup Network smart contracts package includes all core contracts for the environmental cleanup platform: + +### Core Token Contracts +- **DCUToken** - Main ERC-20 utility token with dynamic supply +- **DCUStorage** - Token storage with TGE restrictions and staking +- **DCUAccounting** - Token deposit/withdrawal management + +### NFT & Reward Contracts +- **DipNft** - Soulbound NFTs representing Impact Products +- **NFTCollection** - Basic NFT collection for testing +- **DCURewardManager** - Manages DCU rewards for various activities +- **RewardLogic** - Handles reward distribution logic + +### Additional Contracts +- **Submission** - Handles form submissions from the DeCleanup dapp + +## Package Generation + +### Prerequisites + +1. **Compile Contracts:** + ```bash + npm run compile + ``` + +2. **Generate TypeChain Types:** + ```bash + npm run typechain + ``` + +3. **Deploy Contracts:** + ```bash + # For Arbitrum Mainnet + npm run deploy:arbitrum + + # For Arbitrum Sepolia Testnet + npm run deploy:arbitrum-testnet + ``` + +### Generating the Package + +#### For Arbitrum Mainnet +```bash +npm run generate-package:arbitrum +``` + +#### For Arbitrum Sepolia Testnet +```bash +npm run generate-package:arbitrum-sepolia +``` + +#### For Custom Network +```bash +npm run generate-package +``` + +### Package Structure + +The generated package will have the following structure: + +``` +package/ +├── package.json +├── index.js +├── index.d.ts +└── / + ├── config.json + ├── index.js + ├── index.d.ts + ├── artifacts/ + │ ├── DCUToken/ + │ │ ├── abi.json + │ │ └── bytecode.json + │ ├── DipNft/ + │ │ ├── abi.json + │ │ └── bytecode.json + │ └── ... (other contracts) + └── typechain/ + ├── contracts/ + ├── factories/ + └── ... (TypeChain files) +``` + ## Usage ### Basic Setup @@ -30,6 +115,8 @@ const accounting = contracts.DCUAccounting.connect(signer); const storage = contracts.DCUStorage.connect(signer); const rewardManager = contracts.DCURewardManager.connect(signer); const dipNft = contracts.DipNft.connect(signer); +const submission = contracts.Submission.connect(signer); +const nftCollection = contracts.NFTCollection.connect(signer); ``` ### Contract Information @@ -97,20 +184,15 @@ async function transferTokens(signer: ethers.Signer, recipient: string, amount: ```typescript import { DCUContracts, Networks } from '@decleanup/contracts'; -async function claimRewards(signer: ethers.Signer, submissionId: bigint) { +async function claimRewards(signer: ethers.Signer, amount: bigint) { const contracts = new DCUContracts(Networks.ARBITRUM_SEPOLIA); const rewardManager = contracts.DCURewardManager.connect(signer); - const rewardLogic = contracts.RewardLogic.connect(signer); - - // Check if rewards are available - const isAvailable = await rewardLogic.isRewardAvailable(submissionId); - if (!isAvailable) { - throw new Error('Rewards not available for this submission'); - } // Claim rewards - const tx = await rewardManager.claimRewards(submissionId); + const tx = await rewardManager.claimRewards(amount); await tx.wait(); + + return tx; } ``` @@ -123,8 +205,8 @@ async function mintNFT(signer: ethers.Signer, to: string, tokenURI: string) { const contracts = new DCUContracts(Networks.ARBITRUM_SEPOLIA); const nft = contracts.DipNft.connect(signer); - // Mint new NFT - const tx = await nft.mint(to, tokenURI); + // Mint new NFT (requires PoI verification) + const tx = await nft.safeMint(); await tx.wait(); // Get token ID @@ -136,6 +218,28 @@ async function mintNFT(signer: ethers.Signer, to: string, tokenURI: string) { } ``` +### Example: Submission Operations + +```typescript +import { DCUContracts, Networks } from '@decleanup/contracts'; + +async function createSubmission(signer: ethers.Signer, dataURI: string) { + const contracts = new DCUContracts(Networks.ARBITRUM_SEPOLIA); + const submission = contracts.Submission.connect(signer); + + // Create a new submission + const tx = await submission.createSubmission(dataURI); + await tx.wait(); + + // Get submission ID from event + const receipt = await tx.wait(); + const event = receipt.logs.find(log => log.fragment.name === 'SubmissionCreated'); + const submissionId = event?.args[0]; + + return submissionId; +} +``` + ## Type Safety The package includes TypeChain-generated type definitions, providing: @@ -177,6 +281,78 @@ async function safeTransfer(signer: ethers.Signer, recipient: string, amount: bi } ``` +## Adding New Contracts + +To add a new contract to the package: + +1. **Add to Contract List**: Update the `contracts` array in `scripts/generate-package.ts` + ```typescript + const contracts: ContractInfo[] = [ + // ... existing contracts + { name: "NewContract", path: "NewContract.sol" }, + ]; + ``` + +2. **Update Deployment Script**: Add deployment logic to `scripts/deploy-arbitrum.ts` + ```typescript + // Deploy NewContract + const NewContract = await ethers.getContractFactory("NewContract"); + const newContract = await NewContract.deploy(/* constructor args */); + await newContract.deployed(); + const newContractAddress = newContract.address; + ``` + +3. **Update Ignition Module**: Add to `ignition/modules/DCUContracts.ts` + ```typescript + const newContract = m.contract("NewContract", [/* constructor args */]); + ``` + +4. **Update Deployed Addresses**: Add to the `deployedAddresses` object + ```typescript + const deployedAddresses = { + // ... existing addresses + NewContract: newContractAddress, + }; + ``` + +## Troubleshooting + +### Common Issues + +1. **Missing Contract Artifacts** + - Ensure contracts are compiled: `npm run compile` + - Check that the contract path in `generate-package.ts` is correct + +2. **Missing Deployment Addresses** + - Deploy contracts first: `npm run deploy:arbitrum` + - Verify `deployed_addresses.json` exists and contains all contracts + +3. **TypeChain Types Missing** + - Generate types: `npm run typechain` + - Check that `typechain-types/` directory exists + +4. **Network Not Supported** + - Add network configuration to `generate-package.ts` + - Update deployment scripts for the new network + +### Verification + +After generating the package: + +1. **Check Package Structure**: Verify all contracts are included +2. **Test Integration**: Use the package in a test project +3. **Verify Addresses**: Confirm contract addresses match deployments +4. **Test TypeScript**: Ensure TypeScript types work correctly + +## Publishing + +To publish the package to npm: + +1. **Build Package**: Generate the package for all networks +2. **Test Package**: Verify functionality in a test environment +3. **Update Version**: Increment version in `package.json` +4. **Publish**: Use `npm publish` in the package directory + ## Contributing To contribute to this package: diff --git a/ignition/modules/DCUContracts.ts b/ignition/modules/DCUContracts.ts index 9cd6afb..a58a590 100644 --- a/ignition/modules/DCUContracts.ts +++ b/ignition/modules/DCUContracts.ts @@ -20,7 +20,20 @@ export default buildModule("DCUContracts", (m) => { const dcuToken = m.contract("DCUToken", [rewardLogic]); // Deploy the DCURewardManager contract with DCUToken address - const dcuRewardManager = m.contract("DCURewardManager", [dcuToken]); + const dcuRewardManager = m.contract("DCURewardManager", [ + dcuToken, + nftCollection, + ]); + + // Deploy the DipNft contract with DCURewardManager address + const dipNft = m.contract("DipNft", [dcuRewardManager]); + + // Deploy the Submission contract + const submission = m.contract("Submission", [ + dcuToken, + rewardLogic, + "10000000000000000000", + ]); // 10 DCU default reward // Return all deployed contracts return { @@ -30,5 +43,7 @@ export default buildModule("DCUContracts", (m) => { rewardLogic, dcuToken, dcuRewardManager, + dipNft, + submission, }; }); diff --git a/package.json b/package.json index a0cf64c..40f2cf3 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,10 @@ "verify:all-arbitrum-testnet": "hardhat run scripts/verify-arbitrum.ts --network arbitrumSepolia", "gas:compare": "hardhat run scripts/gas-comparison.ts", "typechain": "hardhat typechain", - "clean": "hardhat clean" + "clean": "hardhat clean", + "generate-package": "ts-node scripts/generate-package.ts", + "generate-package:arbitrum": "ts-node scripts/generate-package.ts arbitrum", + "generate-package:arbitrum-sepolia": "ts-node scripts/generate-package.ts arbitrum-sepolia" }, "dependencies": { "@openzeppelin/contracts": "^5.2.0", diff --git a/scripts/deploy-arbitrum.ts b/scripts/deploy-arbitrum.ts index dab3e91..9de0be1 100644 --- a/scripts/deploy-arbitrum.ts +++ b/scripts/deploy-arbitrum.ts @@ -65,6 +65,14 @@ async function main() { const dcuRewardManagerAddress = dcuRewardManager.address; console.log("DCURewardManager deployed to:", dcuRewardManagerAddress); + // Deploy NFTCollection + console.log("Deploying NFTCollection..."); + const NFTCollection = await ethers.getContractFactory("NFTCollection"); + const nftCollection = await NFTCollection.deploy(); + await nftCollection.deployed(); + const nftCollectionAddress = nftCollection.address; + console.log("NFTCollection deployed to:", nftCollectionAddress); + // Deploy DipNft with the reward manager address console.log("Deploying DipNft..."); const DipNft = await ethers.getContractFactory("DipNft"); @@ -73,6 +81,18 @@ async function main() { const dipNftAddress = dipNft.address; console.log("DipNft deployed to:", dipNftAddress); + // Deploy Submission contract + console.log("Deploying Submission..."); + const Submission = await ethers.getContractFactory("Submission"); + const submission = await Submission.deploy( + dcuTokenAddress, + rewardLogicAddress, + ethers.utils.parseEther("10") // Default reward amount: 10 DCU + ); + await submission.deployed(); + const submissionAddress = submission.address; + console.log("Submission deployed to:", submissionAddress); + // Update NFT collection references in both contracts console.log("Updating NFT collection in RewardLogic..."); await rewardLogic.setNFTCollection(dipNftAddress); @@ -90,6 +110,8 @@ async function main() { DCUStorage: dcuStorageAddress, DCURewardManager: dcuRewardManagerAddress, DipNft: dipNftAddress, + NFTCollection: nftCollectionAddress, + Submission: submissionAddress, network: (await ethers.provider.getNetwork()).name, chainId: Number((await ethers.provider.getNetwork()).chainId), deployedAt: new Date().toISOString(), diff --git a/scripts/generate-package.ts b/scripts/generate-package.ts index 64a587f..bcbbf3f 100644 --- a/scripts/generate-package.ts +++ b/scripts/generate-package.ts @@ -70,6 +70,8 @@ async function main() { { name: "DCUStorage", path: "DCUStorage.sol" }, { name: "DCURewardManager", path: "DCURewardManager.sol" }, { name: "DipNft", path: "tokens/DipNft.sol" }, + { name: "NFTCollection", path: "tokens/NFTCollection.sol" }, + { name: "Submission", path: "Submission.sol" }, ]; // Read deployment addresses