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

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.