Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 188 additions & 12 deletions docs/CONTRACT_PACKAGE.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -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 <network-name>
```

### Package Structure

The generated package will have the following structure:

```
package/
├── package.json
├── index.js
├── index.d.ts
└── <network-name>/
├── 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
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
```

Expand All @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
17 changes: 16 additions & 1 deletion ignition/modules/DCUContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -30,5 +43,7 @@ export default buildModule("DCUContracts", (m) => {
rewardLogic,
dcuToken,
dcuRewardManager,
dipNft,
submission,
};
});
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
22 changes: 22 additions & 0 deletions scripts/deploy-arbitrum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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);
Expand All @@ -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(),
Expand Down
2 changes: 2 additions & 0 deletions scripts/generate-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down