Skip to main content

Security, Audits & Contracts

MINERAL Protocol has undergone three rounds of independent security audits. All contracts are non-upgradeable, open-source, and verified on Basescan.


Audit History​

Three Audit Rounds​

RoundScopeResultKey Findings
V1 AuditFull protocol (10 contracts)4 findings, all fixedInitial comprehensive review
V2 AuditFix verification + new analysisAll V1 fixes verifiedVRF timeout, timelock, claim rounding
V3 AuditFinal review202 checks passed, 0 failedNo-winner rollover, surplus sweep

V1 Findings (All Resolved)​

IDSeverityFindingResolution
BM-H-01HighVRF liveness concernreRequestRandomness() with 300-block timeout
BM-M-01MediumAdmin address changes lack timelock1-day timelock on all admin address updates
BM-L-01LowClaim rounding dustLast claimer receives remainder
PKG-I-01InfoPackage completenessDocumentation improved

V2 Verification​

All V1 fixes independently verified:

  • VRF timeout recovery tested and confirmed
  • Timelock mechanism validated (queue → wait 1 day → apply)
  • Claim rounding edge cases resolved

V3 Findings (All Resolved)​

IDSeverityFindingResolution
BM-M-NEW-01MediumNo-winner rounds could lock fundsRollover to Motherlode pool
BM-I-NEW-01InfoContract accepts arbitrary ETHreceive() now reverts, surplus sweep added

Final V3 Result​

Total checks: 202
Passed: 202
Failed: 0
Previous fixes verified: 13/13

Contract Addresses​

All contracts deployed on Base L2 (Chain ID: 8453)

ContractAddressBasescan
Token (MINERAL)TBDTBD
AuctionMiningTBDTBD
BlockMiningTBDTBD
EmissionsControllerTBDTBD
RefineVaultTBDTBD
StakingVaultTBDTBD
BuybackVaultTBDTBD
BuybackExecutorTBDTBD
AutoLPVaultTBDTBD
AutoLPExecutorTBDTBD

Addresses will be filled after mainnet deployment. All contracts will be verified on Basescan with full source code.


VRF Configuration​

ParameterValueDescription
ProviderChainlink VRF v2.5Industry-standard oracle
CoordinatorTBDChainlink VRF Coordinator on Base
Key HashTBDVRF proving key identifier
Subscription IDTBDPre-funded Chainlink subscription
Request ConfirmationsTBDBlock confirmations before fulfillment
Callback Gas LimitTBDGas budget for VRF callback
Native PaymentTBDETH or LINK for VRF fees
Timeout300 blocks (~10 min)After which re-request is allowed

VRF Verification​

Anyone can verify VRF integrity:

  1. Each round's randomnessRequestId is stored on-chain
  2. Chainlink submits a cryptographic proof with the random word
  3. The VRF Coordinator verifies the proof before forwarding to BlockMining
  4. All VRF events (RandomnessRequested, RandomnessFulfilled) are indexable

Security Architecture​

Defense in Depth​

MINERAL implements multiple layers of security:

Layer 1: Smart Contract Design
├── Non-upgradeable (immutable after deployment)
├── Minimal external dependencies (OpenZeppelin only)
├── Pull-based payments (reentrancy prevention)
└── One-time wiring (critical addresses set once)

Layer 2: Access Control
├── Ownable2Step (two-step ownership transfer)
├── 1-day timelock on admin address changes
├── Keeper-gated executor functions
└── Pausable mining (emergency stop)

Layer 3: Economic Safety
├── Anti-sandwich protection (maxPrice parameter)
├── Slippage protection on swaps
├── Deadline enforcement on trades
├── Flash-loan prevention (2-day claim cooldown)

Layer 4: Liveness Guarantees
├── VRF timeout recovery (300 blocks)
├── Permissionless settlement (anyone can call settle)
├── Permissionless reward pushing
├── No-winner rollover (no locked funds)

Layer 5: Accounting Integrity
├── Tracked balance (all obligations on-chain)
├── Surplus detection and recovery
├── Last claimer gets remainder (no dust)
├── Outstanding claims tracking

Specific Security Features by Contract​

Token.sol​

FeatureDetail
Hard captotalSupply + amount <= CAP enforced on every mint
One-time mintersetMinter() can only be called once
Contract-only minterMinter must have code (prevents EOA)
Initial allocation guardLP + Dev cannot exceed 10% of cap
Two-step ownershipOwnable2Step

AuctionMining.sol​

FeatureDetail
ReentrancyGuardAll state-modifying functions
Pull-based ETHPrevious operator payments via pendingEth
Anti-sandwichmaxPrice parameter on mine
PausableOwner can halt mining
Pool target max pricePrevents forced pool execution at unfavorable prices
CooldownOptional minMineInterval between mines
Epoch-spanning accuracyGeometric series for cross-epoch emission calculation

BlockMining.sol​

FeatureDetail
Chainlink VRF v2.5Tamper-proof random winner selection
VRF timeout recovery300-block permissionless re-request
VRF config protectionCannot change config during active request
No-winner rolloverEmpty winning square → funds to Motherlode
Last claimer remainderNo dust stranded
1-day timelockAdmin address changes delayed 24 hours
Surplus sweepTimelocked recovery of force-sent ETH
Tracked balanceAll obligations accounted on-chain
receive() revertsDirect ETH transfers rejected
Deploy boundsMIN_DEPLOY (0.001 ETH) to MAX_DEPLOY (100 ETH)

StakingVault.sol​

FeatureDetail
2-day claim cooldownPrevents flash-loan reward siphoning
SafeERC20Safe token transfer handling
ETH bufferNo funds lost during bootstrap (zero stakers)
receive() revertsMust use fundRewards()

BuybackExecutor.sol & AutoLPExecutor.sol​

FeatureDetail
Keeper-gatedOnly authorized keepers can execute
Minimum 1 keeperCannot remove the last keeper
Balance verificationPre/post swap balance check
Slippage protectionminTokensOut parameter
DeadlineReverts if block.timestamp > deadline
Router must be contractPrevents EOA manipulation
Approval revocationRouter approval zeroed after LP add

Immutability​

All MINERAL contracts are non-upgradeable. There are no proxy patterns, no delegatecall, and no self-destruct mechanisms.

Once deployed:

  • Contract code cannot be changed
  • Core parameters (revenue splits, grid size, VRF odds) are constants or immutables
  • No admin function can modify the fundamental protocol mechanics

What the Owner CAN Do​

ActionContractTimelock
Pause/unpause miningAuctionMining, BlockMiningImmediate
Update VRF configBlockMiningBlocked during active request
Change staking vault addressBlockMining1-day timelock
Change treasury addressBlockMining1-day timelock
Queue surplus sweepBlockMining1-day timelock
Update refine fee (max 50%)RefineVaultImmediate
Update keeper listExecutorsImmediate
Update router addressExecutorsImmediate
Schedule emission rate changesEmissionsControllerMax 8 epochs ahead

What the Owner CANNOT Do​

ActionReason
Mint tokens beyond capHard-coded in Token.sol
Change revenue splitsImmutable in constructors
Change grid sizeConstant (25)
Change Motherlode oddsConstant (1/625)
Change round durationConstant (30 blocks)
Upgrade contractsNo proxy pattern
Access user fundsPull-based, user-initiated claims
Manipulate VRF resultsChainlink external oracle
Change token capImmutable

Open Source​

All smart contract source code is publicly available:

RepositoryContent
GitHub (TBD)Full source code, tests, deployment scripts
BasescanVerified source for all deployed contracts

Test Suite​

MetricValue
Test files14+
Individual tests45+ (all passing)
Test frameworkFoundry (Forge)
CoverageAll core functions, edge cases, and audit findings

Audit Reports​

Full audit reports are available:

ReportLink
V1 Audit ReportTBD
V2 Audit ReportTBD
V3 Audit ReportTBD

Bug Bounty​

A bug bounty program via Immunefi is planned for post-launch.

SeverityBounty Range
CriticalTBD
HighTBD
MediumTBD
LowTBD

How to Verify​

Verify Contracts on Basescan​

  1. Go to Basescan
  2. Enter contract address
  3. Click "Contract" tab → "Read Contract"
  4. Verify parameters match this documentation

Verify VRF Randomness​

  1. Find a settled round's randomnessRequestId
  2. Check Chainlink VRF explorer for the request
  3. Verify the proof was submitted by the Chainlink Coordinator
  4. Confirm winningSquare = randomWord % 25

Verify Revenue Splits​

  1. Read contract constants on Basescan:
    • AuctionMining: bpsPrevOperator, bpsBuyback, bpsStaking, bpsAutoLP, bpsDevFee
    • BlockMining: WINNER_BPS, MOTHERLODE_BPS, STAKING_BPS, TREASURY_BPS
  2. Confirm they sum to 10,000 (100%)

Verify Token Cap​

  1. Read Token.CAP() on Basescan → should return 21,000,000 * 10^18