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
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
| Name | Type | Description |
|---|---|---|
_player | address | Address performing the forge. |
_nonce | uint256 | Unique nonce preventing replay. |
_amount | uint256 | Raw stones to forge. |
_gems | uint256[] | Gem rewards for each stone. |
_deadline | uint256 | Signature expiration timestamp. |
_signature | bytes | EIP-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
| Name | Type | Description |
|---|---|---|
_player | address | Player receiving raw stones. |
_amount | uint256 | Amount to distribute. |
distributeHammers
Distributes hammers to a player.
Only callable by staking contracts.
function distributeHammers(address _player, uint256 _amount) external;
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Player receiving hammers. |
_amount | uint256 | Amount to distribute. |
distributeGoldenStones
Distributes GoldenStones to a player.
Only callable by staking contracts.
function distributeGoldenStones(address _player, uint256 _amount) external;
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Player receiving GoldenStones. |
_amount | uint256 | Amount to distribute. |
activateDailyHammerRewards
Activates daily hammer reward accumulation for a player.
Only callable by staking contracts.
function activateDailyHammerRewards(address _player) external;
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Player 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
Returns
| Name | Type | Description |
|---|---|---|
inventory_ | PlayerInventory | PlayerInventory 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
Returns
| Name | Type | Description |
|---|---|---|
inventory_ | PlayerInventory | System resources for today. |
getTotalResources
Returns total resources a player has (stored + daily system).
function getTotalResources(address _player) external view returns (PlayerInventory memory inventory_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
Returns
| Name | Type | Description |
|---|---|---|
inventory_ | PlayerInventory | Aggregated inventory. |
getActivatedGoldenStoneAmount
Returns number of activated GoldenStones owned by player.
function getActivatedGoldenStoneAmount(address _player) external view returns (uint256 amount_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
Returns
| Name | Type | Description |
|---|---|---|
amount_ | uint256 | Activation count. |
getActivatedGoldenStones
Returns all activated GoldenStones for a player.
function getActivatedGoldenStones(address _player) external view returns (GoldenStone[] memory goldenStones_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
Returns
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
_start | uint256 | Start index. |
_limit | uint256 | Number of entries. |
Returns
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
_index | uint256 | GoldenStone index. |
Returns
| Name | Type | Description |
|---|---|---|
goldenStone_ | GoldenStone | GoldenStone struct. |
getHammersPerReferral
Returns number of hammers rewarded per referral.
function getHammersPerReferral() external view returns (uint256);
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | hammers 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
_nonce | uint256 | Nonce to query. |
Returns
| Name | Type | Description |
|---|---|---|
valid_ | bool | True 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
Returns
| Name | Type | Description |
|---|---|---|
forged_ | uint256 | Player's forged gems today. |
total_ | uint256 | Total 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
_day | uint256 | Any timestamp within the desired day. |
Returns
| Name | Type | Description |
|---|---|---|
forged_ | uint256 | Player's forged gems that day. |
total_ | uint256 | Total 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
_nonce | uint256 | Nonce in signature. |
_amount | uint256 | Raw stones amount. |
_gems | uint256[] | Gem array. |
_deadline | uint256 | Signature expiration. |
_signature | bytes | Provided signature. |
Returns
| Name | Type | Description |
|---|---|---|
valid_ | bool | True 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address. |
_nonce | uint256 | Nonce. |
_amount | uint256 | Raw stone amount. |
_gems | uint256[] | Gems array. |
_deadline | uint256 | Deadline. |
Returns
| Name | Type | Description |
|---|---|---|
digest_ | bytes32 | EIP-712 digest. |
Events
GemsForged
Emitted when a player successfully forges gems.
event GemsForged(address indexed player, uint256 gems);
Parameters
| Name | Type | Description |
|---|---|---|
player | address | Address of the forging player. |
gems | uint256 | Amount of gems forged. |
GoldenStoneActivated
Emitted when a GoldenStone is activated by a player.
event GoldenStoneActivated(address indexed owner, uint256 index, uint256 deadline);
Parameters
| Name | Type | Description |
|---|---|---|
owner | address | GoldenStone owner. |
index | uint256 | Index of the GoldenStone. |
deadline | uint256 | Activation expiry timestamp. |
GoldenStoneTapped
Emitted when a player taps (joins) someone's GoldenStone.
event GoldenStoneTapped(address indexed owner, address indexed player, uint256 index);
Parameters
| Name | Type | Description |
|---|---|---|
owner | address | Owner of the GoldenStone. |
player | address | Player who tapped. |
index | uint256 | GoldenStone index. |
GoldenStoneForged
Emitted when a GoldenStone is successfully forged.
event GoldenStoneForged(address indexed owner, uint256 index, uint256 participants);
Parameters
| Name | Type | Description |
|---|---|---|
owner | address | Owner of the GoldenStone. |
index | uint256 | Index of the GoldenStone. |
participants | uint256 | Final participant count. |
LotteryGenerated
Emitted once per forged raw stone for each player.
event LotteryGenerated(address indexed player, bytes4 code);
Parameters
| Name | Type | Description |
|---|---|---|
player | address | Address receiving the lottery ticket. |
code | bytes4 | 4-byte lottery code generated via keccak256. |
RawStonesDistributed
Emitted when raw stones are distributed to a player.
event RawStonesDistributed(address indexed player, uint256 amount);
Parameters
| Name | Type | Description |
|---|---|---|
player | address | Player receiving raw stones. |
amount | uint256 | Amount distributed. |
HammersDistributed
Emitted when hammers are distributed to a player.
event HammersDistributed(address indexed player, uint256 amount);
Parameters
| Name | Type | Description |
|---|---|---|
player | address | Player receiving hammers. |
amount | uint256 | Amount distributed. |
GoldenStonesDistributed
Emitted when GoldenStones are distributed.
event GoldenStonesDistributed(address indexed player, uint256 amount);
Parameters
| Name | Type | Description |
|---|---|---|
player | address | Player receiving GoldenStones. |
amount | uint256 | Amount distributed. |
DailyHammerRewardsActivated
Emitted when daily hammer rewards are activated.
event DailyHammerRewardsActivated(address indexed player, uint256 activatedAt);
Parameters
| Name | Type | Description |
|---|---|---|
player | address | Player who activated daily hammer rewards. |
activatedAt | uint256 | UTC-day timestamp marking activation. |
RawStonesForged
Emitted when raw stones are forged.
event RawStonesForged(address indexed player, uint256 amount, uint256 nonce, uint256 gems);
Parameters
| Name | Type | Description |
|---|---|---|
player | address | Player performing forging. |
amount | uint256 | Raw stones forged. |
nonce | uint256 | Forge nonce. |
gems | uint256 | Total 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
| Name | Type | Description |
|---|---|---|
staking | address | Address of staking contract. |
flag | bool | True if enabled, false if disabled. |
SetMasterSigner
Emitted when master forge signer is updated.
event SetMasterSigner(address indexed oldSigner, address indexed newSigner);
Parameters
| Name | Type | Description |
|---|---|---|
oldSigner | address | Previous signer. |
newSigner | address | New 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
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
| Name | Type | Description |
|---|---|---|
_referee | address | The address whose referrer is queried. |
Returns
| Name | Type | Description |
|---|---|---|
referrer_ | address | The 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
| Name | Type | Description |
|---|---|---|
_referee | address | The user being referred. |
_referrer | address | The user who referred the referee. |
Returns
| Name | Type | Description |
|---|---|---|
binded_ | bool | True 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
| Name | Type | Description |
|---|---|---|
referee | address | The user who was referred. |
referrer | address | The user who referred the referee. |
SetKeepers
Emitted when keeper permissions change.
event SetKeepers(address indexed keeper, bool flag);
Parameters
| Name | Type | Description |
|---|---|---|
keeper | address | Address of the keeper contract. |
flag | bool | True to enable, false to disable. |
ISTONEUSDStaking
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
| Name | Type | Description |
|---|---|---|
_tokenLocked | uint256 | The amount of STONEUSD to lock. |
_referrer | address | The 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
| Name | Type | Description |
|---|---|---|
_player | address | The user whose locked amount is queried. |
Returns
| Name | Type | Description |
|---|---|---|
locked_ | uint256 | The 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
| Name | Type | Description |
|---|---|---|
_player | address | The user whose quota is queried. |
Returns
| Name | Type | Description |
|---|---|---|
quota_ | uint256 | Remaining 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
| Name | Type | Description |
|---|---|---|
_player | address | The user whose eligibility is queried. |
Returns
| Name | Type | Description |
|---|---|---|
eligibility_ | bool | True 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
| Name | Type | Description |
|---|---|---|
_player | address | The user whose lockCount is queried. |
Returns
| Name | Type | Description |
|---|---|---|
lockCount_ | uint256 | Number 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
| Name | Type | Description |
|---|---|---|
player | address | The user performing the lock. |
token | address | The address of the locked token (STONEUSD). |
amount | uint256 | The 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
| Name | Type | Description |
|---|---|---|
player | address | The user unlocking the tokens. |
token | address | The address of the unlocked token (STONEUSD). |
amount | uint256 | The amount unlocked. |
ISTOStaking
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.
_hammersand_rawStonesdetermine how much STO is required- System distributes resources accordingly
function lockFor(uint256 _hammers, uint256 _rawStones, address _referrer) external;
Parameters
| Name | Type | Description |
|---|---|---|
_hammers | uint256 | Number of hammers to purchase via locking. |
_rawStones | uint256 | Number of raw stones to purchase via locking. |
_referrer | address | Optional referral address. |
lockForHammers
Locks STO exclusively for hammers.
function lockForHammers(uint256 _amount, address _referrer) external;
Parameters
| Name | Type | Description |
|---|---|---|
_amount | uint256 | Number of hammers to purchase. |
_referrer | address | Optional referral address. |
lockForRawStones
Locks STO exclusively for raw stones.
function lockForRawStones(uint256 _amount, address _referrer) external;
Parameters
| Name | Type | Description |
|---|---|---|
_amount | uint256 | Number of raw stones to purchase. |
_referrer | address | Optional 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
| Name | Type | Description |
|---|---|---|
_lockIndex | uint256 | Index 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
| Name | Type | Description |
|---|---|---|
_player | address | Address querying unlockable STO. |
Returns
| Name | Type | Description |
|---|---|---|
unlockableAmount_ | uint256 | Amount 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
| Name | Type | Description |
|---|---|---|
_player | address | User address. |
Returns
| Name | Type | Description |
|---|---|---|
lockedAmount_ | uint256 | Total STO currently locked. |
getLockEntries
Returns all lock entries for a player.
function getLockEntries(address _player) external view returns (LockEntry[] memory lockEntries_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | The user whose lock entries are queried. |
Returns
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
_player | address | User address. |
_start | uint256 | Starting index. |
_limit | uint256 | Number of entries to return. |
Returns
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
_player | address | User address. |
Returns
| Name | Type | Description |
|---|---|---|
length_ | uint256 | Number 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
| Name | Type | Description |
|---|---|---|
_player | address | User address. |
Returns
| Name | Type | Description |
|---|---|---|
index_ | uint256 | Last 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
| Name | Type | Description |
|---|---|---|
player | address | Address performing the lock. |
token | address | The STO token address. |
amount | uint256 | Amount of STO locked. |
lockFor | LOCK_TYPE | Resource 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
| Name | Type | Description |
|---|---|---|
player | address | The user unlocking STO. |
token | address | The STO token address. |
amount | uint256 | Amount unlocked. |
SetHammerPrice
Emitted when the STO -> Hammer conversion price changes.
event SetHammerPrice(uint256 oldPrice, uint256 newPrice);
Parameters
| Name | Type | Description |
|---|---|---|
oldPrice | uint256 | Previous price. |
newPrice | uint256 | New price. |
SetRawStonePrice
Emitted when the STO -> Raw Stone conversion price changes.
event SetRawStonePrice(uint256 oldPrice, uint256 newPrice);
Parameters
| Name | Type | Description |
|---|---|---|
oldPrice | uint256 | Previous price. |
newPrice | uint256 | New price. |
SetGoldenStonePrice
Emitted when the STO -> Golden Stone conversion price changes.
event SetGoldenStonePrice(uint256 oldPrice, uint256 newPrice);
Parameters
| Name | Type | Description |
|---|---|---|
oldPrice | uint256 | Previous price. |
newPrice | uint256 | New 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
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
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.
_startTimemust 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
| Name | Type | Description |
|---|---|---|
_referralRegistryAddr | address | Address of the ReferralRegistry contract. |
_masterSigner | address | Address of the EIP-712 master signer (with off-chain private key). |
_startTime | uint256 | UTC-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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
Returns
| Name | Type | Description |
|---|---|---|
inventory_ | PlayerInventory | The 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
Returns
| Name | Type | Description |
|---|---|---|
inventory_ | PlayerInventory | Inventory 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
Returns
| Name | Type | Description |
|---|---|---|
inventory_ | PlayerInventory | Aggregated 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
Returns
| Name | Type | Description |
|---|---|---|
amount_ | uint256 | The 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
Returns
| Name | Type | Description |
|---|---|---|
goldenStones_ | GoldenStone[] | Array of GoldenStone structures. |
getActivatedGoldenStones
Returns a paginated slice of activated golden stones for a player.
- Validates that
_start + _limit - 1is < 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
_start | uint256 | The starting index (inclusive). |
_limit | uint256 | The number of entries to fetch. |
Returns
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
_index | uint256 | Index of the activated golden stone. |
Returns
| Name | Type | Description |
|---|---|---|
goldenStone_ | GoldenStone | The 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
| Name | Type | Description |
|---|---|---|
<none> | uint256 | The 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
_nonce | uint256 | The nonce to check. |
Returns
| Name | Type | Description |
|---|---|---|
valid_ | bool | True 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
Returns
| Name | Type | Description |
|---|---|---|
forged_ | uint256 | Gems forged today by the player. |
total_ | uint256 | Total gems forged today by all players. |
getForgedGems
Returns the gems forged by a player on a specific day.
_daycan be any timestamp; it is floored to UTC day.
function getForgedGems(address _player, uint256 _day) external view returns (uint256 forged_, uint256 total_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
_day | uint256 | Any timestamp in the desired day (UTC). |
Returns
| Name | Type | Description |
|---|---|---|
forged_ | uint256 | Gems forged by the player on that day. |
total_ | uint256 | Total 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address in the signed struct. |
_nonce | uint256 | Unique nonce for replay protection. |
_amount | uint256 | Number of raw stones to forge. |
_gems | uint256[] | Array of gem rewards per raw stone. |
_deadline | uint256 | Signature expiry timestamp. |
_signature | bytes | Off-chain EIP-712 signature. |
Returns
| Name | Type | Description |
|---|---|---|
valid_ | bool | True 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address in the struct. |
_nonce | uint256 | Unique nonce. |
_amount | uint256 | Number of raw stones to forge. |
_gems | uint256[] | Array of gem amounts. |
_deadline | uint256 | Signature expiry timestamp. |
Returns
| Name | Type | Description |
|---|---|---|
digest_ | bytes32 | The 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
| Name | Type | Description |
|---|---|---|
_player | address | Address of the player (must equal msg.sender). |
_nonce | uint256 | Unique nonce provided in signed data. |
_amount | uint256 | Number of raw stones to forge (length of _gems). |
_gems | uint256[] | Gem rewards array for each forged raw stone. |
_deadline | uint256 | UNIX timestamp after which signature is invalid. |
_signature | bytes | Off-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
| Name | Type | Description |
|---|---|---|
_owner | address | The owner of the GoldenStone. |
_index | uint256 | Index 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
| Name | Type | Description |
|---|---|---|
_owner | address | Owner address of the GoldenStone. |
_index | uint256 | Index 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
| Name | Type | Description |
|---|---|---|
_owner | address | Owner address of the GoldenStone. |
_index | uint256 | Index 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
_amount | uint256 | Amount 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
_amount | uint256 | Amount 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
| Name | Type | Description |
|---|---|---|
_player | address | The address of the player. |
_amount | uint256 | Amount 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
| Name | Type | Description |
|---|---|---|
_player | address | The 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
| Name | Type | Description |
|---|---|---|
_staking | address | The staking contract address. |
_flag | bool | True 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
| Name | Type | Description |
|---|---|---|
_key | address | New 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
| Name | Type | Description |
|---|---|---|
_activeDuration | uint256 | New active duration in seconds. |
_minParticipants | uint256 | New minimum participants. |
_maxParticipants | uint256 | New maximum participants. |
setGoldenStoneReward
Updates the GoldenStone base reward and linear slope.
- No explicit bounds on
_baseRewardand_slopeBps; must be configured carefully.
function setGoldenStoneReward(uint256 _baseReward, uint256 _slopeBps) external onlyOwner;
Parameters
| Name | Type | Description |
|---|---|---|
_baseReward | uint256 | New base gem reward per participant. |
_slopeBps | uint256 | New 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
| Name | Type | Description |
|---|---|---|
_hammersPerReferral | uint256 | New 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
| Name | Type | Description |
|---|---|---|
timestamp | uint256 | The original timestamp. |
Returns
| Name | Type | Description |
|---|---|---|
<none> | uint256 | The 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
| Name | Type | Description |
|---|---|---|
_player | address | The player address receiving lottery codes. |
_amount | uint256 | The 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
| Name | Type | Description |
|---|---|---|
_player | address | The player who receives the gems. |
_gems | uint256[] | Array of gem amounts per forged raw stone. |
Returns
| Name | Type | Description |
|---|---|---|
gemsForged_ | uint256 | Total 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
| Name | Type | Description |
|---|---|---|
_player | address | The player performing the forge. |
_amount | uint256 | The 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
| Name | Type | Description |
|---|---|---|
_player | address | The player address. |
_nonce | uint256 | The nonce to check. |
Returns
| Name | Type | Description |
|---|---|---|
consumed_ | bool | True if nonce is already used. |
_forgeGoldenStone
Internal logic to forge a GoldenStone, manual or auto.
- If
_isAutois false:
- Caller must be the owner.
- GoldenStone must not be expired.
- If
_isAutois 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
| Name | Type | Description |
|---|---|---|
_owner | address | The owner of the GoldenStone. |
_index | uint256 | Index of the GoldenStone in the owner's list. |
_isAuto | bool | True 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
| Name | Type | Description |
|---|---|---|
_player | address | Player address in the message. |
_nonce | uint256 | Nonce used for replay protection. |
_amount | uint256 | Amount of raw stones to forge. |
_gems | uint256[] | Array of gem rewards. |
_deadline | uint256 | Signature expiry timestamp. |
_signature | bytes | EIP-712 off-chain signature. |
Returns
| Name | Type | Description |
|---|---|---|
valid_ | bool | True 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.
_gemsis hashed first with keccak256 to abytes32 gemsHash.
function _hashForForge(
bytes32 _typehash,
address _player,
uint256 _nonce,
uint256 _amount,
uint256[] memory _gems,
uint256 _deadline
) internal pure returns (bytes32 hash_);
Parameters
| Name | Type | Description |
|---|---|---|
_typehash | bytes32 | The typehash of the Forge struct. |
_player | address | Player address. |
_nonce | uint256 | Unique nonce. |
_amount | uint256 | Forge amount. |
_gems | uint256[] | Array of gem values. |
_deadline | uint256 | Signature deadline. |
Returns
| Name | Type | Description |
|---|---|---|
hash_ | bytes32 | The keccak256 hash of the encoded struct. |
ReferralRegistry
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
| Name | Type | Description |
|---|---|---|
_referee | address | The address whose referrer is queried. |
Returns
| Name | Type | Description |
|---|---|---|
referrer_ | address | The 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
| Name | Type | Description |
|---|---|---|
_referee | address | The user being referred. |
_referrer | address | The address that referred the referee. |
Returns
| Name | Type | Description |
|---|---|---|
binded_ | bool | Whether a new valid referral entry was successfully created. |
setKeepers
Updates keeper authorization for a contract or address.
- Only owner can call.
- Setting
_flag = trueauthorizes the address as a keeper. - Setting
_flag = falseremoves authorization.
function setKeepers(address _keeper, bool _flag) external onlyOwner;
Parameters
| Name | Type | Description |
|---|---|---|
_keeper | address | Address to update. |
_flag | bool | Whether 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
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
| Name | Type | Description |
|---|---|---|
_stoneusdAddr | address | Address of STONEUSD ERC20 token. |
_expeditionAddr | address | Address of Genesis Expedition contract. |
_referralRegistryAddr | address | Address of Referral Registry contract. |
_startTime | uint256 | Timestamp 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
| Name | Type | Description |
|---|---|---|
_tokenLocked | uint256 | Amount of STONEUSD the user wants to lock. |
_referrer | address | Optional 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
| Name | Type | Description |
|---|---|---|
_player | address | Address of user. |
Returns
| Name | Type | Description |
|---|---|---|
locked_ | uint256 | Total 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
| Name | Type | Description |
|---|---|---|
_player | address | Address of user. |
Returns
| Name | Type | Description |
|---|---|---|
quota_ | uint256 | Remaining lockable STONEUSD amount. |
getEligibility
Returns whether user has already qualified for daily hammer rewards.
function getEligibility(address _player) external view returns (bool eligibility_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Address of user. |
Returns
| Name | Type | Description |
|---|---|---|
eligibility_ | bool | True 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
| Name | Type | Description |
|---|---|---|
_player | address | Address of user. |
Returns
| Name | Type | Description |
|---|---|---|
lockCount_ | uint256 | Count 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
| Name | Type | Description |
|---|---|---|
_referee | address | Address performing the lock. |
_referrer | address | Address that referred the referee. |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | Whether the binding operation created a new referral link. |
STOStaking
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
| Name | Type | Description |
|---|---|---|
_stoAddr | address | STO token address. |
_expeditionAddr | address | GenesisExpedition contract address. |
_referralRegistryAddr | address | ReferralRegistry contract address. |
_startTime | uint256 | Event 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
| Name | Type | Description |
|---|---|---|
_hammers | uint256 | Number of hammers to mint. |
_rawStones | uint256 | Number of raw stones to mint. |
_referrer | address | Address of the referring user. |
lockForHammers
Locks STO exclusively for hammers.
function lockForHammers(uint256 _amount, address _referrer) external onlyEventActive;
Parameters
| Name | Type | Description |
|---|---|---|
_amount | uint256 | Number of hammers to mint. |
_referrer | address | Referrer address. |
lockForRawStones
Locks STO exclusively for raw stones.
function lockForRawStones(uint256 _amount, address _referrer) external onlyEventActive;
Parameters
| Name | Type | Description |
|---|---|---|
_amount | uint256 | Number of raw stones to mint. |
_referrer | address | Referrer 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
| Name | Type | Description |
|---|---|---|
_lockIndex | uint256 | Last 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
| Name | Type | Description |
|---|---|---|
_player | address | User address. |
Returns
| Name | Type | Description |
|---|---|---|
lockedAmount_ | uint256 | Total locked STO. |
getLockEntries
Returns all lock entries for a user.
function getLockEntries(address _player) external view returns (LockEntry[] memory lockEntries_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Address to query. |
Returns
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
_player | address | Address to query. |
_start | uint256 | Starting index. |
_limit | uint256 | Number of entries to return. |
Returns
| Name | Type | Description |
|---|---|---|
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
| Name | Type | Description |
|---|---|---|
_player | address | Address to query. |
Returns
| Name | Type | Description |
|---|---|---|
length_ | uint256 | Number of lock entries. |
getLastUnlockIndex
Returns the next unlockable lock index.
function getLastUnlockIndex(address _player) external view returns (uint256 index_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Address to query. |
Returns
| Name | Type | Description |
|---|---|---|
index_ | uint256 | Next unlockable index. |
getUnlockableAmount
Computes how much STO is unlockable at current time.
function getUnlockableAmount(address _player) external view returns (uint256 unlockableAmount_);
Parameters
| Name | Type | Description |
|---|---|---|
_player | address | Address to query. |
Returns
| Name | Type | Description |
|---|---|---|
unlockableAmount_ | uint256 | Total unlockable STO. |
setHammerPrice
Updates STO price per Hammer.
function setHammerPrice(uint256 _stoPerHammer) external onlyOwner;
Parameters
| Name | Type | Description |
|---|---|---|
_stoPerHammer | uint256 | New price. |
setRawStonePrice
Updates STO price per Raw Stone.
function setRawStonePrice(uint256 _stoPerRawStone) external onlyOwner;
Parameters
| Name | Type | Description |
|---|---|---|
_stoPerRawStone | uint256 | New price. |
setGoldenStonePrice
Updates STO price per Golden Stone.
function setGoldenStonePrice(uint256 _stoPerGoldenStone) external onlyOwner;
Parameters
| Name | Type | Description |
|---|---|---|
_stoPerGoldenStone | uint256 | New 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
| Name | Type | Description |
|---|---|---|
_referee | address | User being referred. |
_referrer | address | Referrer. |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | Whether 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
| Name | Type | Description |
|---|---|---|
_player | address | User performing the lock. |
_referrer | address | Referrer address. |
_hammers | uint256 | Number of hammers requested. |
_rawStones | uint256 | Number 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
| Name | Type | Description |
|---|---|---|
_player | address | User performing the lock. |
_amount | uint256 | STO locked. |