Skip to content
Open
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
5 changes: 4 additions & 1 deletion contracts/TruthBounty.sol
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ contract TruthBounty is AccessControl, ReentrancyGuard, Pausable, GovernanceOwna

_setRoleAdmin(RESOLVER_ROLE, ADMIN_ROLE);
_setRoleAdmin(TREASURY_ROLE, ADMIN_ROLE);
_setRoleAdmin(PAUSER_ROLE, ADMIN_ROLE);
_setRoleAdmin(PAUSER_ROLE, ADMIN_ROLE);
}

_initializeGovernance(
_governanceController,
Expand Down Expand Up @@ -425,6 +426,8 @@ contract TruthBounty is AccessControl, ReentrancyGuard, Pausable, GovernanceOwna
uint256 slashedAmount = _percentOf(v.stakeAmount, slashPercent);
uint256 returnAmount = v.stakeAmount - slashedAmount;

v.stakeReturned = true;

v.stakeReturned = true;
verifierStakes[msg.sender].activeStakes -= v.stakeAmount;

Expand Down
13 changes: 12 additions & 1 deletion contracts/governance/GovernanceHooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,18 @@ interface GovernanceHooks {
MIN_STAKE_MULTIPLIER,
MAX_STAKE_MULTIPLIER,
MIN_GOVERNANCE_MULTIPLIER,
MAX_GOVERNANCE_MULTIPLIER
MAX_GOVERNANCE_MULTIPLIER,
// TokenomicsEngine parameters (60+)
VERIFIER_REWARD_ALLOCATION_BPS,
TREASURY_RESERVE_ALLOCATION_BPS,
ECOSYSTEM_INCENTIVE_ALLOCATION_BPS,
GOVERNANCE_INCENTIVE_ALLOCATION_BPS,
PROTOCOL_DEVELOPMENT_ALLOCATION_BPS,
EMERGENCY_RESERVE_ALLOCATION_BPS,
EMISSION_LIMIT,
REWARD_MULTIPLIER,
TREASURY_RESERVE_TARGET_BPS,
PROTOCOL_FEE_ALLOCATION_BPS
}

// ============ Events ============
Expand Down
1 change: 1 addition & 0 deletions contracts/reward/RewardEngine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ contract RewardEngine is ReentrancyGuard, Pausable, GovernanceOwnable, ITruthBou
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant DISTRIBUTOR_ROLE = keccak256("DISTRIBUTOR_ROLE");
bytes32 public constant REWARD_ENGINE_ROLE = keccak256("REWARD_ENGINE_ROLE");

// ============ Constants ============

Expand Down
194 changes: 194 additions & 0 deletions contracts/tokenomics/AllocationPolicies.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "./ITokenomicsEngine.sol";

/**
* @title AllocationPolicies
* @notice Pure mathematical library for tokenomics distribution policies.
* @dev Contains deterministic, testable allocation functions.
*
* Supported policies:
* - proportional: equal-percentage split across categories
* - reputation-weighted: verifier share modulated by reputation score
* - stake-weighted: verifier share modulated by active stake
* - governance-incentives: reserved for future governance reward distribution
*
* Referral incentives can be added later by extending this library
* without modifying the core TokenomicsEngine.
*/
library AllocationPolicies {

uint256 public constant BPS_DENOMINATOR = 10_000;

// ============ Proportional Allocation ==========

function calculateProportionalAllocation(
uint256 amount,
ITokenomicsEngine.SourceAllocation memory config
)
internal
pure
returns (ITokenomicsEngine.AllocationShares memory shares)
{
uint256 remaining = amount;

shares.verifierRewards = _bpsShare(amount, config.verifierRewardsBPS);
remaining -= shares.verifierRewards;

shares.treasuryReserve = _bpsShare(amount, config.treasuryReserveBPS);
remaining -= shares.treasuryReserve;

shares.ecosystemIncentives = _bpsShare(amount, config.ecosystemIncentivesBPS);
remaining -= shares.ecosystemIncentives;

shares.governanceIncentives = _bpsShare(amount, config.governanceIncentivesBPS);
remaining -= shares.governanceIncentives;

shares.protocolDevelopment = _bpsShare(amount, config.protocolDevelopmentBPS);
remaining -= shares.protocolDevelopment;

shares.emergencyReserve = remaining;

return shares;
}

// ============ Reputation-Weighted Allocation ==========

function calculateReputationWeightedAllocation(
uint256 amount,
ITokenomicsEngine.SourceAllocation memory config,
uint256 totalReputationScore
)
internal
pure
returns (ITokenomicsEngine.AllocationShares memory shares)
{
uint256 remaining = amount;

shares.verifierRewards = _bpsShare(amount, config.verifierRewardsBPS);
remaining -= shares.verifierRewards;

shares.treasuryReserve = _bpsShare(amount, config.treasuryReserveBPS);
remaining -= shares.treasuryReserve;

shares.ecosystemIncentives = _bpsShare(amount, config.ecosystemIncentivesBPS);
remaining -= shares.ecosystemIncentives;

shares.governanceIncentives = _bpsShare(amount, config.governanceIncentivesBPS);
remaining -= shares.governanceIncentives;

shares.protocolDevelopment = _bpsShare(amount, config.protocolDevelopmentBPS);
remaining -= shares.protocolDevelopment;

shares.emergencyReserve = remaining;

if (totalReputationScore > 0) {
uint256 reputationScaled = (shares.verifierRewards * totalReputationScore) / (totalReputationScore + 1e18);
shares.verifierRewards = reputationScaled;
}

return shares;
}

// ============ Stake-Weighted Allocation ==========

function calculateStakeWeightedAllocation(
uint256 amount,
ITokenomicsEngine.SourceAllocation memory config,
uint256 totalActiveStake
)
internal
pure
returns (ITokenomicsEngine.AllocationShares memory shares)
{
uint256 remaining = amount;

shares.verifierRewards = _bpsShare(amount, config.verifierRewardsBPS);
remaining -= shares.verifierRewards;

shares.treasuryReserve = _bpsShare(amount, config.treasuryReserveBPS);
remaining -= shares.treasuryReserve;

shares.ecosystemIncentives = _bpsShare(amount, config.ecosystemIncentivesBPS);
remaining -= shares.ecosystemIncentives;

shares.governanceIncentives = _bpsShare(amount, config.governanceIncentivesBPS);
remaining -= shares.governanceIncentives;

shares.protocolDevelopment = _bpsShare(amount, config.protocolDevelopmentBPS);
remaining -= shares.protocolDevelopment;

shares.emergencyReserve = remaining;

if (totalActiveStake > 0) {
uint256 stakeScaled = (shares.verifierRewards * totalActiveStake) / (totalActiveStake + 1e18);
shares.verifierRewards = stakeScaled;
}

return shares;
}

// ============ Governance Incentive Allocation ==========

function calculateGovernanceIncentiveAllocation(
uint256 amount,
ITokenomicsEngine.SourceAllocation memory config
)
internal
pure
returns (ITokenomicsEngine.AllocationShares memory shares)
{
uint256 remaining = amount;

shares.verifierRewards = _bpsShare(amount, config.verifierRewardsBPS);
remaining -= shares.verifierRewards;

shares.treasuryReserve = _bpsShare(amount, config.treasuryReserveBPS);
remaining -= shares.treasuryReserve;

shares.ecosystemIncentives = _bpsShare(amount, config.ecosystemIncentivesBPS);
remaining -= shares.ecosystemIncentives;

shares.governanceIncentives = _bpsShare(amount, config.governanceIncentivesBPS);
remaining -= shares.governanceIncentives;

shares.protocolDevelopment = _bpsShare(amount, config.protocolDevelopmentBPS);
remaining -= shares.protocolDevelopment;

shares.emergencyReserve = remaining;

return shares;
}

// ============ Validation Helpers ==========

function validateAllocationConfig(ITokenomicsEngine.SourceAllocation memory config)
internal
pure
returns (bool valid, string memory reason)
{
if (!config.active) {
return (false, "allocation inactive");
}

uint256 totalBPS = config.verifierRewardsBPS
+ config.treasuryReserveBPS
+ config.ecosystemIncentivesBPS
+ config.governanceIncentivesBPS
+ config.protocolDevelopmentBPS
+ config.emergencyReserveBPS;

if (totalBPS != BPS_DENOMINATOR) {
return (false, "basis points do not sum to 10000");
}

return (true, "");
}

// ============ Internal Helpers ==========

function _bpsShare(uint256 amount, uint256 bps) internal pure returns (uint256) {
return (amount * bps) / BPS_DENOMINATOR;
}
}
Loading