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

Foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.

Foundry consists of:

  • Forge: Ethereum testing framework (like Truffle, Hardhat and DappTools).
  • Cast: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
  • Anvil: Local Ethereum node, akin to Ganache, Hardhat Network.
  • Chisel: Fast, utilitarian, and verbose solidity REPL.

Documentation

https://book.getfoundry.sh/

Usage

Build

$ forge build

Test

$ forge test

Format

$ forge fmt

Gas Snapshots

$ forge snapshot

Anvil

$ anvil

Deploy

$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>

Cast

$ cast <subcommand>

Help

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

Contents

IGenesisExpedition

Git Source

Author: luoyhang003

Interface for the Genesis Expedition core game contract.

This interface defines:

  • Core structs for player inventory and GoldenStone mechanics.
  • Events emitted during forging, GoldenStone operations, lotteries, and admin updates.
  • Functions for forging, distributing resources, querying state, and validating signatures.

Functions

forge

Forges raw stones into gems using a valid EIP-712 signature.

Validates:

  • player identity
  • nonce uniqueness
  • array length
  • signature validity
  • deadline Consumes hammers & raw stones, distributes gems, generates lottery codes.
function forge(
    address _player,
    uint256 _nonce,
    uint256 _amount,
    uint256[] memory _gems,
    uint256 _deadline,
    bytes calldata _signature
) external;

Parameters

NameTypeDescription
_playeraddressAddress performing the forge.
_nonceuint256Unique nonce preventing replay.
_amountuint256Raw stones to forge.
_gemsuint256[]Gem rewards for each stone.
_deadlineuint256Signature expiration timestamp.
_signaturebytesEIP-712 signature from master signer.

distributeRawStones

Distributes raw stones to a player.

Only callable by whitelisted staking contracts.

function distributeRawStones(address _player, uint256 _amount) external;

Parameters

NameTypeDescription
_playeraddressPlayer receiving raw stones.
_amountuint256Amount to distribute.

distributeHammers

Distributes hammers to a player.

Only callable by staking contracts.

function distributeHammers(address _player, uint256 _amount) external;

Parameters

NameTypeDescription
_playeraddressPlayer receiving hammers.
_amountuint256Amount to distribute.

distributeGoldenStones

Distributes GoldenStones to a player.

Only callable by staking contracts.

function distributeGoldenStones(address _player, uint256 _amount) external;

Parameters

NameTypeDescription
_playeraddressPlayer receiving GoldenStones.
_amountuint256Amount to distribute.

activateDailyHammerRewards

Activates daily hammer reward accumulation for a player.

Only callable by staking contracts.

function activateDailyHammerRewards(address _player) external;

Parameters

NameTypeDescription
_playeraddressPlayer whose daily rewards are activated.

getPlayerInventory

Returns the player's stored (non-system) inventory.

function getPlayerInventory(address _player) external view returns (PlayerInventory memory inventory_);

Parameters

NameTypeDescription
_playeraddressPlayer address.

Returns

NameTypeDescription
inventory_PlayerInventoryPlayerInventory struct.

getSystemResources

Returns daily system resources available to the player.

Includes only fresh (non-stored) daily rewards.

function getSystemResources(address _player) external view returns (PlayerInventory memory inventory_);

Parameters

NameTypeDescription
_playeraddressPlayer address.

Returns

NameTypeDescription
inventory_PlayerInventorySystem resources for today.

getTotalResources

Returns total resources a player has (stored + daily system).

function getTotalResources(address _player) external view returns (PlayerInventory memory inventory_);

Parameters

NameTypeDescription
_playeraddressPlayer address.

Returns

NameTypeDescription
inventory_PlayerInventoryAggregated inventory.

getActivatedGoldenStoneAmount

Returns number of activated GoldenStones owned by player.

function getActivatedGoldenStoneAmount(address _player) external view returns (uint256 amount_);

Parameters

NameTypeDescription
_playeraddressPlayer address.

Returns

NameTypeDescription
amount_uint256Activation count.

getActivatedGoldenStones

Returns all activated GoldenStones for a player.

function getActivatedGoldenStones(address _player) external view returns (GoldenStone[] memory goldenStones_);

Parameters

NameTypeDescription
_playeraddressPlayer address.

Returns

NameTypeDescription
goldenStones_GoldenStone[]Array of GoldenStone structs.

getActivatedGoldenStones

Returns paginated GoldenStones for a player.

function getActivatedGoldenStones(address _player, uint256 _start, uint256 _limit)
    external
    view
    returns (GoldenStone[] memory goldenStones_);

Parameters

NameTypeDescription
_playeraddressPlayer address.
_startuint256Start index.
_limituint256Number of entries.

Returns

NameTypeDescription
goldenStones_GoldenStone[]Array of GoldenStone structs.

getActivatedGoldenStone

Returns a single GoldenStone at index.

function getActivatedGoldenStone(address _player, uint256 _index)
    external
    view
    returns (GoldenStone memory goldenStone_);

Parameters

NameTypeDescription
_playeraddressPlayer address.
_indexuint256GoldenStone index.

Returns

NameTypeDescription
goldenStone_GoldenStoneGoldenStone struct.

getHammersPerReferral

Returns number of hammers rewarded per referral.

function getHammersPerReferral() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256hammers Number of hammers per referral.

checkNonce

Checks whether forge nonce is still unused.

function checkNonce(address _player, uint256 _nonce) external view returns (bool valid_);

Parameters

NameTypeDescription
_playeraddressPlayer address.
_nonceuint256Nonce to query.

Returns

NameTypeDescription
valid_boolTrue if nonce is unconsumed.

getForgedGems

Returns today's forged gems for player & total forged gems globally.

function getForgedGems(address _player) external view returns (uint256 forged_, uint256 total_);

Parameters

NameTypeDescription
_playeraddressPlayer address.

Returns

NameTypeDescription
forged_uint256Player's forged gems today.
total_uint256Total forged gems today.

getForgedGems

Returns forged gems for a given UTC day.

function getForgedGems(address _player, uint256 _day) external view returns (uint256 forged_, uint256 total_);

Parameters

NameTypeDescription
_playeraddressPlayer address.
_dayuint256Any timestamp within the desired day.

Returns

NameTypeDescription
forged_uint256Player's forged gems that day.
total_uint256Total forged gems globally that day.

verifyForgeSignature

Verifies whether a signature is a valid forge EIP-712 signature.

function verifyForgeSignature(
    address _player,
    uint256 _nonce,
    uint256 _amount,
    uint256[] memory _gems,
    uint256 _deadline,
    bytes calldata _signature
) external view returns (bool valid_);

Parameters

NameTypeDescription
_playeraddressPlayer address.
_nonceuint256Nonce in signature.
_amountuint256Raw stones amount.
_gemsuint256[]Gem array.
_deadlineuint256Signature expiration.
_signaturebytesProvided signature.

Returns

NameTypeDescription
valid_boolTrue if signature is valid and from master signer.

getForgeDigest

Returns EIP-712 digest for Forge message (for off-chain debugging).

function getForgeDigest(
    address _player,
    uint256 _nonce,
    uint256 _amount,
    uint256[] memory _gems,
    uint256 _deadline
) external view returns (bytes32 digest_);

Parameters

NameTypeDescription
_playeraddressPlayer address.
_nonceuint256Nonce.
_amountuint256Raw stone amount.
_gemsuint256[]Gems array.
_deadlineuint256Deadline.

Returns

NameTypeDescription
digest_bytes32EIP-712 digest.

Events

GemsForged

Emitted when a player successfully forges gems.

event GemsForged(address indexed player, uint256 gems);

Parameters

NameTypeDescription
playeraddressAddress of the forging player.
gemsuint256Amount of gems forged.

GoldenStoneActivated

Emitted when a GoldenStone is activated by a player.

event GoldenStoneActivated(address indexed owner, uint256 index, uint256 deadline);

Parameters

NameTypeDescription
owneraddressGoldenStone owner.
indexuint256Index of the GoldenStone.
deadlineuint256Activation expiry timestamp.

GoldenStoneTapped

Emitted when a player taps (joins) someone's GoldenStone.

event GoldenStoneTapped(address indexed owner, address indexed player, uint256 index);

Parameters

NameTypeDescription
owneraddressOwner of the GoldenStone.
playeraddressPlayer who tapped.
indexuint256GoldenStone index.

GoldenStoneForged

Emitted when a GoldenStone is successfully forged.

event GoldenStoneForged(address indexed owner, uint256 index, uint256 participants);

Parameters

NameTypeDescription
owneraddressOwner of the GoldenStone.
indexuint256Index of the GoldenStone.
participantsuint256Final participant count.

LotteryGenerated

Emitted once per forged raw stone for each player.

event LotteryGenerated(address indexed player, bytes4 code);

Parameters

NameTypeDescription
playeraddressAddress receiving the lottery ticket.
codebytes44-byte lottery code generated via keccak256.

RawStonesDistributed

Emitted when raw stones are distributed to a player.

event RawStonesDistributed(address indexed player, uint256 amount);

Parameters

NameTypeDescription
playeraddressPlayer receiving raw stones.
amountuint256Amount distributed.

HammersDistributed

Emitted when hammers are distributed to a player.

event HammersDistributed(address indexed player, uint256 amount);

Parameters

NameTypeDescription
playeraddressPlayer receiving hammers.
amountuint256Amount distributed.

GoldenStonesDistributed

Emitted when GoldenStones are distributed.

event GoldenStonesDistributed(address indexed player, uint256 amount);

Parameters

NameTypeDescription
playeraddressPlayer receiving GoldenStones.
amountuint256Amount distributed.

DailyHammerRewardsActivated

Emitted when daily hammer rewards are activated.

event DailyHammerRewardsActivated(address indexed player, uint256 activatedAt);

Parameters

NameTypeDescription
playeraddressPlayer who activated daily hammer rewards.
activatedAtuint256UTC-day timestamp marking activation.

RawStonesForged

Emitted when raw stones are forged.

event RawStonesForged(address indexed player, uint256 amount, uint256 nonce, uint256 gems);

Parameters

NameTypeDescription
playeraddressPlayer performing forging.
amountuint256Raw stones forged.
nonceuint256Forge nonce.
gemsuint256Total gems earned.

RewardedRawStonesConsumed

Emitted when system daily raw stones are consumed.

event RewardedRawStonesConsumed(address indexed player, uint256 amount);

StoredRawStonesConsumed

Emitted when stored raw stones are consumed.

event StoredRawStonesConsumed(address indexed player, uint256 amount);

RewardedHammersConsumed

Emitted when system daily hammers are consumed.

event RewardedHammersConsumed(address indexed player, uint256 amount);

StoredHammersConsumed

Emitted when stored hammers are consumed.

event StoredHammersConsumed(address indexed player, uint256 amount);

SetStakings

Emitted when staking contract permissions change.

event SetStakings(address indexed staking, bool flag);

Parameters

NameTypeDescription
stakingaddressAddress of staking contract.
flagboolTrue if enabled, false if disabled.

SetMasterSigner

Emitted when master forge signer is updated.

event SetMasterSigner(address indexed oldSigner, address indexed newSigner);

Parameters

NameTypeDescription
oldSigneraddressPrevious signer.
newSigneraddressNew signer.

SetGoldenStoneConfigs

Emitted when GoldenStone config updates occur.

event SetGoldenStoneConfigs(
    uint256 oldDuration,
    uint256 newDuration,
    uint256 oldMinParticipants,
    uint256 newMinParticipants,
    uint256 oldMaxParticipants,
    uint256 newMaxParticipants
);

SetGoldenStoneReward

Emitted when GoldenStone reward settings change.

event SetGoldenStoneReward(uint256 oldReward, uint256 newReward, uint256 oldBps, uint256 newBps);

SetHammersPerReferral

Emitted when per-referral hammer reward is updated.

event SetHammersPerReferral(uint256 oldVal, uint256 newVal);

Structs

PlayerInventory

Represents both stored and system resources of a player.

  • rawStones: stored raw stones (not including daily system raw stones).
  • goldenStones: number of GoldenStones owned (not yet activated).
  • hammers: stored hammers (not including rewarded system hammers).
struct PlayerInventory {
    uint256 rawStones;
    uint256 goldenStones;
    uint256 hammers;
}

GoldenStone

Represents the state of an activated GoldenStone.

  • deadline: expiration timestamp beyond which it can be auto-forged.
  • isForged: marks whether the GoldenStone has been forged.
  • participants: array of participant addresses (owner is always index 0).
struct GoldenStone {
    uint256 deadline;
    bool isForged;
    address[] participants;
}

IReferralRegistry

Git Source

Author: luoyhang003

Defines the referral binding system used across staking and expedition modules.

This registry maintains:

  • One-to-one mapping between referee -> referrer
  • Keeper-controlled binding operations
  • View helpers for reading referral relationships Keeper contracts are expected to be staking contracts or other protocol-approved callers.

Functions

getReferrerOf

Returns the referrer associated with a given referee.

Returns:

  • address(0) if no referrer is set
  • DEAD_ADDRESS if referrer is invalid or self-referred
function getReferrerOf(address _referee) external view returns (address referrer_);

Parameters

NameTypeDescription
_refereeaddressThe address whose referrer is queried.

Returns

NameTypeDescription
referrer_addressThe resulting referrer address.

bindReferral

Binds a referral relationship between a referee and a referrer.

  • Only callable by keeper contracts.
  • Binding occurs only if referee has no existing referrer.
  • Invalid referrers (zero address or self-reference) map to DEAD_ADDRESS.
function bindReferral(address _referee, address _referrer) external returns (bool binded_);

Parameters

NameTypeDescription
_refereeaddressThe user being referred.
_referreraddressThe user who referred the referee.

Returns

NameTypeDescription
binded_boolTrue if a valid referral was recorded, false otherwise.

Events

ReferralBinded

Emitted when a referral relationship is successfully established.

event ReferralBinded(address indexed referee, address indexed referrer);

Parameters

NameTypeDescription
refereeaddressThe user who was referred.
referreraddressThe user who referred the referee.

SetKeepers

Emitted when keeper permissions change.

event SetKeepers(address indexed keeper, bool flag);

Parameters

NameTypeDescription
keeperaddressAddress of the keeper contract.
flagboolTrue to enable, false to disable.

ISTONEUSDStaking

Git Source

Author: luoyhang003

Interface for the STONEUSD staking contract used in the Genesis Expedition event.

This interface defines:

  • Locking of STONEUSD to earn RawStones and Hammers
  • Eligibility tracking for daily rewarded hammers
  • Unlocking staked STONEUSD after the event ends
  • View helpers for quota, locked amount, and user eligibility

Functions

lock

Locks STONEUSD into the staking contract to participate in the event.

  • Requires the event to be active.
  • Enforces per-user lock quota.
  • May trigger referral binding and bonus hammer distribution.
function lock(uint256 _tokenLocked, address _referrer) external;

Parameters

NameTypeDescription
_tokenLockeduint256The amount of STONEUSD to lock.
_referreraddressThe address of the user who referred the caller (optional).

unlock

Unlocks all previously locked STONEUSD after the event ends.

  • Callable only after the global unlock timestamp.
  • Transfers all unlocked tokens back to the user.
function unlock() external;

getLockedAmount

Returns the total amount of STONEUSD locked by a user.

function getLockedAmount(address _player) external view returns (uint256 locked_);

Parameters

NameTypeDescription
_playeraddressThe user whose locked amount is queried.

Returns

NameTypeDescription
locked_uint256The total locked STONEUSD amount.

getLockQuota

Returns the remaining amount of STONEUSD the user is still allowed to lock.

Quota is based on the MAX_LOCK_COUNT (10 * 1000 STONEUSD).

function getLockQuota(address _player) external view returns (uint256 quota_);

Parameters

NameTypeDescription
_playeraddressThe user whose quota is queried.

Returns

NameTypeDescription
quota_uint256Remaining allowable lock amount.

getEligibility

Returns whether the user has activated daily hammer rewards (eligibility).

Eligibility becomes true once the user locks STONEUSD for the first time.

function getEligibility(address _player) external view returns (bool eligibility_);

Parameters

NameTypeDescription
_playeraddressThe user whose eligibility is queried.

Returns

NameTypeDescription
eligibility_boolTrue if the user receives daily system hammer rewards.

getLockCount

Returns how many times the user has locked 1000 STONEUSD units.

Each 1000 STONEUSD increases lockCount by 1, up to MAX_LOCK_COUNT.

function getLockCount(address _player) external view returns (uint256 lockCount_);

Parameters

NameTypeDescription
_playeraddressThe user whose lockCount is queried.

Returns

NameTypeDescription
lockCount_uint256Number of lock units attributed to the user.

Events

TokenLocked

Emitted when a user locks STONEUSD for event participation.

event TokenLocked(address indexed player, address indexed token, uint256 amount);

Parameters

NameTypeDescription
playeraddressThe user performing the lock.
tokenaddressThe address of the locked token (STONEUSD).
amountuint256The amount of STONEUSD locked.

TokenUnlocked

Emitted when a user unlocks their previously locked STONEUSD.

event TokenUnlocked(address indexed player, address indexed token, uint256 amount);

Parameters

NameTypeDescription
playeraddressThe user unlocking the tokens.
tokenaddressThe address of the unlocked token (STONEUSD).
amountuint256The amount unlocked.

ISTOStaking

Git Source

Author: luoyhang003

Interface for the STO staking contract used in the Genesis Expedition event.

This interface defines:

  • Locking STO to earn Hammers, Raw Stones, and Golden Stones
  • Time-indexed unlocking mechanism
  • View helpers for lock entries, unlockable amounts, and price configurations STO is locked for 70 days before becoming withdrawable.

Functions

lockFor

Locks STO for hammers and raw stones in a single transaction.

  • _hammers and _rawStones determine how much STO is required
  • System distributes resources accordingly
function lockFor(uint256 _hammers, uint256 _rawStones, address _referrer) external;

Parameters

NameTypeDescription
_hammersuint256Number of hammers to purchase via locking.
_rawStonesuint256Number of raw stones to purchase via locking.
_referreraddressOptional referral address.

lockForHammers

Locks STO exclusively for hammers.

function lockForHammers(uint256 _amount, address _referrer) external;

Parameters

NameTypeDescription
_amountuint256Number of hammers to purchase.
_referreraddressOptional referral address.

lockForRawStones

Locks STO exclusively for raw stones.

function lockForRawStones(uint256 _amount, address _referrer) external;

Parameters

NameTypeDescription
_amountuint256Number of raw stones to purchase.
_referreraddressOptional referral address.

unlock

Unlocks a specific lock entry after maturity.

Unlock is allowed only when event has ended and the entry has matured.

function unlock(uint256 _lockIndex) external;

Parameters

NameTypeDescription
_lockIndexuint256Index of the lock entry to unlock.

unlockAll

Unlocks all matured lock entries at once.

Stops iterating when an entry is not yet matured.

function unlockAll() external;

getUnlockableAmount

Returns the total STO amount that is currently withdrawable by a user.

A lock becomes unlockable after: END_TIME + (timeIndex * 1 day).

function getUnlockableAmount(address _player) external view returns (uint256 unlockableAmount_);

Parameters

NameTypeDescription
_playeraddressAddress querying unlockable STO.

Returns

NameTypeDescription
unlockableAmount_uint256Amount of STO eligible for unlocking.

getTotalLockedAmount

Returns total STO locked by a player (including un-matured entries).

function getTotalLockedAmount(address _player) external view returns (uint256 lockedAmount_);

Parameters

NameTypeDescription
_playeraddressUser address.

Returns

NameTypeDescription
lockedAmount_uint256Total STO currently locked.

getLockEntries

Returns all lock entries for a player.

function getLockEntries(address _player) external view returns (LockEntry[] memory lockEntries_);

Parameters

NameTypeDescription
_playeraddressThe user whose lock entries are queried.

Returns

NameTypeDescription
lockEntries_LockEntry[]Dynamic array of LockEntry structs.

getLockEntries

Returns a paginated slice of a user's lock entries.

Reverts if _start + _limit exceeds total entries.

function getLockEntries(address _player, uint256 _start, uint256 _limit)
    external
    view
    returns (LockEntry[] memory lockEntries_);

Parameters

NameTypeDescription
_playeraddressUser address.
_startuint256Starting index.
_limituint256Number of entries to return.

Returns

NameTypeDescription
lockEntries_LockEntry[]Array slice of LockEntry records.

getLockEntryLength

Returns total number of lock entries created by a player.

function getLockEntryLength(address _player) external view returns (uint256 length_);

Parameters

NameTypeDescription
_playeraddressUser address.

Returns

NameTypeDescription
length_uint256Number of lock entries.

getLastUnlockIndex

Returns the player's last processed unlock index.

Used internally to track which entries have been unlocked already.

function getLastUnlockIndex(address _player) external view returns (uint256 index_);

Parameters

NameTypeDescription
_playeraddressUser address.

Returns

NameTypeDescription
index_uint256Last unlocked index (exclusive).

Events

TokenLocked

Emitted when a player locks STO for specific game resources.

event TokenLocked(address indexed player, address indexed token, uint256 amount, LOCK_TYPE lockFor);

Parameters

NameTypeDescription
playeraddressAddress performing the lock.
tokenaddressThe STO token address.
amountuint256Amount of STO locked.
lockForLOCK_TYPEResource type the STO is locked to obtain.

TokenUnlocked

Emitted when locked STO becomes unlocked and is withdrawn.

event TokenUnlocked(address indexed player, address indexed token, uint256 amount);

Parameters

NameTypeDescription
playeraddressThe user unlocking STO.
tokenaddressThe STO token address.
amountuint256Amount unlocked.

SetHammerPrice

Emitted when the STO -> Hammer conversion price changes.

event SetHammerPrice(uint256 oldPrice, uint256 newPrice);

Parameters

NameTypeDescription
oldPriceuint256Previous price.
newPriceuint256New price.

SetRawStonePrice

Emitted when the STO -> Raw Stone conversion price changes.

event SetRawStonePrice(uint256 oldPrice, uint256 newPrice);

Parameters

NameTypeDescription
oldPriceuint256Previous price.
newPriceuint256New price.

SetGoldenStonePrice

Emitted when the STO -> Golden Stone conversion price changes.

event SetGoldenStonePrice(uint256 oldPrice, uint256 newPrice);

Parameters

NameTypeDescription
oldPriceuint256Previous price.
newPriceuint256New price.

Structs

LockEntry

Represents a time-indexed STO lock entry.

  • timeIndex: (timestamp / 1 days) - startTimeIndex, representing day offset
  • lockedAmount: amount of STO locked on this day
struct LockEntry {
    uint256 timeIndex;
    uint256 lockedAmount;
}

Enums

LOCK_TYPE

Defines lock type used during locking operations.

LOCK_FOR_HAMMER: lock STO to receive hammers LOCK_FOR_RAW_STONE: lock STO to receive raw stones

enum LOCK_TYPE {
    LOCK_FOR_HAMMER,
    LOCK_FOR_RAW_STONE
}

Contents

Errors

Git Source

Author: luoyhang003

Centralized custom error definitions used across the Genesis Expedition contracts.

Custom errors significantly reduce gas costs compared to revert strings. These errors are grouped by contract/module for clarity and maintainability. For off-chain tools, debuggers, and log parsers, selectors can be derived from:

bytes4(keccak256("ErrorName()")).

Errors

ZeroAddress

Thrown when a required address argument is zero.

Selector: 0xd92e233d

error ZeroAddress();

IndexOutOfBounds

Thrown when accessing an array index out of bounds.

Selector: 0x4e23d035

error IndexOutOfBounds();

InvalidArrayLength

Thrown when input arrays have mismatched or invalid lengths.

Selector: 0x9d89020a

error InvalidArrayLength();

NotStakingContract

Thrown when caller is not an authorized staking contract.

Selector: 0x135420fb

error NotStakingContract();

InvalidSignature

Thrown when EIP-712 signature validation fails.

Selector: 0x8baa579f

error InvalidSignature();

SignatureExpired

Thrown when a signature is past its deadline.

Selector: 0x0819bdcd

error SignatureExpired();

InvalidNonce

Thrown when a signature nonce is invalid or already used.

Selector: 0x756688fe

error InvalidNonce();

RawStoneNotEnough

Thrown when user does not have enough Raw Stones.

Selector: 0xfdc0d989

error RawStoneNotEnough();

GoldenStoneNotEnough

Thrown when user does not have enough Golden Stones.

Selector: 0xd867d602

error GoldenStoneNotEnough();

GoldenStoneNotActivated

Thrown when attempting to interact with an inactive Golden Stone.

Selector: 0x0fdef728

error GoldenStoneNotActivated();

GoldenStoneExpired

Thrown when Golden Stone has expired and cannot be used.

Selector: 0x15089372

error GoldenStoneExpired();

GoldenStoneNotExpired

Thrown when Golden Stone is expected to be expired but is not.

Selector: 0x1265e724

error GoldenStoneNotExpired();

NotGoldenStoneOwner

Thrown when caller is not the owner of a Golden Stone.

Selector: 0xb9e8af49

error NotGoldenStoneOwner();

NotRawStoneOwner

Thrown when user attempts to consume Raw Stones they do not own.

Selector: 0xf08bbab8

error NotRawStoneOwner();

AlreadyTapped

Thrown when a user attempts to tap a Golden Stone more than once.

Selector: 0xf1fa8e2f

error AlreadyTapped();

GoldenStoneAlreadyForged

Thrown when attempting to forge a Golden Stone that is already forged.

Selector: 0x03d15bb0

error GoldenStoneAlreadyForged();

NotEnoughParticipants

Thrown when Golden Stone forging does not meet minimum participants.

Selector: 0x99f46cd5

error NotEnoughParticipants();

ExceedMaxParticipants

Thrown when Golden Stone forging exceeds maximum allowed participants.

Selector: 0xfc8b1cb6

error ExceedMaxParticipants();

HammerNotEnough

Thrown when user lacks the required hammers for forging actions.

Selector: 0xc1bb1476

error HammerNotEnough();

InvalidGoldenStoneConfig

Thrown when configuration for Golden Stones is invalid.

Selector: 0x42431218

error InvalidGoldenStoneConfig();

NotMasterSigner

Thrown when signature validates, but signer is not the authorized master signer.

Selector: 0x4d053391

error NotMasterSigner();

EventNotActive

Thrown when an action requires the event to be active but it is not.

Selector: 0x0f0c1bc8

error EventNotActive();

EventNotEnded

Thrown when an action requires the event to have ended but it has not.

Selector: 0xfb141a0d

error EventNotEnded();

InvalidStartTime

Thrown when the staking start time is invalid or misaligned.

Selector: 0xb290253c

error InvalidStartTime();

InvalidPrice

Thrown when an admin sets an invalid price or configuration value.

Selector: 0x00bfc921

error InvalidPrice();

ExceedMaxLockCap

Thrown when a user attempts to lock more than the maximum allowed.

Selector: 0xba4beea8

error ExceedMaxLockCap();

BelowMinimumLockAmount

Thrown when user locks less than the required minimum amount.

Selector: 0xdcb6ca48

error BelowMinimumLockAmount();

UnlockNotMatured

Thrown when user attempts to unlock tokens before maturity.

Selector: 0x2a916d02

error UnlockNotMatured();

NothingToUnlock

Thrown when a user attempts to unlock but has no unlockable balance.

Selector: 0x764c157f

error NothingToUnlock();

NotKeeperContract

Thrown when caller is not the authorized keeper contract.

Selector: 0x90023044

error NotKeeperContract();

GenesisExpedition

Git Source

Inherits: IGenesisExpedition, EIP712, Ownable2Step

Author: luoyhang003

Core game logic contract for the Genesis Expedition event.

  • Manages player inventories (raw stones, hammers, golden stones).
  • Handles forging of raw stones into gems via EIP-712 server signatures.
  • Manages GoldenStone activation, tapping, and group forging mechanics.
  • Tracks daily system rewards (daily raw stones & daily hammers).
  • Aggregates gem forging statistics for daily STO reward sharing.
  • Only registered staking contracts can distribute base resources.

State Variables

FORGE_TYPEHASH

EIP-712 typehash used for forging typed data messages.

keccak256("Forge(address player,uint256 nonce,uint256 amount,bytes32 gemsHash,uint256 deadline)") This defines the struct used in server-side signing for forge operations.

bytes32 public constant FORGE_TYPEHASH =
    keccak256("Forge(address player,uint256 nonce,uint256 amount,bytes32 gemsHash,uint256 deadline)")

BPS_DENOMINATOR

Denominator used for basis points (BPS) math.

  • 100 == 1x (100%)
  • e.g. slopeBps = 5 means 5% of baseReward.
uint256 internal constant BPS_DENOMINATOR = 100

DURATION

Duration of the Genesis Expedition event.

Used together with START_TIME to derive END_TIME.

uint256 public constant DURATION = 70 days

DAILY_REWARDED_HAMMERS

Daily rewarded hammer count (system-level, per eligible user).

  • Given once per UTC day after daily hammer rewards are activated.
  • These are stored virtually and consumed during golden stone actions / forging.
uint256 public constant DAILY_REWARDED_HAMMERS = 2

DAILY_REWARDED_RAW_STONES

Daily rewarded raw stones (system-level, per user).

  • 3 system raw stones are granted virtually per day.
  • They expire daily if not used (tracked via consumedRawStones).
uint256 public constant DAILY_REWARDED_RAW_STONES = 3

REFERRAL_REGISTRY_ADDR

Address of the ReferralRegistry contract.

Used in off-chain indexing / integrity checks; not called directly here.

address public immutable REFERRAL_REGISTRY_ADDR

START_TIME

Event start timestamp (UTC-0 aligned).

All time-based logic (daily rewards, availability, etc.) depends on this.

uint256 public immutable START_TIME

END_TIME

Event end timestamp.

After this time, the event is considered inactive for time-gated actions.

uint256 public immutable END_TIME

hammersPerReferral

Number of hammers rewarded per valid referral.

Used by staking contracts to reward referrers via this core contract.

uint256 public hammersPerReferral = 2

goldenStoneActiveDuration

Duration for which a GoldenStone remains active after activation.

  • Used for both manual forging and auto-forging conditions.
  • Measured in seconds; default is 3 days.
uint256 public goldenStoneActiveDuration = 3 days

goldenStoneMinParticipants

Minimum number of participants required to successfully forge a GoldenStone.

Must be >= 3 by design.

uint256 public goldenStoneMinParticipants = 3

goldenStoneMaxParticipants

Maximum number of participants allowed for a single GoldenStone.

Upper cap for fairness & gas constraints (default 10).

uint256 public goldenStoneMaxParticipants = 10

goldenStoneBaseReward

Base gem reward per participant when forging a GoldenStone.

  • Actual reward scales with participant count via rewardLinearSlopeBps.
  • Final reward per participant = baseReward + baseReward * slopeBps * N / BPS_DENOMINATOR.
uint256 public goldenStoneBaseReward = 1000

rewardLinearSlopeBps

Linear slope (in BPS) used to scale GoldenStone rewards with participants.

  • Example: slopeBps = 5 -> +5% per extra participant (relative to baseReward).
uint256 public rewardLinearSlopeBps = 5

masterSigner

Address of the master signer used for EIP-712 forge signatures.

  • Private key is used off-chain to sign forge messages.
  • This address is used on-chain for signature verification.
address public masterSigner

inventories

Player inventory of stored resources (non-system, non-expiring).

Tracks raw stones, hammers, and golden stones that belong to players.

mapping(address => PlayerInventory) private inventories

consumedRawStones

Tracks how many system raw stones a user has consumed on a given day.

  • Keyed by user and floored UTC day timestamp.
  • Used to compute "available" daily system raw stones = DAILY_REWARDED_RAW_STONES - consumed.
mapping(address => mapping(uint256 => uint256)) private consumedRawStones

consumedRewardedHammers

Tracks total system hammers consumed by a user (across days).

  • System rewarded hammers are computed from activation day and consumed count.
  • This value is not keyed by day, only total count.
mapping(address => uint256) private consumedRewardedHammers

stakings

Registry of staking contracts allowed to call distributing functions.

Only staking contracts can mint raw stones/hammers/golden stones.

mapping(address => bool) private stakings

activatedGoldenStones

Activated GoldenStone instances per player and index.

  • Each entry contains deadline, forged flag, and participant addresses.
  • Indexed by player & activatedGoldenStoneAmount[player].
mapping(address => mapping(uint256 => GoldenStone)) private activatedGoldenStones

activatedGoldenStoneAmount

Count of GoldenStones a player has activated.

Also used as upper bound for indexing into activatedGoldenStones.

mapping(address => uint256) private activatedGoldenStoneAmount

dailyHammerRewardsActivatedAt

Day on which a user first activated daily hammer rewards (UTC-floor).

  • Zero means user has not activated daily hammer rewards.
  • After activation, user accrues DAILY_REWARDED_HAMMERS per full day.
mapping(address => uint256) private dailyHammerRewardsActivatedAt

isNonceConsumed

Tracks whether a forge nonce has been consumed for a given player.

Used to prevent replay of EIP-712 signed forge messages.

mapping(address => mapping(uint256 => bool)) private isNonceConsumed

forgedGems

Per-player gems forged on a given UTC day.

Used for-share-of-daily rewards / analytics.

mapping(address => mapping(uint256 => uint256)) private forgedGems

totalForgedGems

Total gems forged by all players on a given day.

Combined with forgedGems to compute proportional STO rewards.

mapping(uint256 => uint256) private totalForgedGems

internalLotteryNonce

Internal nonce used in lottery code generation.

Incremented per-code to perturb randomness inputs.

uint256 private internalLotteryNonce

Functions

onlyStakings

Restricts function to authorized staking contracts only.

Reverts with NotStakingContract if caller is not whitelisted.

modifier onlyStakings() ;

onlyEventActive

Restricts function to when the event is active.

Reverts if block.timestamp is outside [START_TIME, END_TIME].

modifier onlyEventActive() ;

constructor

Initializes the Genesis Expedition core contract.

  • _startTime must be in the future and aligned to UTC-0 (mod 1 days == 0).
  • EIP-712 domain is configured with name "GenesisExpedition" and version "1".
constructor(address _referralRegistryAddr, address _masterSigner, uint256 _startTime)
    EIP712("GenesisExpedition", "1")
    Ownable(msg.sender);

Parameters

NameTypeDescription
_referralRegistryAddraddressAddress of the ReferralRegistry contract.
_masterSigneraddressAddress of the EIP-712 master signer (with off-chain private key).
_startTimeuint256UTC-0 aligned start timestamp of the event.

getPlayerInventory

Returns the player's stored inventory (non-system resources only).

  • Before event start, always returns zero-initialized inventory.
  • This does not include daily system raw stones or system hammers.
function getPlayerInventory(address _player) public view returns (PlayerInventory memory inventory_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.

Returns

NameTypeDescription
inventory_PlayerInventoryThe player's stored inventory (rawStones, hammers, goldenStones).

getSystemResources

Returns system-level resources available to a player (daily rewards).

  • Daily raw stones: 3 per day minus consumed.
  • Daily hammers: accrues since activation and minus consumed.
  • GoldenStones are not system-level here (always 0 in this struct).
function getSystemResources(address _player) public view returns (PlayerInventory memory inventory_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.

Returns

NameTypeDescription
inventory_PlayerInventoryInventory representing system resources available today.

getTotalResources

Returns total resources (stored + system) for a player.

  • Aggregates getPlayerInventory and getSystemResources.
  • Before event start, returns empty inventory.
function getTotalResources(address _player) external view returns (PlayerInventory memory inventory_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.

Returns

NameTypeDescription
inventory_PlayerInventoryAggregated inventory (stored + system resources).

getActivatedGoldenStoneAmount

Returns how many golden stones a player has activated.

This describes the length of the player's activatedGoldenStones list.

function getActivatedGoldenStoneAmount(address _player) external view returns (uint256 amount_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.

Returns

NameTypeDescription
amount_uint256The number of activated golden stones.

getActivatedGoldenStones

Returns all activated golden stones for a player.

  • Iterates from 0 up to activatedGoldenStoneAmount.
  • Stops early if a goldenStone has deadline == 0 (sparse safety).
function getActivatedGoldenStones(address _player) external view returns (GoldenStone[] memory goldenStones_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.

Returns

NameTypeDescription
goldenStones_GoldenStone[]Array of GoldenStone structures.

getActivatedGoldenStones

Returns a paginated slice of activated golden stones for a player.

  • Validates that _start + _limit - 1 is < activatedGoldenStoneAmount.
  • May stop early if a golden stone with deadline == 0 is encountered.
function getActivatedGoldenStones(address _player, uint256 _start, uint256 _limit)
    external
    view
    returns (GoldenStone[] memory goldenStones_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.
_startuint256The starting index (inclusive).
_limituint256The number of entries to fetch.

Returns

NameTypeDescription
goldenStones_GoldenStone[]Array of GoldenStone structures of size _limit.

getActivatedGoldenStone

Returns a single activated golden stone for a player by index.

Reverts if _index is out of range.

function getActivatedGoldenStone(address _player, uint256 _index)
    external
    view
    returns (GoldenStone memory goldenStone_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.
_indexuint256Index of the activated golden stone.

Returns

NameTypeDescription
goldenStone_GoldenStoneThe GoldenStone data at the given index.

getHammersPerReferral

Returns the current configured hammers reward per referral.

Used by staking contracts to query the up-to-date per-referral reward.

function getHammersPerReferral() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The number of hammers rewarded per valid referral.

checkNonce

Checks whether a given forge nonce is still valid for a player.

Returns false if the nonce has already been consumed.

function checkNonce(address _player, uint256 _nonce) external view returns (bool valid_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.
_nonceuint256The nonce to check.

Returns

NameTypeDescription
valid_boolTrue if nonce has not yet been consumed.

getForgedGems

Returns the gems forged by a player today versus total forged today.

Uses current UTC day derived from block.timestamp.

function getForgedGems(address _player) external view returns (uint256 forged_, uint256 total_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.

Returns

NameTypeDescription
forged_uint256Gems forged today by the player.
total_uint256Total gems forged today by all players.

getForgedGems

Returns the gems forged by a player on a specific day.

  • _day can be any timestamp; it is floored to UTC day.
function getForgedGems(address _player, uint256 _day) external view returns (uint256 forged_, uint256 total_);

Parameters

NameTypeDescription
_playeraddressThe address of the player.
_dayuint256Any timestamp in the desired day (UTC).

Returns

NameTypeDescription
forged_uint256Gems forged by the player on that day.
total_uint256Total gems forged by all players on that day.

verifyForgeSignature

Verifies an off-chain EIP-712 forge signature.

  • Does not mutate state.
  • Returns true if signature is valid and signer == masterSigner.
function verifyForgeSignature(
    address _player,
    uint256 _nonce,
    uint256 _amount,
    uint256[] memory _gems,
    uint256 _deadline,
    bytes calldata _signature
) external view returns (bool valid_);

Parameters

NameTypeDescription
_playeraddressPlayer address in the signed struct.
_nonceuint256Unique nonce for replay protection.
_amountuint256Number of raw stones to forge.
_gemsuint256[]Array of gem rewards per raw stone.
_deadlineuint256Signature expiry timestamp.
_signaturebytesOff-chain EIP-712 signature.

Returns

NameTypeDescription
valid_boolTrue if signature is valid and from masterSigner.

getForgeDigest

Computes the EIP-712 digest for a forge operation.

  • Helpful for debugging and off-chain tooling verification.
function getForgeDigest(
    address _player,
    uint256 _nonce,
    uint256 _amount,
    uint256[] memory _gems,
    uint256 _deadline
) external view returns (bytes32 digest_);

Parameters

NameTypeDescription
_playeraddressPlayer address in the struct.
_nonceuint256Unique nonce.
_amountuint256Number of raw stones to forge.
_gemsuint256[]Array of gem amounts.
_deadlineuint256Signature expiry timestamp.

Returns

NameTypeDescription
digest_bytes32The EIP-712 message digest used for signing.

forge

Forges raw stones into gems using a server-side signature.

Flow:

  • Validates caller is the player.
  • Validates array length and non-zero amount.
  • Checks deadline, nonce, and EIP-712 signature.
  • Marks nonce consumed.
  • Consumes required resources (raw stones + hammers; system then stored).
  • Emits gem rewards and generates lottery codes.
function forge(
    address _player,
    uint256 _nonce,
    uint256 _amount,
    uint256[] memory _gems,
    uint256 _deadline,
    bytes calldata _signature
) external onlyEventActive;

Parameters

NameTypeDescription
_playeraddressAddress of the player (must equal msg.sender).
_nonceuint256Unique nonce provided in signed data.
_amountuint256Number of raw stones to forge (length of _gems).
_gemsuint256[]Gem rewards array for each forged raw stone.
_deadlineuint256UNIX timestamp after which signature is invalid.
_signaturebytesOff-chain EIP-712 signature from masterSigner.

activateGoldenStone

Activates one GoldenStone for the caller so others can join and forge together.

  • Requires caller to have more golden stones than already activated.
  • Creates a GoldenStone record with deadline = now + goldenStoneActiveDuration.
  • First participant is always the owner.

Note: events: Emits GoldenStoneActivated.

function activateGoldenStone() external onlyEventActive;

tapGoldenStone

Allows a user to tap (join) another player's activated GoldenStone.

  • Requires golden stone to be active and not yet forged.
  • Enforces max participants.
  • Ensures participant cannot join twice.
  • Consumes either system rewarded hammer or stored hammer.
function tapGoldenStone(address _owner, uint256 _index) external onlyEventActive;

Parameters

NameTypeDescription
_owneraddressThe owner of the GoldenStone.
_indexuint256Index of the GoldenStone in the owner's list.

forgeGoldenStone

Manually forges an activated GoldenStone by its owner.

  • Only the owner can call.
  • Enforces participant count and deadline conditions.
function forgeGoldenStone(address _owner, uint256 _index) external onlyEventActive;

Parameters

NameTypeDescription
_owneraddressOwner address of the GoldenStone.
_indexuint256Index of the GoldenStone in the owner's list.

autoForgeGoldenStone

Auto-forges a GoldenStone after expiration using the master signer.

  • Can only be called by masterSigner.
  • Requires the GoldenStone to have expired.
function autoForgeGoldenStone(address _owner, uint256 _index) external onlyEventActive;

Parameters

NameTypeDescription
_owneraddressOwner address of the GoldenStone.
_indexuint256Index of the GoldenStone in the owner's list.

distributeRawStones

Distributes raw stones to a player (called by staking contracts).

  • Restricted to registered staking contracts via onlyStakings.
  • Increases the player's stored rawStones.
function distributeRawStones(address _player, uint256 _amount) external onlyStakings onlyEventActive;

Parameters

NameTypeDescription
_playeraddressThe address of the player.
_amountuint256Amount of raw stones to distribute.

distributeHammers

Distributes hammers to a player (called by staking contracts).

Increases the player's stored hammers.

function distributeHammers(address _player, uint256 _amount) external onlyStakings onlyEventActive;

Parameters

NameTypeDescription
_playeraddressThe address of the player.
_amountuint256Amount of hammers to distribute.

distributeGoldenStones

Distributes golden stones to a player (called by staking contracts).

Increases the player's stored goldenStones.

function distributeGoldenStones(address _player, uint256 _amount) external onlyStakings onlyEventActive;

Parameters

NameTypeDescription
_playeraddressThe address of the player.
_amountuint256Amount of golden stones to distribute.

activateDailyHammerRewards

Activates daily hammer rewards for a player (called by staking).

  • Only callable once per player (re-activating simply resets date).
  • Daily rewards start counting from this day forward.
function activateDailyHammerRewards(address _player) external onlyStakings onlyEventActive;

Parameters

NameTypeDescription
_playeraddressThe address of the player.

setStakings

Sets or unsets a staking contract address.

Only callable by owner.

function setStakings(address _staking, bool _flag) external onlyOwner;

Parameters

NameTypeDescription
_stakingaddressThe staking contract address.
_flagboolTrue to enable as staking, false to disable.

setMasterSigner

Updates the master signer address used for EIP-712 forging.

  • Only callable by owner.
  • Critical for security: masterSigner compromise requires changing this.
function setMasterSigner(address _key) external onlyOwner;

Parameters

NameTypeDescription
_keyaddressNew master signer address.

setGoldenStoneConfigs

Updates configuration for GoldenStone activation and participant limits.

  • _activeDuration must be > 0.
  • _minParticipants must be > 1.
  • _maxParticipants must be >= _minParticipants.
function setGoldenStoneConfigs(uint256 _activeDuration, uint256 _minParticipants, uint256 _maxParticipants)
    external
    onlyOwner;

Parameters

NameTypeDescription
_activeDurationuint256New active duration in seconds.
_minParticipantsuint256New minimum participants.
_maxParticipantsuint256New maximum participants.

setGoldenStoneReward

Updates the GoldenStone base reward and linear slope.

  • No explicit bounds on _baseReward and _slopeBps; must be configured carefully.
function setGoldenStoneReward(uint256 _baseReward, uint256 _slopeBps) external onlyOwner;

Parameters

NameTypeDescription
_baseRewarduint256New base gem reward per participant.
_slopeBpsuint256New BPS slope value for linear reward scaling.

setHammersPerReferral

Updates the number of hammers rewarded per referral.

Does not enforce a max; must be set to reasonable values via governance.

function setHammersPerReferral(uint256 _hammersPerReferral) external onlyOwner;

Parameters

NameTypeDescription
_hammersPerReferraluint256New hammer reward amount per referral.

_onlyStakings

Internal check that caller is a registered staking contract.

Reverts with NotStakingContract if stakings[msg.sender] is false.

function _onlyStakings() internal view;

_onlyEventActive

Internal check that event is active.

Reverts with EventNotActive if timestamp not in [START_TIME, END_TIME].

function _onlyEventActive() internal view;

_floorToDay

Floors a timestamp down to its UTC-0 day boundary.

E.g. 2024-01-01 15:23 -> 2024-01-01 00:00.

function _floorToDay(uint256 timestamp) internal pure returns (uint256);

Parameters

NameTypeDescription
timestampuint256The original timestamp.

Returns

NameTypeDescription
<none>uint256The floored timestamp at 00:00 UTC of that day.

_generateLotteryCodes

Generates lottery codes for a forge action.

  • Uses blockhash, timestamp, gasleft, player, and internalLotteryNonce as entropy.
  • Emits LotteryGenerated per code.
function _generateLotteryCodes(address _player, uint256 _amount) internal;

Parameters

NameTypeDescription
_playeraddressThe player address receiving lottery codes.
_amountuint256The number of lottery codes to generate.

_distributeGems

Distributes gem rewards from a forge request.

  • Emits a GemsForged event per entry.
  • Aggregates per-player and global forged gems for the current day.
function _distributeGems(address _player, uint256[] memory _gems) internal returns (uint256 gemsForged_);

Parameters

NameTypeDescription
_playeraddressThe player who receives the gems.
_gemsuint256[]Array of gem amounts per forged raw stone.

Returns

NameTypeDescription
gemsForged_uint256Total gems forged in this operation.

_consumeResources

Consumes raw stones and hammers for a forge operation.

  • Prioritizes consumption of system (daily) resources before stored resources.
  • Reverts if not enough total raw stones or hammers.
function _consumeResources(address _player, uint256 _amount) internal;

Parameters

NameTypeDescription
_playeraddressThe player performing the forge.
_amountuint256The number of raw stones to consume.

_isNonceConsumed

Internal helper to check if a forge nonce is consumed.

Returns true if isNonceConsumed[_player][_nonce] is true.

function _isNonceConsumed(address _player, uint256 _nonce) internal view returns (bool consumed_);

Parameters

NameTypeDescription
_playeraddressThe player address.
_nonceuint256The nonce to check.

Returns

NameTypeDescription
consumed_boolTrue if nonce is already used.

_forgeGoldenStone

Internal logic to forge a GoldenStone, manual or auto.

  • If _isAuto is false:
  • Caller must be the owner.
  • GoldenStone must not be expired.
  • If _isAuto is true:
  • Caller must be masterSigner.
  • GoldenStone must be expired.
  • Enforces participant count and not-yet-forged.
  • Distributes gem rewards to all participants.
function _forgeGoldenStone(address _owner, uint256 _index, bool _isAuto) internal;

Parameters

NameTypeDescription
_owneraddressThe owner of the GoldenStone.
_indexuint256Index of the GoldenStone in the owner's list.
_isAutoboolTrue if called by auto-forge logic (masterSigner).

_verifyForgeSignature

Internal EIP-712 signature verification for forge operations.

  • Reverts if nonce already consumed.
  • Returns true if recovered signer equals masterSigner.
function _verifyForgeSignature(
    address _player,
    uint256 _nonce,
    uint256 _amount,
    uint256[] memory _gems,
    uint256 _deadline,
    bytes calldata _signature
) internal view returns (bool valid_);

Parameters

NameTypeDescription
_playeraddressPlayer address in the message.
_nonceuint256Nonce used for replay protection.
_amountuint256Amount of raw stones to forge.
_gemsuint256[]Array of gem rewards.
_deadlineuint256Signature expiry timestamp.
_signaturebytesEIP-712 off-chain signature.

Returns

NameTypeDescription
valid_boolTrue if signature is valid and from masterSigner.

_hashForForge

Internal helper to compute the struct hash for Forge EIP-712 messages.

  • Computes keccak256(abi.encode(FORGE_TYPEHASH, ...)) with inline assembly.
  • _gems is hashed first with keccak256 to a bytes32 gemsHash.
function _hashForForge(
    bytes32 _typehash,
    address _player,
    uint256 _nonce,
    uint256 _amount,
    uint256[] memory _gems,
    uint256 _deadline
) internal pure returns (bytes32 hash_);

Parameters

NameTypeDescription
_typehashbytes32The typehash of the Forge struct.
_playeraddressPlayer address.
_nonceuint256Unique nonce.
_amountuint256Forge amount.
_gemsuint256[]Array of gem values.
_deadlineuint256Signature deadline.

Returns

NameTypeDescription
hash_bytes32The keccak256 hash of the encoded struct.

ReferralRegistry

Git Source

Inherits: IReferralRegistry, Ownable2Step

Author: luoyhang003

Maintains referrer–referee relationships for the Genesis Expedition event.

  • A referee can only be bound once; future attempts return false.
  • Self-referrals and zero-address referrers are replaced with a DEAD_ADDRESS marker.
  • Only keeper contracts (staking contracts) can bind referral relationships.
  • Owner can configure keeper addresses.
  • The DEAD_ADDRESS is used to explicitly mark invalid or blocked relationships.

State Variables

DEAD_ADDRESS

Pseudo-referrer used to indicate invalid or rejected referral bindings.

When a user self-refers or referrer is zero address, we assign DEAD_ADDRESS.

address constant DEAD_ADDRESS = 0x000000000000000000000000000000000000dEaD

referrerOf

Tracks each user's referrer.

A value of ZERO means "not yet bound", DEAD_ADDRESS means "invalid binding".

mapping(address => address) private referrerOf

keepers

Addresses authorized to bind referrals.

Usually STOStaking and STONEUSDStaking contracts.

mapping(address => bool) private keepers

Functions

onlyKeepers

Restricts function access to keeper contracts only.

Reverts with NotKeeperContract() if caller is not authorized.

modifier onlyKeepers() ;

constructor

Initializes the Referral Registry.

Deploying address becomes owner (via Ownable2Step).

constructor() Ownable(msg.sender);

getReferrerOf

Returns the referrer for a given referee.

  • Returns address(0) if not yet bound.
  • Returns DEAD_ADDRESS if binding was invalid (self-referral or bad input).
function getReferrerOf(address _referee) external view returns (address referrer_);

Parameters

NameTypeDescription
_refereeaddressThe address whose referrer is queried.

Returns

NameTypeDescription
referrer_addressThe referee's referrer.

bindReferral

Binds a referee to a referrer. Can only be called by keeper contracts.

Rules:

  • A referee can only be bound once.
  • Self-referrals or zero-address referrers are replaced with DEAD_ADDRESS.
  • Returns true only if a successful valid binding occurred.
function bindReferral(address _referee, address _referrer) external onlyKeepers returns (bool binded_);

Parameters

NameTypeDescription
_refereeaddressThe user being referred.
_referreraddressThe address that referred the referee.

Returns

NameTypeDescription
binded_boolWhether a new valid referral entry was successfully created.

setKeepers

Updates keeper authorization for a contract or address.

  • Only owner can call.
  • Setting _flag = true authorizes the address as a keeper.
  • Setting _flag = false removes authorization.
function setKeepers(address _keeper, bool _flag) external onlyOwner;

Parameters

NameTypeDescription
_keeperaddressAddress to update.
_flagboolWhether the address should be authorized as a keeper.

_onlyKeepers

Ensures that the caller is an authorized keeper contract.

Reverts with NotKeeperContract() if keepers[msg.sender] is false.

function _onlyKeepers() internal view;

STONEUSDStaking

Git Source

Inherits: ISTONEUSDStaking

Author: luoyhang003

Handles the entire staking logic for STONEUSD within the Genesis Expedition event.

  • Users lock STONEUSD in batches of 1000 STONEUSD.
  • Each batch grants 1 Raw Stone and (1 or 3) Hammers.
  • Users may lock up to 10 batches (10,000 STONEUSD).
  • Locked STONEUSD unlocks only once: after the event ends.
  • Integrates with GenesisExpedition for resource distribution.
  • Integrates with ReferralRegistry for referral bonus hammer rewards.

State Variables

DURATION

Duration of the staking event.

uint256 public constant DURATION = 70 days

STONEUSD_PER_LOCK

Required STONEUSD amount per valid lock batch.

uint256 public constant STONEUSD_PER_LOCK = 1_000 * 1e18

MAX_LOCK_COUNT

Maximum number of valid lock batches per user.

uint256 public constant MAX_LOCK_COUNT = 10

STONEUSD_ADDR

STONEUSD ERC20 token address.

address public immutable STONEUSD_ADDR

EXPEDITION_ADDR

Genesis Expedition main contract address.

address public immutable EXPEDITION_ADDR

REFERRAL_REGISTRY_ADDR

Referral Registry contract address.

address public immutable REFERRAL_REGISTRY_ADDR

START_TIME

Genesis Expedition start time (UTC-0 aligned).

uint256 public immutable START_TIME

END_TIME

Time when the staking period ends.

uint256 public immutable END_TIME

locked

Total STONEUSD locked per user.

mapping(address => uint256) private locked

lockCount

Number of valid lock batches a user has consumed.

mapping(address => uint256) private lockCount

isEligible

Whether the user has already qualified for daily hammer rewards.

mapping(address => bool) private isEligible

Functions

onlyEventActive

Ensures that a function can only be executed while event is active.

Active range: [START_TIME, END_TIME].

modifier onlyEventActive() ;

constructor

Initializes the STONEUSD staking module.

_startTime must be exactly aligned to UTC-0 (mod 1 days == 0).

constructor(address _stoneusdAddr, address _expeditionAddr, address _referralRegistryAddr, uint256 _startTime) ;

Parameters

NameTypeDescription
_stoneusdAddraddressAddress of STONEUSD ERC20 token.
_expeditionAddraddressAddress of Genesis Expedition contract.
_referralRegistryAddraddressAddress of Referral Registry contract.
_startTimeuint256Timestamp of event start.

lock

Allows users to lock STONEUSD to earn Raw Stones and Hammers.

  • Lock amount must be >= 1000 STONEUSD.
  • Lock amount cannot exceed remaining quota.
  • First–time lockers receive +2 bonus hammers and activation for daily hammer rewards.
function lock(uint256 _tokenLocked, address _referrer) external onlyEventActive;

Parameters

NameTypeDescription
_tokenLockeduint256Amount of STONEUSD the user wants to lock.
_referreraddressOptional referrer who may receive bonus hammers.

unlock

Unlocks all STONEUSD previously locked by the caller.

  • Unlock is allowed only after END_TIME.
  • All STONEUSD unlocks at once, not progressively.
function unlock() external;

getLockedAmount

Returns how much STONEUSD the user has locked.

function getLockedAmount(address _player) external view returns (uint256 locked_);

Parameters

NameTypeDescription
_playeraddressAddress of user.

Returns

NameTypeDescription
locked_uint256Total STONEUSD locked.

getLockQuota

Returns how much more STONEUSD the user is allowed to lock.

Maximum lock capacity = MAX_LOCK_COUNT * STONEUSD_PER_LOCK.

function getLockQuota(address _player) public view returns (uint256 quota_);

Parameters

NameTypeDescription
_playeraddressAddress of user.

Returns

NameTypeDescription
quota_uint256Remaining lockable STONEUSD amount.

getEligibility

Returns whether user has already qualified for daily hammer rewards.

function getEligibility(address _player) external view returns (bool eligibility_);

Parameters

NameTypeDescription
_playeraddressAddress of user.

Returns

NameTypeDescription
eligibility_boolTrue if user is eligible.

getLockCount

Returns the number of valid lock batches the user has performed.

function getLockCount(address _player) external view returns (uint256 lockCount_);

Parameters

NameTypeDescription
_playeraddressAddress of user.

Returns

NameTypeDescription
lockCount_uint256Count of 1000-STONEUSD lock batches.

_onlyEventActive

Internal check to ensure event is active.

Reverts if block.timestamp is outside the active event window.

function _onlyEventActive() internal view;

_bindReferral

Registers a referrer relationship for referral rewards.

Returns true only if binding succeeds and is new.

function _bindReferral(address _referee, address _referrer) internal returns (bool);

Parameters

NameTypeDescription
_refereeaddressAddress performing the lock.
_referreraddressAddress that referred the referee.

Returns

NameTypeDescription
<none>boolWhether the binding operation created a new referral link.

STOStaking

Git Source

Inherits: ISTOStaking, Ownable2Step

Author: luoyhang003

Enables users to lock STO tokens during the Genesis Expedition event to earn Hammers, Raw Stones, and Golden Stones.

  • Lock entries are grouped by UTC-0 day (timeIndex).
  • STO unlocks gradually after the event ends (END_TIME).
  • Golden Stones are distributed using cumulative modulo accounting.
  • Integrates with GenesisExpedition for distributing in-game resources.
  • Integrates with ReferralRegistry for bonus hammer rewards.

State Variables

DURATION

Duration of the staking event.

uint256 public constant DURATION = 70 days

STO_ADDR

Address of the STO ERC20 token to be staked.

address public immutable STO_ADDR

EXPEDITION_ADDR

GenesisExpedition contract for distributing Hammers, Raw Stones, Golden Stones.

address public immutable EXPEDITION_ADDR

REFERRAL_REGISTRY_ADDR

Referral registry for establishing referrer/referee relationships.

address public immutable REFERRAL_REGISTRY_ADDR

START_TIME

Event start timestamp (UTC-0 aligned).

uint256 public immutable START_TIME

END_TIME

Event end timestamp (START_TIME + DURATION).

uint256 public immutable END_TIME

START_TIME_INDEX

UTC-0 day index corresponding to START_TIME.

uint256 public immutable START_TIME_INDEX

END_TIME_INDEX

UTC-0 day index corresponding to END_TIME.

uint256 public immutable END_TIME_INDEX

stoPerHammer

STO amount required to mint one Hammer.

uint256 public stoPerHammer = 30 * 1e18

stoPerRawStone

STO amount required to mint one Raw Stone.

uint256 public stoPerRawStone = 50 * 1e18

stoPerGoldenStone

STO amount required to mint one Golden Stone.

uint256 public stoPerGoldenStone = 2000 * 1e18

lockEntries

User lock entries, grouped by day index.

mapping(address => LockEntry[]) private lockEntries

totalLocked

Total STO locked per user.

mapping(address => uint256) private totalLocked

lastUnlockIndex

Next unlockable lock index per user.

mapping(address => uint256) private lastUnlockIndex

Functions

onlyEventActive

Ensures a function is only callable while event is active.

Active period: START_TIME <= block.timestamp <= END_TIME.

modifier onlyEventActive() ;

onlyEventEnded

Ensures a function is only callable after event has ended.

modifier onlyEventEnded() ;

constructor

Initializes the STO staking contract.

Start time must be UTC-0 aligned and in the future.

constructor(address _stoAddr, address _expeditionAddr, address _referralRegistryAddr, uint256 _startTime)
    Ownable(msg.sender);

Parameters

NameTypeDescription
_stoAddraddressSTO token address.
_expeditionAddraddressGenesisExpedition contract address.
_referralRegistryAddraddressReferralRegistry contract address.
_startTimeuint256Event start timestamp.

lockFor

Locks STO for both Hammers and Raw Stones in a single transaction.

Wrapper around _lockForResources.

function lockFor(uint256 _hammers, uint256 _rawStones, address _referrer) external onlyEventActive;

Parameters

NameTypeDescription
_hammersuint256Number of hammers to mint.
_rawStonesuint256Number of raw stones to mint.
_referreraddressAddress of the referring user.

lockForHammers

Locks STO exclusively for hammers.

function lockForHammers(uint256 _amount, address _referrer) external onlyEventActive;

Parameters

NameTypeDescription
_amountuint256Number of hammers to mint.
_referreraddressReferrer address.

lockForRawStones

Locks STO exclusively for raw stones.

function lockForRawStones(uint256 _amount, address _referrer) external onlyEventActive;

Parameters

NameTypeDescription
_amountuint256Number of raw stones to mint.
_referreraddressReferrer address.

unlock

Unlocks matured lock entries up to _lockIndex.

  • Each lock entry unlocks at: END_TIME_INDEX + entry.timeIndex.
  • Reverts if any entry in range has not matured.
function unlock(uint256 _lockIndex) external onlyEventEnded;

Parameters

NameTypeDescription
_lockIndexuint256Last index to unlock (inclusive).

unlockAll

Unlocks all matured lock entries.

Stops at the first non-mature lock entry.

function unlockAll() external onlyEventEnded;

getTotalLockedAmount

Returns total STO locked by _player.

function getTotalLockedAmount(address _player) external view returns (uint256 lockedAmount_);

Parameters

NameTypeDescription
_playeraddressUser address.

Returns

NameTypeDescription
lockedAmount_uint256Total locked STO.

getLockEntries

Returns all lock entries for a user.

function getLockEntries(address _player) external view returns (LockEntry[] memory lockEntries_);

Parameters

NameTypeDescription
_playeraddressAddress to query.

Returns

NameTypeDescription
lockEntries_LockEntry[]Array of all LockEntry items.

getLockEntries

Paginated lock entry query.

function getLockEntries(address _player, uint256 _start, uint256 _limit)
    external
    view
    returns (LockEntry[] memory lockEntries_);

Parameters

NameTypeDescription
_playeraddressAddress to query.
_startuint256Starting index.
_limituint256Number of entries to return.

Returns

NameTypeDescription
lockEntries_LockEntry[]Slice of lock entries.

getLockEntryLength

Returns total number of lock entries for a user.

function getLockEntryLength(address _player) external view returns (uint256 length_);

Parameters

NameTypeDescription
_playeraddressAddress to query.

Returns

NameTypeDescription
length_uint256Number of lock entries.

getLastUnlockIndex

Returns the next unlockable lock index.

function getLastUnlockIndex(address _player) external view returns (uint256 index_);

Parameters

NameTypeDescription
_playeraddressAddress to query.

Returns

NameTypeDescription
index_uint256Next unlockable index.

getUnlockableAmount

Computes how much STO is unlockable at current time.

function getUnlockableAmount(address _player) external view returns (uint256 unlockableAmount_);

Parameters

NameTypeDescription
_playeraddressAddress to query.

Returns

NameTypeDescription
unlockableAmount_uint256Total unlockable STO.

setHammerPrice

Updates STO price per Hammer.

function setHammerPrice(uint256 _stoPerHammer) external onlyOwner;

Parameters

NameTypeDescription
_stoPerHammeruint256New price.

setRawStonePrice

Updates STO price per Raw Stone.

function setRawStonePrice(uint256 _stoPerRawStone) external onlyOwner;

Parameters

NameTypeDescription
_stoPerRawStoneuint256New price.

setGoldenStonePrice

Updates STO price per Golden Stone.

function setGoldenStonePrice(uint256 _stoPerGoldenStone) external onlyOwner;

Parameters

NameTypeDescription
_stoPerGoldenStoneuint256New price.

_onlyEventActive

Ensures event is active.

function _onlyEventActive() internal view;

_onlyEventEnded

Ensures event has ended.

function _onlyEventEnded() internal view;

_bindReferral

Binds referee–referrer relationship.

function _bindReferral(address _referee, address _referrer) internal returns (bool);

Parameters

NameTypeDescription
_refereeaddressUser being referred.
_referreraddressReferrer.

Returns

NameTypeDescription
<none>boolWhether binding succeeded.

_lockForResources

Core lock logic for Hammers and Raw Stones.

Also distributes Golden Stones and applies referral rewards.

function _lockForResources(address _player, address _referrer, uint256 _hammers, uint256 _rawStones) internal;

Parameters

NameTypeDescription
_playeraddressUser performing the lock.
_referreraddressReferrer address.
_hammersuint256Number of hammers requested.
_rawStonesuint256Number of raw stones requested.

_addNewLockEntry

Adds STO lock entry for the current UTC-0 day.

Aggregates multiple locks in the same day.

function _addNewLockEntry(address _player, uint256 _amount) internal;

Parameters

NameTypeDescription
_playeraddressUser performing the lock.
_amountuint256STO locked.