Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
237b653
feat: implement Arbitrum deployment and verification process
fatiudeen Apr 22, 2025
7a5d8ca
feat: add GitHub Actions workflow for deploying and verifying smart c…
fatiudeen Apr 22, 2025
46aff7f
docs: add CONTRACT_PACKAGE.md for DeCleanup Network smart contracts
fatiudeen Apr 22, 2025
4edf9aa
fix: update branch name in GitHub Actions workflow and correct import…
fatiudeen Apr 22, 2025
06326a5
chore: update Node.js version in GitHub Actions workflow from 20 to 22
fatiudeen Apr 22, 2025
671c3e5
chore: update Node.js version in GitHub Actions workflow from 18 to 22
fatiudeen Apr 22, 2025
608a24e
chore: update npm install command in GitHub Actions workflow to use -…
fatiudeen Apr 22, 2025
811c6e4
chore: add viem dependency to package.json and package-lock.json
fatiudeen Apr 22, 2025
6f44594
Merge pull request #3 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
9d06048
chore: integrate TypeChain into Hardhat configuration and update pack…
fatiudeen Apr 22, 2025
59beabb
chore: clean up package.json and package-lock.json by removing unused…
fatiudeen Apr 22, 2025
5a37891
Merge pull request #4 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
a91140e
chore: update .gitignore, refine GitHub Actions workflow, and enhance…
fatiudeen Apr 22, 2025
1ad5782
Merge pull request #5 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
6e90f94
chore: add contract compilation step to GitHub Actions workflow
fatiudeen Apr 22, 2025
d307243
Merge pull request #6 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
34dc85e
chore: add custom versioning and GitHub release step to deployment wo…
fatiudeen Apr 22, 2025
e4af761
Merge pull request #7 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
71ca284
fix: handle initial versioning in update-version script to start at 1…
fatiudeen Apr 22, 2025
db8db42
Merge pull request #8 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
ad70a7c
chore: simplify version handling in deployment workflow and update ou…
fatiudeen Apr 22, 2025
bff70e1
Merge pull request #9 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
acc5a21
chore: add version field to package.json to specify project version a…
fatiudeen Apr 22, 2025
691d8ad
Merge pull request #10 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
55d8c25
chore: comment out GitHub release step in deployment workflow
fatiudeen Apr 22, 2025
150829d
Merge pull request #11 from fatiudeen/feat/installable-abi
fatiudeen Apr 22, 2025
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
13 changes: 8 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Network RPC URLs - Get this from Infura or Alchemy
SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/<INFURA_API_KEY>
ARBITRUM_ONE_RPC_URL=
ARBITRUM_SEPOLIA_RPC_URL=

# Private key for deployment (without 0x prefix)
# WARNING: Never commit your actual private key to git
PRIVATE_KEY=your_private_key_here
PRIVATE_KEY=

# Etherscan API Key - Required for contract verification
# Get this from https://etherscan.io/myapikey
ETHERSCAN_API_KEY=<ETHERSCAN_API_KEY>
# API keys for block explorers
ARBISCAN_API_KEY=

# Gas reporting flag (set to true to enable gas reporting)
REPORT_GAS=
144 changes: 144 additions & 0 deletions .github/workflows/deploy-contracts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
name: Deploy Smart Contracts

on:
push:
branches:
- master
paths:
- 'contracts/**'

workflow_dispatch:
inputs:
network:
description: 'Network to deploy to (testnet/mainnet)'
required: true
default: 'testnet'
type: choice
options:
- testnet
- mainnet
version:
description: 'Custom version to use (e.g., 1.0.0). Leave empty for auto-increment.'
required: false
type: string
default: ''

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
cache-dependency-path: 'package-lock.json'

- name: Install dependencies
run: npm install --legacy-peer-deps

- name: Compile contracts
run: npm run compile

- name: Generate TypeChain types
run: npm run typechain

- name: Deploy to Testnet
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.network == 'testnet')
run: npm run deploy:arbitrum-testnet
env:
ARBITRUM_SEPOLIA_RPC_URL: ${{ secrets.ARBITRUM_SEPOLIA_RPC_URL }}
PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }}
ARBISCAN_API_KEY: ${{ secrets.ARBISCAN_API_KEY }}

- name: Deploy to Mainnet
if: github.event_name == 'workflow_dispatch' && github.event.inputs.network == 'mainnet'
run: npm run deploy:arbitrum
env:
ARBITRUM_ONE_RPC_URL: ${{ secrets.ARBITRUM_ONE_RPC_URL }}
PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }}
ARBISCAN_API_KEY: ${{ secrets.ARBISCAN_API_KEY }}

- name: Verify Contracts on Testnet
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.network == 'testnet')
run: npm run verify:all-arbitrum-testnet
env:
ARBITRUM_SEPOLIA_RPC_URL: ${{ secrets.ARBITRUM_SEPOLIA_RPC_URL }}
ARBISCAN_API_KEY: ${{ secrets.ARBISCAN_API_KEY }}

- name: Verify Contracts on Mainnet
if: github.event_name == 'workflow_dispatch' && github.event.inputs.network == 'mainnet'
run: npm run verify:all-arbitrum
env:
ARBITRUM_ONE_RPC_URL: ${{ secrets.ARBITRUM_ONE_RPC_URL }}
ARBISCAN_API_KEY: ${{ secrets.ARBISCAN_API_KEY }}

- name: Upload Deployment Artifacts
uses: actions/upload-artifact@v4
with:
name: deployment-artifacts
path: |
scripts/deployed_addresses_arbitrum.json
typechain-types/
if-no-files-found: error

publish-package:
needs: deploy
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
cache-dependency-path: 'package-lock.json'
registry-url: 'https://registry.npmjs.org'

- name: Download Deployment Artifacts
uses: actions/download-artifact@v4
with:
name: deployment-artifacts
path: .

- name: Install dependencies
run: npm install --legacy-peer-deps

- name: Compile contracts
run: npm run compile

- name: Update package version
id: version
run: |
VERSION=$(npx ts-node scripts/update-version.ts)
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "NEW_VERSION=$VERSION" >> $GITHUB_ENV

- name: Generate Package
run: npx ts-node scripts/generate-package.ts

- name: Publish Package
run: |
cd package
npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
npm publish --access public
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

# - name: Create GitHub Release
# uses: softprops/action-gh-release@v1
# with:
# tag_name: v${{ env.NEW_VERSION }}
# name: Contracts v${{ env.NEW_VERSION }}
# body: |
# DeCleanup Network Smart Contracts Release
# - Deployed to ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.network == 'mainnet' && 'Arbitrum Mainnet' || 'Arbitrum Testnet' }}
# - Published to npm as @decleanup/contracts@${{ env.NEW_VERSION }}
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 2 additions & 2 deletions .github/workflows/test-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
node-version: '22'
cache: 'npm'

- name: Install dependencies
run: npm install
run: npm install --legacy-peer-deps

- name: Install bc
run: sudo apt-get install -y bc
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ node_modules
# Hardhat Ignition default folder for deployments against a local node
ignition/deployments/chain-31337
ignition/deployments
issues
issues
package
44 changes: 41 additions & 3 deletions contracts/RewardLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ contract RewardLogic is Ownable, IRewards {
IDCUToken public dcuToken;
INFTCollection public nftCollection;

// Authorization for external contracts
mapping(address => bool) public authorizedContracts;

// Constants
uint256 public constant NFT_CLAIM_REWARD = 10 ether; // 10 DCU for new NFT claims
uint256 public constant LEVEL_UPGRADE_REWARD = 10 ether; // 10 DCU for level upgrades
Expand Down Expand Up @@ -49,6 +52,16 @@ contract RewardLogic is Ownable, IRewards {
uint256 timestamp,
string reason
);

event NFTCollectionUpdated(
address indexed oldCollection,
address indexed newCollection
);

event ContractAuthorizationChanged(
address indexed contractAddress,
bool authorized
);

/**
* @dev Constructor sets the DCU token and NFT collection addresses
Expand All @@ -60,6 +73,28 @@ contract RewardLogic is Ownable, IRewards {
nftCollection = INFTCollection(_nftCollection);
}

/**
* @dev Set the NFT collection address
* @param _nftCollection Address of the new NFT collection contract
*/
function setNFTCollection(address _nftCollection) external onlyOwner {
require(_nftCollection != address(0), "Invalid NFT collection address");
address oldCollection = address(nftCollection);
nftCollection = INFTCollection(_nftCollection);
emit NFTCollectionUpdated(oldCollection, _nftCollection);
}

/**
* @dev Authorize or revoke a contract to call distributeDCU
* @param contractAddress The contract address to authorize
* @param authorized Whether to authorize or revoke
*/
function authorizeContract(address contractAddress, bool authorized) external onlyOwner {
require(contractAddress != address(0), "Invalid contract address");
authorizedContracts[contractAddress] = authorized;
emit ContractAuthorizationChanged(contractAddress, authorized);
}

/**
* @dev Calculate reward based on NFT holdings (base implementation)
* @param user Address of the user to calculate reward for
Expand Down Expand Up @@ -129,7 +164,10 @@ contract RewardLogic is Ownable, IRewards {
*/
function distributeDCU(address user, uint256 amount) external override {
// Only authorized contracts can call this function
require(msg.sender == address(nftCollection), "Only authorized contracts can call");
require(
msg.sender == address(nftCollection) || authorizedContracts[msg.sender],
"Only authorized contracts can call"
);

// Verify user through the reward manager if available
DCURewardManager rewardManager = DCURewardManager(address(0));
Expand All @@ -141,8 +179,8 @@ contract RewardLogic is Ownable, IRewards {
// Continue even if we can't get the reward manager
}

// If we have a reward manager, check eligibility
if (address(rewardManager) != address(0)) {
// If we have a reward manager and the caller is the NFT contract, check eligibility
if (address(rewardManager) != address(0) && msg.sender == address(nftCollection)) {
try rewardManager.getVerificationStatus(user) returns (
bool poiVerified,
bool nftMinted,
Expand Down
Loading