Overview
This page documents all events emitted by the Proteus smart contracts. Events provide a way to track on-chain activity and can be efficiently queried using blockchain indexers.
PredictionMarketV2 Events
MarketCreated
Emitted when a new prediction market is created.
event MarketCreated(
uint256 indexed marketId,
string actorHandle,
uint256 endTime,
address creator
)
The ID of the newly created market
Social media handle being predicted
Unix timestamp when the market ends
Address that created the market
Emitted by: createMarket()
Example Usage:
// Listen for new markets
predictionMarket.on("MarketCreated", (marketId, actorHandle, endTime, creator) => {
console.log(`New market ${marketId} for ${actorHandle}`);
console.log(`Ends at: ${new Date(endTime * 1000)}`);
});
SubmissionCreated
Emitted when a user submits a prediction to a market.
event SubmissionCreated(
uint256 indexed submissionId,
uint256 indexed marketId,
address submitter,
string predictedText,
uint256 amount
)
The ID of the newly created submission
The market this submission belongs to
Address that created the submission
ETH staked on this prediction (in wei)
Emitted by: createSubmission()
Example Usage:
// Listen for submissions on a specific market
const marketFilter = predictionMarket.filters.SubmissionCreated(null, marketId);
predictionMarket.on(marketFilter, (submissionId, marketId, submitter, predictedText, amount) => {
console.log(`New submission ${submissionId}: "${predictedText}"`);
console.log(`Stake: ${ethers.formatEther(amount)} ETH`);
});
MarketResolved
Emitted when a market is resolved with the actual text.
event MarketResolved(
uint256 indexed marketId,
uint256 winningSubmissionId,
string actualText,
uint256 winningDistance
)
The market that was resolved
The ID of the winning submission
The actual text the actor posted
Levenshtein distance of the winning prediction
Emitted by: resolveMarket()
Example Usage:
// Listen for market resolutions
predictionMarket.on("MarketResolved", (marketId, winningSubmissionId, actualText, winningDistance) => {
console.log(`Market ${marketId} resolved!`);
console.log(`Winner: Submission #${winningSubmissionId}`);
console.log(`Actual text: "${actualText}"`);
console.log(`Edit distance: ${winningDistance}`);
});
PayoutClaimed
Emitted when a winner claims their payout.
event PayoutClaimed(
uint256 indexed submissionId,
address indexed claimer,
uint256 amount
)
The winning submission being claimed
Address claiming the payout
Emitted by: claimPayout()
Example Usage:
// Listen for payout claims
predictionMarket.on("PayoutClaimed", (submissionId, claimer, amount) => {
console.log(`Submission ${submissionId} claimed!`);
console.log(`Winner: ${claimer}`);
console.log(`Payout: ${ethers.formatEther(amount)} ETH`);
});
SingleSubmissionRefunded
Emitted when a market with only one submission is refunded.
event SingleSubmissionRefunded(
uint256 indexed marketId,
uint256 indexed submissionId,
address submitter,
uint256 amount
)
The market with single submission
The submission being refunded
Address receiving the refund
Emitted by: refundSingleSubmission() and emergencyWithdraw()
Example Usage:
// Listen for single submission refunds
predictionMarket.on("SingleSubmissionRefunded", (marketId, submissionId, submitter, amount) => {
console.log(`Market ${marketId} had only one submission`);
console.log(`Refunded ${ethers.formatEther(amount)} ETH to ${submitter}`);
});
FeesWithdrawn
Emitted when accumulated fees are withdrawn.
event FeesWithdrawn(
address indexed recipient,
uint256 amount
)
Amount withdrawn (in wei)
Emitted by: withdrawFees()
Example Usage:
// Listen for fee withdrawals
predictionMarket.on("FeesWithdrawn", (recipient, amount) => {
console.log(`${recipient} withdrew ${ethers.formatEther(amount)} ETH in fees`);
});
GenesisNFT Events
GenesisNFTMinted
Emitted when a Genesis NFT is minted.
event GenesisNFTMinted(
address indexed to,
uint256 tokenId
)
Address receiving the NFT
The token ID that was minted
Emitted by: mint()
Example Usage:
// Listen for Genesis NFT mints
genesisNFT.on("GenesisNFTMinted", (to, tokenId) => {
console.log(`Genesis #${tokenId} minted to ${to}`);
});
MintingFinalized
Emitted when minting is finalized.
event MintingFinalized(
uint256 totalMinted
)
Total number of NFTs that were minted
Emitted by: finalizeMinting() and automatically by mint() when max supply is reached
Example Usage:
// Listen for minting finalization
genesisNFT.on("MintingFinalized", (totalMinted) => {
console.log(`Minting finalized with ${totalMinted} Genesis NFTs`);
});
Standard ERC721 Events
The GenesisNFT contract also emits standard ERC721 events:
Transfer
Emitted when an NFT is transferred.
event Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
)
Address transferring the NFT (zero address for minting)
Address receiving the NFT
The token ID being transferred
Emitted by: transferFrom(), safeTransferFrom(), and mint()
Approval
Emitted when an NFT is approved for transfer.
event Approval(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
)
Address approved to transfer the NFT
The token ID being approved
Emitted by: approve()
ApprovalForAll
Emitted when an operator is approved/revoked for all of an owner’s NFTs.
event ApprovalForAll(
address indexed owner,
address indexed operator,
bool approved
)
Address being approved/revoked as operator
True if operator is approved, false if revoked
Emitted by: setApprovalForAll()
Event Querying Examples
Query Past Events
// Get all markets created in the last 24 hours
const currentBlock = await provider.getBlockNumber();
const blocksPerDay = 7200; // ~12 second blocks
const fromBlock = currentBlock - blocksPerDay;
const marketEvents = await predictionMarket.queryFilter(
predictionMarket.filters.MarketCreated(),
fromBlock
);
marketEvents.forEach(event => {
console.log(`Market ${event.args.marketId}: ${event.args.actorHandle}`);
});
Track User Activity
// Get all submissions by a specific user
const userAddress = "0x...";
const allSubmissions = await predictionMarket.queryFilter(
predictionMarket.filters.SubmissionCreated(null, null, userAddress)
);
console.log(`User has made ${allSubmissions.length} predictions`);
Monitor Market Resolution
// Wait for a specific market to be resolved
const marketId = 42;
const resolvedEvent = await new Promise((resolve) => {
predictionMarket.once(
predictionMarket.filters.MarketResolved(marketId),
resolve
);
});
console.log(`Market ${marketId} resolved!`);
console.log(`Winner: ${resolvedEvent.args.winningSubmissionId}`);
Event Indexing
For production applications, consider using event indexing services:
- The Graph: Create a subgraph to index and query events efficiently
- Moralis: Real-time event streaming and historical queries
- Alchemy Notify: Webhook notifications for specific events
- Etherscan: View all events via the blockchain explorer
Example Subgraph Schema
type Market @entity {
id: ID!
marketId: BigInt!
actorHandle: String!
endTime: BigInt!
creator: Bytes!
submissions: [Submission!]! @derivedFrom(field: "market")
resolved: Boolean!
winningSubmission: Submission
totalPool: BigInt!
}
type Submission @entity {
id: ID!
submissionId: BigInt!
market: Market!
submitter: Bytes!
predictedText: String!
amount: BigInt!
claimed: Boolean!
}
Best Practices
-
Use Indexed Parameters: Query events efficiently using indexed parameters (marked with
indexed keyword)
-
Block Range Limits: Most RPC providers limit event queries to 10,000 blocks at a time
-
Event Confirmation: Wait for multiple block confirmations before considering events finalized
-
Error Handling: Events may not be available immediately; implement retry logic
-
Local Caching: Cache event data to reduce RPC calls and improve performance
-
Websocket Subscriptions: Use websockets for real-time event monitoring instead of polling