DevelopersSmart Contract

Smart Contract

TicketPrizePoolShmonV2 is the V2 prize vault contract. Two instances run in parallel on offset weekly anchors.

Deployed contracts

VaultNetworkAddressAnchor
Vault AMonad Mainnet0x2208a2Fe2d08061B2a5ee69A2a3b906B58C17888Wed 13:00 UTC
Vault BMonad Mainnet(deployed Sun 2026-05-10, address to be added post-deploy)Sun 01:00 UTC

Both verified on MonadVision. Source, ABI, and constructor arguments are public.


Constructor

constructor(
    address _shmon,
    uint96  _ticketPriceMON,
    uint32  _roundDurationSec,
    uint32  _yieldPeriodSec,
    address _owner
)
ParameterDescription
_shmonshMON contract address
_ticketPriceMONPrice per ticket, in wei (1e18 = 1 MON)
_roundDurationSecLength of the deposit window in seconds (86400 for 24 hours)
_yieldPeriodSecLength of the lock period in seconds (518100 for 6 days minus 5 minutes)
_ownerContract owner. Can pause and set ticket price. Cannot move user funds.

TARGET_BLOCK_DELAY = 3 is a constant (number of blocks between commit and settle).


Round states

ValueStateMeaning
0OpenDeposit window active
1CommittedDeposit window closed, target block locked, awaiting settle
2SettledWinner drawn, claim and withdraw available
3SkippedRound closed with zero tickets sold
4FailedTarget block hash unavailable (more than 255 blocks late). Principal returns to all depositors, no prize

Read functions

function currentRoundId() external view returns (uint256);
 
function getRoundInfo(uint256 rid) external view returns (
    uint8   state,
    uint64  salesEndTime,
    uint64  targetBlockNumber,
    uint32  totalTickets,
    uint256 totalPrincipalMON,
    uint256 totalShmonShares,
    uint256 principalSharesAtSettle,
    uint256 prizeShares,
    uint256 shareRateAtSettle,
    address winner,
    uint32  winningTicket,
    bool    prizeClaimed
);
 
function getUserPosition(uint256 rid, address user)
    external view returns (uint128 principalMON, uint128 principalShmonShares);
 
function getWithdrawableShares(uint256 rid, address user)
    external view returns (uint256);
 
function getCommitAfterTime(uint256 rid)
    external view returns (uint64);
 
// Returns the next pending action. Action: 0 None, 1 Commit, 2 Settle, 3 MarkFailed.
function nextExecutable() external view returns (uint256 rid, uint8 action);

Write functions

// Pay with MON. msg.value must equal ticketPriceMON * ticketCount.
function buyTicketsMON(uint32 ticketCount) external payable;
 
// Pay with shMON. Caller must have approved sharesOwed = previewWithdraw(cost) + 1.
function buyTicketsShmon(uint32 ticketCount) external;
 
// Lifecycle. Both public, anyone can call.
function commit(uint256 rid) external;
function settle(uint256 rid) external;
 
// Post settle.
function withdrawPrincipal(uint256 rid) external;
function claimPrize(uint256 rid) external;

Events

event RoundStarted(uint256 indexed roundId, uint64 salesEndTime);
 
event TicketsPurchased(
    uint256 indexed roundId,
    address indexed buyer,
    uint32  ticketCount,
    uint256 costMON,
    uint256 sharesDeposited,
    uint256 shareRateAtDeposit,
    uint8   depositAsset       // 0 MON, 1 shMON
);
 
event RoundCommitted(uint256 indexed roundId, uint64 targetBlockNumber);
 
event RoundSettled(
    uint256 indexed roundId,
    address indexed winner,
    uint32  winningTicket,
    uint256 totalPrincipalMON,
    uint256 totalShmonShares,
    uint256 principalShares,
    uint256 prizeShares,
    uint256 shareRateAtSettle
);
 
event RoundSkipped(uint256 indexed roundId);
event RoundFailed(uint256 indexed roundId);
 
event PrincipalWithdrawn(
    uint256 indexed roundId,
    address indexed user,
    uint256 sharesReturned,
    uint256 shareRateAtWithdraw
);
 
event PrizeClaimed(
    uint256 indexed roundId,
    address indexed winner,
    uint256 prizeShares,
    uint256 shareRateAtClaim
);

Merkl readable position surface

The contract exposes ERC20 style read views and events so Merkl’s generic vault indexer can track active positions and award shMonad points. The position is non transferable. There is no transfer, approve, or allowance.

function name()      external view returns (string memory);   // "EverDraw shMON Position"
function symbol()    external view returns (string memory);   // "EVRDRAW-SHMON"
function decimals()  external view returns (uint8);           // 18
 
function balanceOf(address user) external view returns (uint256);  // active MON principal across rounds
function totalSupply()           external view returns (uint256);  // sum across all users
 
event Deposit(address indexed recipient, uint256 amount);   // emitted on every ticket purchase
event Withdraw(address indexed recipient, uint256 amount);  // emitted on every withdrawPrincipal

balanceOf is denominated in MON wei (1 MON = 1e18). It reflects the user’s currently active EverDraw principal summed across all open and locked rounds in this vault. It does not include settled rounds the user has not yet withdrawn from (those drop on withdrawPrincipal).


Owner surface

function pause()              external;  // owner only
function unpause()            external;  // owner only
function transferOwnership(address newOwner) external;  // two step
function acceptOwnership()    external;
function setTicketPrice(uint96 newPrice) external;      // owner only, only between rounds

The owner cannot access user funds, override draws, or modify per round parameters.