Skip to content

RaymondAbiola/JUDGE-Token-Contract

Repository files navigation

JUDGE CONTRACTS

Summary

The JudgeToken ecosystem is a modular set of contracts thats includes the following:

  • JudgeToken: This is the ERC20 token contract that defines the rules for the JUDGE governance token.
  • JudgeTreasury: This is the project safe treasury that does funding for the staking rewards, team. Also functions as a bank for fees collected from misplaced tokens.
  • JudgeStaking: Contract with defined rules for staking and pays out rewards in JudgeToken. Open to anyone.
  • RewardsManager: This is the rewards distributor contract for base and bonus rewards handling.

The contracts were built with OpenZeppelin Access control for role based administration and also includes robust recovery systems for accidental transfers of ERC20 tokens to any of the Judge Project contracts expect the token contract. It is assumed that users are unlikely to have interactions with the token contract on a technical level

Contracts Overview

1. JudgeToken

ERC20 token with the following details:

  • Max Supply: 500_000_000 JUDGE
  • Burnable
  • ERC20Permit (gasless approvals)
  • ERC20Votes: Delegation style governance

The JudgeToken contract defines allocation for:

  • Staking Rewards Allocation
  • Team Allocation

2. JudgeTreasury

Acts as the Bank contract for the ecosystem

Features:

  • Can mint tokens to self
  • Can fund rewards manager contracts with staking base rewards
  • Handles team funding too
  • Supports sending bonus rewards to the Reward Manager contract.
    NOTE: Bonus rewards can only be sent to the rewards manager contract if the base quarterly reward for the current quarter has been paid. A minimum of 100k blocks can be set for bonus duration.
  • Includes recovery function for JUDGE and other ERC20 tokens. A defined fee is paid for token recovery.

3. Rewards Manager

Distributes rewards to stakers in the JudgeStaking contract whenever a claim or withdrawal related functions are called by the a staker

Handles:

  • Payment of quarterly base rewards.
  • Payment of optional quarterly bonus rewards
  • Provides JudgeStaking with the hooks below to enable claim:
    sendRewards()
    sendBonus()
  • Includes recovery function for JUDGE and other ERC20 tokens. A defined fee is paid for token recovery.

4. Judge Staking

This is the core staking contract where users can lock their JUDGE tokens to earn pro-rata rewards

Reward Accounting:

  • It uses accJudgePerShare and accBonusJudgePerShare to calculate stake earnings per share over a number of blocks Key Functions:
  • The deposit() function allows any address to participate in the staking contract by staking JUDGE tokens. They simply input a stake amount and a lockup duration to create a stake.
  • Users can use the claimRewards() function to withdraw their rewards while still having their stakes in the pool
  • The withdraw() function when called claims pending rewards and withdraws specified amount for the target stake to the user wallet. Calling this function is not possible until the stake at the desired index is matured. Matured stakes will keep receiving a pro rata share of rewards.
  • The withdrawAll() function when called claims pending rewards and withdraws all the desired stake index balance to the user wallet. Calling this function is also not possible until the stake matures.
  • The earlyWithdraw() function when called claims pending rewards and withdraws specified amount for the target stake to the user wallet (penalty applies). Learn more about the penalty.
  • The updatePool() function when called loops through missed quarters starting from the lastRewardBlock. For each call, the pool loops through a maximum of 4 quarters. If the pool has many stale quarters, the updatePool() can be called repeatedly to update the staking pool to the current block.
  • It includes the token recovery function (recovery fee applies). Learn more about recovery fees.

Integration:

  • Interacts with the Rewards Manager contract to distribute base and bonus rewards. Any time a user initiates a claim or a withdrawal, the staking contract calls the sendRewards() and sendBonus() if the pending baseReward and pending bonusRewards are greater than 0.

Security Features

  • Built with OpenZeppelin Access Control contract to support role based permissions across all contracts.
  • Multiple gatekeepers and modifiers to handle edge cases.
  • Follows the CEI security order for solidity contracts.
  • Recovery functions for all ERC20 tokens in all contracts except JUDGE Token contract itself.
  • Reentrancy proof

Deployment Notes

The 4 contracts somewhat have circular dependency. You can correctly deploy them in this order:

  • JudgeToken.sol
  • RewardsManager.sol
  • JudgeStaking.sol
  • JudgeTreasury.sol

    Grant neccesary roles across contracts to allow secure and seamless interactions. Some examples below:
  • Grant Judge Treasury address the MINTER_ROLE() and ALLOCATION_MINTER_ROLE() from Judge Token contract
  • Grant Jusge Staking address the REWARDS_DISTRIBUTOR_ROLE()

    Alternatively run the deployment script in this repo to seamlessly deploy all 4 contracts

Getting Started (Developer)

Pre-requisites

  • Install foundry on linux or WSL for windows
$ curl -L https://foundry.paradigm.xyz | bash
  • Clone Repo
$ git clone https://github.com/raymondabiola/JUDGE-Token-Contract.git
  • Change directory
$ cd JUDGE-Token-Contract
  • Install solidity dependencies (OZ version 5.3.0 most suitable for this project)
$ forge install OpenZeppelin/openzeppelin-contracts@v5.3.0
  • Compile Contracts
$ forge build
  • Run test suite
$ forge test

Deploy Contracts
Create a .env file in the project root and input the following inside it:

  • INFURA_API_URL, PRIVATE_KEY, ETHERSCAN_API_KEY
  • The infura api url looks like this INFURA_API_URL=https://sepolia.infura.io/v3/YOUR_PROJECT_ID. You can get your infura PROJECT_ID from the Infura Website
  • You can get your etherscan api key from EtherScan Website The deploy script is found in scripts/DeployJudgeContracts.sol
  • Run the script command below to simulate deployment on sepolia testnet
$ forge script script/DeployJudgeContracts.s.sol:DeployJudgeContracts --rpc-url $INFURA_API_URL
  • Run the script command below to actually deploy and also verify the contracts on the sepolia testnet
$ forge script script/DeployJudgeContracts.s.sol:DeployJudgeContracts \
  --rpc-url $INFURA_API_URL \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --verify \
  --etherscan-api-key $ETHERSCAN_API_KEY \
  --chain-id 11155111

The script will:

  • Deploy all contracts, verify their source code, set key parameters on each contract,and grant neccesary roles to deployer address.

Deployed Instances on Sepolia Testnet

Help

$ forge --help
$ anvil --help
$ cast --help

License

MIT

Built With

Solidity
Foundry
Openzeppelin

Author

Built with 🤍 by Raymond Abiola
Feel free to follow my Github account or fork this repo for learning and testing.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors