Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TreasureXRewards

Git Source

Inherits: Initializable, AccessControlUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable, ITreasureXRewards

Title: TreasureXRewards - Multi-Campaign Reward Claiming Contract

Author: ShareX Team

Upgradeable contract managing multiple reward campaigns, each with its own ERC20 token, claim window, and per-user allocations. Key Features:

  • Multiple campaigns in a single contract
  • Per-campaign ERC20 reward token
  • Time-controlled claim windows per campaign
  • Updatable per-user allocations
  • Gas-optimized storage (1 slot per campaign config, 1 slot per user allocation)

State Variables

_campaignCount

Total number of campaigns created

uint256 private _campaignCount;

_campaigns

Campaign ID => config (1 slot per campaign)

mapping(uint256 campaignId => CampaignConfigInternal config) private _campaigns;

_campaignActive

Campaign ID => whether campaign is active

mapping(uint256 campaignId => bool active) private _campaignActive;

_allocations

Campaign ID => user address => allocation (1 slot per user per campaign)

mapping(uint256 campaignId => mapping(address user => UserAllocationInternal info)) private
    _allocations;

_campaignTotalAllocated

Campaign ID => total allocated

mapping(uint256 campaignId => uint128 total) private _campaignTotalAllocated;

_campaignTotalClaimed

Campaign ID => total claimed

mapping(uint256 campaignId => uint128 total) private _campaignTotalClaimed;

__gap

Reserved storage gap for upgrades

uint256[44] private __gap;

Functions

validAddress

modifier validAddress(address addr);

validCampaign

modifier validCampaign(uint256 campaignId);

whenCampaignActive

modifier whenCampaignActive(uint256 campaignId);

whenClaimEnabled

Reason: Combined modifier checks both campaign active + time window in one call, saving gas vs two separate modifiers on the claim hot path.

modifier whenClaimEnabled(uint256 campaignId);

initialize

Initialize the rewards contract

function initialize(address admin_) external initializer validAddress(admin_);

Parameters

NameTypeDescription
admin_addressAdmin address with DEFAULT_ADMIN_ROLE

createCampaign

Create a new campaign with reward token and claim window

function createCampaign(address rewardToken, uint64 claimStartTime, uint64 claimEndTime)
    external
    override
    onlyRole(DEFAULT_ADMIN_ROLE)
    validAddress(rewardToken)
    returns (uint256 campaignId);

Parameters

NameTypeDescription
rewardTokenaddressERC20 token address for rewards
claimStartTimeuint64Timestamp when claims open
claimEndTimeuint64Timestamp when claims close

Returns

NameTypeDescription
campaignIduint256The ID of the newly created campaign

updateCampaignTime

Update claim window for a campaign

function updateCampaignTime(uint256 campaignId, uint64 claimStartTime, uint64 claimEndTime)
    external
    override
    onlyRole(DEFAULT_ADMIN_ROLE)
    validCampaign(campaignId);

Parameters

NameTypeDescription
campaignIduint256The campaign to update
claimStartTimeuint64New start timestamp
claimEndTimeuint64New end timestamp

setCampaignActive

Toggle campaign active status

function setCampaignActive(uint256 campaignId, bool active)
    external
    override
    onlyRole(DEFAULT_ADMIN_ROLE)
    validCampaign(campaignId);

Parameters

NameTypeDescription
campaignIduint256The campaign to update
activeboolWhether the campaign should be active

setAllocation

Set allocation for a single user in a campaign

function setAllocation(uint256 campaignId, address account, uint256 amount)
    external
    override
    onlyRole(DEFAULT_ADMIN_ROLE)
    validCampaign(campaignId)
    validAddress(account);

Parameters

NameTypeDescription
campaignIduint256The campaign ID
accountaddressThe user address
amountuint256The allocation amount

setAllocations

Set allocations for multiple users in a campaign

function setAllocations(
    uint256 campaignId,
    address[] calldata accounts,
    uint256[] calldata amounts
) external override onlyRole(DEFAULT_ADMIN_ROLE) validCampaign(campaignId);

Parameters

NameTypeDescription
campaignIduint256The campaign ID
accountsaddress[]Array of user addresses
amountsuint256[]Array of allocation amounts

withdrawTokens

Withdraw tokens from a campaign

function withdrawTokens(uint256 campaignId, uint256 amount)
    external
    override
    onlyRole(DEFAULT_ADMIN_ROLE)
    validCampaign(campaignId)
    nonReentrant;

Parameters

NameTypeDescription
campaignIduint256The campaign ID
amountuint256Amount to withdraw

pause

Pause the contract

function pause() external onlyRole(DEFAULT_ADMIN_ROLE);

unpause

Unpause the contract

function unpause() external onlyRole(DEFAULT_ADMIN_ROLE);

claim

Claim a specific amount from a campaign

function claim(uint256 campaignId, uint256 amount)
    external
    override
    nonReentrant
    whenNotPaused
    validCampaign(campaignId)
    whenClaimEnabled(campaignId);

Parameters

NameTypeDescription
campaignIduint256The campaign ID
amountuint256Amount to claim

claimAll

Claim all available tokens from a campaign

function claimAll(uint256 campaignId)
    external
    override
    nonReentrant
    whenNotPaused
    validCampaign(campaignId)
    whenClaimEnabled(campaignId);

Parameters

NameTypeDescription
campaignIduint256The campaign ID

getCampaign

Get campaign info

function getCampaign(uint256 campaignId)
    external
    view
    override
    validCampaign(campaignId)
    returns (CampaignInfo memory info);

Parameters

NameTypeDescription
campaignIduint256The campaign ID

Returns

NameTypeDescription
infoCampaignInfoCampaignInfo struct

getCampaignCount

Get total number of campaigns

function getCampaignCount() external view override returns (uint256);

Returns

NameTypeDescription
<none>uint256count The campaign count

getAllocation

Get allocation info for a user in a campaign

function getAllocation(uint256 campaignId, address account)
    external
    view
    override
    validCampaign(campaignId)
    returns (AllocationInfo memory info);

Parameters

NameTypeDescription
campaignIduint256The campaign ID
accountaddressThe user address

Returns

NameTypeDescription
infoAllocationInfoAllocationInfo struct

getClaimableAmount

Get claimable amount for a user in a campaign

function getClaimableAmount(uint256 campaignId, address account)
    external
    view
    override
    validCampaign(campaignId)
    returns (uint256);

Parameters

NameTypeDescription
campaignIduint256The campaign ID
accountaddressThe user address

Returns

NameTypeDescription
<none>uint256claimable Amount that can be claimed

isCampaignClaimActive

Check if a campaign’s claim period is active

function isCampaignClaimActive(uint256 campaignId)
    external
    view
    override
    validCampaign(campaignId)
    returns (bool);

Parameters

NameTypeDescription
campaignIduint256The campaign ID

Returns

NameTypeDescription
<none>boolactive True if claims are allowed

_setAllocation

Set allocation for a user in a campaign

function _setAllocation(uint256 campaignId, address account, uint256 amount) internal;

_claim

Process a claim for a user in a campaign

function _claim(uint256 campaignId, address user, uint256 amount) internal;

_getClaimableAmount

Get claimable amount for a user in a campaign

function _getClaimableAmount(uint256 campaignId, address account)
    internal
    view
    returns (uint256);

_isCampaignClaimActive

Check if campaign claim period is active (time-based only)

function _isCampaignClaimActive(uint256 campaignId) internal view returns (bool);

Structs

CampaignConfigInternal

Campaign config packed into 1 storage slot (29 bytes)

struct CampaignConfigInternal {
    address rewardToken; // 20 bytes
    uint64 claimStartTime; // 8 bytes
    uint32 claimEndTimeOffset; // 4 bytes - offset from startTime in seconds
    // Reason: Using offset saves 4 bytes vs storing full uint64,
    // supports durations up to ~136 years which is sufficient
}

UserAllocationInternal

User allocation packed into 1 storage slot (32 bytes)

struct UserAllocationInternal {
    uint128 allocated; // 16 bytes
    uint128 claimed; // 16 bytes
}