A production-oriented Solidity project implementing an NFT collection and a staking-based reward distribution system.
- NFTCollection:
0x6CA691947f144b33135889b7855e47D30a56c90F - GovernanceToken:
0x380E2C6613d99461f47e522f3DE17914d46e2546 - NFTStaking:
0x8D2a23889f0A677Ee13C2E66f16aA931AeaE25A5
This project consists of three core components:
- ERC721A NFT Collection
- NFT Staking Contract
- ERC20 Reward Token
The system allows users to stake NFTs and earn rewards over time using a gas-efficient accumulator-based model.
Gas-efficient ERC721A-based NFT contract.
Features:
- Whitelist mint (Merkle proof)
- Public mint
- Max supply enforcement
- Per-wallet mint limits
- Reveal mechanism (hidden → baseURI + tokenId)
- ERC2981 royalties
- Pause control
- Secure ETH withdrawal
Core staking contract responsible for reward distribution.
Features:
- Stake / unstake NFTs (batch supported)
- Per-second reward emission
- Accumulator-based reward accounting (O(1))
- Per-user staking tracking
- Claimable rewards
- Role-based reward rate updates
ERC20 reward token with:
- capped max supply
- role-based minting (
MINTER_ROLE) - mint controlled by staking contract
Rewards are distributed using a cumulative index:
accRewardPerShare→ total rewards per staked NFTrewardCheckpoint→ user-specific accounting checkpointpendingRewards→ stored rewards not yet claimed
Core formula:
earned = pendingRewards + ((balance * accRewardPerShare) / PRECISION - rewardCheckpoint)
This design:
- avoids looping over users
- scales efficiently with many stakers
- mirrors patterns used in production DeFi systems
- update pool state
- settle user rewards
- transfer NFTs to contract
- update balances
- update reward checkpoint
- update pool
- settle rewards
- update balances
- transfer NFTs back to user
- update pool
- settle rewards
- mint ERC20 rewards to user
Covers:
- NFT minting, limits, and pricing
- Whitelist logic
- Staking flows (stake / unstake / claim)
- Reward distribution correctness
- Access control and failure cases
The system is tested under randomized sequences of actions to ensure state consistency.
totalSupplyconsistency- User balances never exceed wallet limits
- ETH accounting (including forced ETH scenarios)
tokenURIcorrectness before and after reveal
totalStaked == sum(balanceOf(users))- Mapping ↔ array consistency
- NFT custody correctness
- No duplicate tokens per user
- Reward accounting correctness
- Reentrancy tested using a malicious ERC721 mock
- Callback attacks during
safeTransferFromare prevented
| Contract | Coverage |
|---|---|
| NFTCollection | 100% |
| GovernanceToken | 100% |
| NFTStaking | ~99% lines / ~94% branches |
- Reentrancy protection (
ReentrancyGuard) - Direct NFT transfer attack prevented (
operatorcheck inonERC721Received) - Safe reward accounting (no double counting)
- Role-based access control (
AccessControl) - Production admin model designed around multisig ownership/control
- ETH withdrawal handles unexpected ETH transfers
- Failure handling for rejecting recipients
Privileged roles are designed to be controlled by a multisig wallet in production.
Recommended setup:
NFTCollectionowner → multisigGovernanceTokenDEFAULT_ADMIN_ROLE→ multisigGovernanceTokenMINTER_ROLE→NFTStakingNFTStakingDEFAULT_ADMIN_ROLE→ multisigNFTStakingREWARD_MANAGER_ROLE→ multisig
User actions remain permissionless:
stakeunstakeclaim
This keeps user interactions immediate while admin actions require multisig approval.
- Each NFT represents 1 staking unit
- Reward distribution is time-based (
rewardPerSecond) - System avoids loops over users (gas-efficient)
- Uses patterns similar to MasterChef-style contracts
src/
nft/
NFTCollection.sol
staking/
NFTStaking.sol
token/
GovernanceToken.sol
interfaces/
- Contracts are verified on Etherscan
- Admin roles are intended to be transferred to a multisig wallet
- Current deployment may still be controlled by a deployer EOA
git clone https://github.com/theonomiMC/NFTCollection.git
cd NFTCollection
forge install
forge build
forge test
forge coverage- Integration tests (NFT ↔ staking ↔ rewards)
- Frontend integration