Blockchain / Global / Address
Contract
0x7871dbA04da0B2B03a45B76D633AC926275BA151
- Balance
- 9.388228 SOMI
- Transactions sent
- 1
- Type
- Contract · 13,857 bytes of code
DreamCheckersEscrowNoLimit Verified
- Compiler
- solc 0.8.30+commit.73712a01
- Language
- Solidity
- Optimization
- No
- EVM version
- —
- License
- —
- Verified
- 2026-10-12
MainnetDreamCheckers.sol
and 4 more files
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title DreamCheckersEscrowNoLimit
* @dev Simplified escrow contract for Dream Checkers WITHOUT rate limiting or match timeouts
* All game logic is handled off-chain, this contract only manages the escrow functions
*/
contract DreamCheckersEscrowNoLimit is ReentrancyGuard, Pausable, Ownable {
// Custom Errors
error InvalidStake();
error MatchNotFound();
error NotAuthorized();
error InvalidWinner();
error MatchAlreadyCompleted();
error TransferFailed();
error InvalidPlayers();
error DisputeWindowActive();
error AdminEarningsOverflow();
error EmergencyRescueFailed();
error DisputeWindowExpired();
error CannotCancelActiveMatch();
// Constants
uint256 public constant ADMIN_FEE_BPS = 2000; // 20% fee in basis points
uint256 public constant DISPUTE_WINDOW = 5 minutes; // Time window for dispute after completion
uint256 public constant MAX_ADMIN_EARNINGS = 1e30; // Prevent overflow
// Enums
enum MatchStatus {
WAITING, // Waiting for second player
ACTIVE, // Both players joined, game in progress
COMPLETED, // Game finished with winner
REFUNDED, // Stakes refunded (draw)
DISPUTED, // In dispute state
CANCELLED // Match cancelled by creator
}
// Structs
struct Match {
uint256 id;
address player1;
address player2;
uint256 stake;
MatchStatus status;
address winner;
uint256 createdAt;
uint256 completedAt;
bool disputeRaised;
}
// State Variables
uint256 private _matchCounter;
uint256 public totalAdminEarnings;
mapping(uint256 => Match) public matches;
mapping(address => uint256[]) public playerMatches;
// Events
event MatchCreated(
uint256 indexed matchId,
address indexed player1,
uint256 stake
);
event MatchJoined(
uint256 indexed matchId,
address indexed player1,
address indexed player2,
uint256 stake
);
event MatchCompleted(
uint256 indexed matchId,
address indexed winner,
uint256 winnerPayout,
uint256 adminFee
);
event MatchRefunded(
uint256 indexed matchId,
address indexed player1,
address indexed player2,
uint256 stake
);
event MatchCancelled(
uint256 indexed matchId,
address indexed player1,
uint256 stake
);
event MatchDisputed(
uint256 indexed matchId,
address indexed disputeRaiser
);
event AdminFeesWithdrawn(
address indexed admin,
uint256 amount
);
event EmergencyCompletion(
uint256 indexed matchId,
address indexed winner,
string reason
);
event EmergencyRescue(
address indexed token,
address indexed recipient,
uint256 amount,
string reason
);
// Constructor
constructor(address initialOwner) Ownable(initialOwner) {}
// Modifiers
modifier matchExists(uint256 matchId) {
if (matchId == 0 || matchId > _matchCounter) revert MatchNotFound();
_;
}
modifier onlyMatchPlayer(uint256 matchId) {
Match storage _match = matches[matchId];
if (msg.sender != _match.player1 && msg.sender != _match.player2) {
revert NotAuthorized();
}
_;
}
modifier disputeWindowPassed(uint256 matchId) {
Match storage _match = matches[matchId];
if (_match.completedAt + DISPUTE_WINDOW > block.timestamp) {
revert DisputeWindowActive();
}
_;
}
/**
* @dev Create a new match with stake deposit (NO TIMEOUTS)
*/
function createMatch()
external
payable
nonReentrant
whenNotPaused
returns (uint256)
{
if (msg.value == 0) revert InvalidStake();
_matchCounter++;
Match storage newMatch = matches[_matchCounter];
newMatch.id = _matchCounter;
newMatch.player1 = msg.sender;
newMatch.stake = msg.value;
newMatch.status = MatchStatus.WAITING;
newMatch.createdAt = block.timestamp;
playerMatches[msg.sender].push(_matchCounter);
emit MatchCreated(_matchCounter, msg.sender, msg.value);
return _matchCounter;
}
/**
* @dev Join an existing match with stake deposit
*/
function joinMatch(uint256 matchId)
external
payable
nonReentrant
whenNotPaused
matchExists(matchId)
{
Match storage _match = matches[matchId];
// Validation
if (_match.status != MatchStatus.WAITING) revert MatchNotFound();
if (_match.player1 == msg.sender) revert InvalidPlayers();
if (msg.value != _match.stake) revert InvalidStake();
// Update match state
_match.player2 = msg.sender;
_match.status = MatchStatus.ACTIVE;
playerMatches[msg.sender].push(matchId);
emit MatchJoined(matchId, _match.player1, msg.sender, _match.stake);
}
/**
* @dev Cancel a waiting match (creator only, full refund)
*/
function cancelMatch(uint256 matchId)
external
nonReentrant
matchExists(matchId)
{
Match storage _match = matches[matchId];
// Validation
if (msg.sender != _match.player1) revert NotAuthorized();
if (_match.status != MatchStatus.WAITING) revert CannotCancelActiveMatch();
// Update match state
_match.status = MatchStatus.CANCELLED;
_match.completedAt = block.timestamp;
// Full refund to creator (no fees)
(bool success, ) = payable(_match.player1).call{value: _match.stake}("");
if (!success) revert TransferFailed();
emit MatchCancelled(matchId, _match.player1, _match.stake);
}
/**
* @dev Complete match with winner (called by authorized backend)
*/
function completeMatch(uint256 matchId, address winner)
external
onlyOwner
nonReentrant
matchExists(matchId)
{
Match storage _match = matches[matchId];
// Validation
if (_match.status != MatchStatus.ACTIVE) revert MatchAlreadyCompleted();
if (winner != _match.player1 && winner != _match.player2) revert InvalidWinner();
// Update match state
_match.status = MatchStatus.COMPLETED;
_match.winner = winner;
_match.completedAt = block.timestamp;
// Calculate payouts
uint256 totalPrize = _match.stake * 2;
uint256 adminFee = (totalPrize * ADMIN_FEE_BPS) / 10000;
uint256 winnerPayout = totalPrize - adminFee;
// Check for admin earnings overflow
if (totalAdminEarnings + adminFee > MAX_ADMIN_EARNINGS) {
revert AdminEarningsOverflow();
}
// Update admin earnings
totalAdminEarnings += adminFee;
// Transfer winner payout
(bool success, ) = payable(winner).call{value: winnerPayout}("");
if (!success) revert TransferFailed();
emit MatchCompleted(matchId, winner, winnerPayout, adminFee);
}
/**
* @dev Handle draw by refunding both players
*/
function refundDraw(uint256 matchId)
external
onlyOwner
nonReentrant
matchExists(matchId)
{
Match storage _match = matches[matchId];
// Validation
if (_match.status != MatchStatus.ACTIVE) revert MatchAlreadyCompleted();
if (_match.player2 == address(0)) revert InvalidPlayers();
// Update match state
_match.status = MatchStatus.REFUNDED;
_match.completedAt = block.timestamp;
// Refund both players (no admin fee on draws)
(bool success1, ) = payable(_match.player1).call{value: _match.stake}("");
if (!success1) revert TransferFailed();
(bool success2, ) = payable(_match.player2).call{value: _match.stake}("");
if (!success2) revert TransferFailed();
emit MatchRefunded(matchId, _match.player1, _match.player2, _match.stake);
}
/**
* @dev Raise dispute during dispute window
*/
function raiseDispute(uint256 matchId)
external
matchExists(matchId)
onlyMatchPlayer(matchId)
{
Match storage _match = matches[matchId];
// Validation
if (_match.status != MatchStatus.COMPLETED) revert MatchNotFound();
if (_match.completedAt + DISPUTE_WINDOW <= block.timestamp) revert DisputeWindowExpired();
if (_match.disputeRaised) revert MatchAlreadyCompleted();
// Update match state
_match.disputeRaised = true;
_match.status = MatchStatus.DISPUTED;
emit MatchDisputed(matchId, msg.sender);
}
/**
* @dev Emergency completion by admin (for stuck matches)
*/
function emergencyComplete(uint256 matchId, address winner, string calldata reason)
external
onlyOwner
nonReentrant
matchExists(matchId)
{
Match storage _match = matches[matchId];
// Can only emergency complete active or disputed matches
if (_match.status != MatchStatus.ACTIVE && _match.status != MatchStatus.DISPUTED) {
revert MatchAlreadyCompleted();
}
// Allow address(0) for draws, but validate non-zero winners
if (winner != address(0) && winner != _match.player1 && winner != _match.player2) {
revert InvalidWinner();
}
_match.status = MatchStatus.COMPLETED;
_match.winner = winner;
_match.completedAt = block.timestamp;
if (winner != address(0)) {
// Winner payout
uint256 totalPrize = _match.stake * 2;
uint256 adminFee = (totalPrize * ADMIN_FEE_BPS) / 10000;
uint256 winnerPayout = totalPrize - adminFee;
// Check for admin earnings overflow
if (totalAdminEarnings + adminFee > MAX_ADMIN_EARNINGS) {
revert AdminEarningsOverflow();
}
totalAdminEarnings += adminFee;
(bool success, ) = payable(winner).call{value: winnerPayout}("");
if (!success) revert TransferFailed();
} else {
// Draw refund - only if both players exist
if (_match.player2 == address(0)) revert InvalidPlayers();
(bool success1, ) = payable(_match.player1).call{value: _match.stake}("");
if (!success1) revert TransferFailed();
(bool success2, ) = payable(_match.player2).call{value: _match.stake}("");
if (!success2) revert TransferFailed();
}
emit EmergencyCompletion(matchId, winner, reason);
}
/**
* @dev Withdraw accumulated admin fees
*/
function withdrawAdminFees()
external
onlyOwner
nonReentrant
{
uint256 amount = totalAdminEarnings;
if (amount == 0) revert TransferFailed();
totalAdminEarnings = 0;
(bool success, ) = payable(owner()).call{value: amount}("");
if (!success) revert TransferFailed();
emit AdminFeesWithdrawn(owner(), amount);
}
/**
* @dev Emergency rescue function for stuck tokens or ETH
* @param token Address of token to rescue (address(0) for ETH)
* @param amount Amount to rescue
* @param reason Reason for emergency rescue
*/
function emergencyRescue(address token, uint256 amount, string calldata reason)
external
onlyOwner
nonReentrant
{
if (token == address(0)) {
// Rescue ETH
(bool success, ) = payable(owner()).call{value: amount}("");
if (!success) revert EmergencyRescueFailed();
} else {
// Rescue ERC20 tokens
(bool success, ) = token.call(abi.encodeWithSignature("transfer(address,uint256)", owner(), amount));
if (!success) revert EmergencyRescueFailed();
}
emit EmergencyRescue(token, owner(), amount, reason);
}
// View Functions
/**
* @dev Get match details
*/
function getMatch(uint256 matchId)
external
view
matchExists(matchId)
returns (Match memory)
{
return matches[matchId];
}
/**
* @dev Get player's match history
*/
function getPlayerMatches(address player)
external
view
returns (uint256[] memory)
{
return playerMatches[player];
}
/**
* @dev Get current match counter
*/
function getCurrentMatchId() external view returns (uint256) {
return _matchCounter;
}
/**
* @dev Check if match can be completed (dispute window passed)
*/
function canFinalizeMatch(uint256 matchId)
external
view
matchExists(matchId)
returns (bool)
{
Match storage _match = matches[matchId];
return _match.status == MatchStatus.COMPLETED &&
_match.completedAt + DISPUTE_WINDOW <= block.timestamp;
}
/**
* @dev Get contract balance of ETH
*/
function getETHBalance() external view returns (uint256) {
return address(this).balance;
}
/**
* @dev Emergency pause function
*/
function pause() external onlyOwner {
_pause();
}
/**
* @dev Emergency unpause function
*/
function unpause() external onlyOwner {
_unpause();
}
// Fallback function to receive ETH
receive() external payable {}
}
Other files
@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }@openzeppelin/contracts/security/Pausable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }@openzeppelin/contracts/security/ReentrancyGuard.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
ABI · 54 entries
json
[
{
"type": "constructor",
"inputs": [
{
"name": "initialOwner",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "nonpayable"
},
{
"name": "AdminEarningsOverflow",
"type": "error",
"inputs": []
},
{
"name": "CannotCancelActiveMatch",
"type": "error",
"inputs": []
},
{
"name": "DisputeWindowActive",
"type": "error",
"inputs": []
},
{
"name": "DisputeWindowExpired",
"type": "error",
"inputs": []
},
{
"name": "EmergencyRescueFailed",
"type": "error",
"inputs": []
},
{
"name": "InvalidPlayers",
"type": "error",
"inputs": []
},
{
"name": "InvalidStake",
"type": "error",
"inputs": []
},
{
"name": "InvalidWinner",
"type": "error",
"inputs": []
},
{
"name": "MatchAlreadyCompleted",
"type": "error",
"inputs": []
},
{
"name": "MatchNotFound",
"type": "error",
"inputs": []
},
{
"name": "NotAuthorized",
"type": "error",
"inputs": []
},
{
"name": "OwnableInvalidOwner",
"type": "error",
"inputs": [
{
"name": "owner",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "OwnableUnauthorizedAccount",
"type": "error",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "TransferFailed",
"type": "error",
"inputs": []
},
{
"name": "AdminFeesWithdrawn",
"type": "event",
"inputs": [
{
"name": "admin",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "EmergencyCompletion",
"type": "event",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "winner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "reason",
"type": "string",
"indexed": false,
"internalType": "string"
}
],
"anonymous": false
},
{
"name": "EmergencyRescue",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "reason",
"type": "string",
"indexed": false,
"internalType": "string"
}
],
"anonymous": false
},
{
"name": "MatchCancelled",
"type": "event",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "player1",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "stake",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "MatchCompleted",
"type": "event",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "winner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "winnerPayout",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "adminFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "MatchCreated",
"type": "event",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "player1",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "stake",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "MatchDisputed",
"type": "event",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "disputeRaiser",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "MatchJoined",
"type": "event",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "player1",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "player2",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "stake",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "MatchRefunded",
"type": "event",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "player1",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "player2",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "stake",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "OwnershipTransferred",
"type": "event",
"inputs": [
{
"name": "previousOwner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newOwner",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "Paused",
"type": "event",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "Unpaused",
"type": "event",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "ADMIN_FEE_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "DISPUTE_WINDOW",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "MAX_ADMIN_EARNINGS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "canFinalizeMatch",
"type": "function",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "cancelMatch",
"type": "function",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "completeMatch",
"type": "function",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "winner",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "createMatch",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "payable"
},
{
"name": "emergencyComplete",
"type": "function",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "winner",
"type": "address",
"internalType": "address"
},
{
"name": "reason",
"type": "string",
"internalType": "string"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "emergencyRescue",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "reason",
"type": "string",
"internalType": "string"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "getCurrentMatchId",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "getETHBalance",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "getMatch",
"type": "function",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "id",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "player1",
"type": "address",
"internalType": "address"
},
{
"name": "player2",
"type": "address",
"internalType": "address"
},
{
"name": "stake",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "status",
"type": "uint8",
"internalType": "enum DreamCheckersEscrowNoLimit.MatchStatus"
},
{
"name": "winner",
"type": "address",
"internalType": "address"
},
{
"name": "createdAt",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "completedAt",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "disputeRaised",
"type": "bool",
"internalType": "bool"
}
],
"internalType": "struct DreamCheckersEscrowNoLimit.Match"
}
],
"stateMutability": "view"
},
{
"name": "getPlayerMatches",
"type": "function",
"inputs": [
{
"name": "player",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256[]",
"internalType": "uint256[]"
}
],
"stateMutability": "view"
},
{
"name": "joinMatch",
"type": "function",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "payable"
},
{
"name": "matches",
"type": "function",
"inputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "id",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "player1",
"type": "address",
"internalType": "address"
},
{
"name": "player2",
"type": "address",
"internalType": "address"
},
{
"name": "stake",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "status",
"type": "uint8",
"internalType": "enum DreamCheckersEscrowNoLimit.MatchStatus"
},
{
"name": "winner",
"type": "address",
"internalType": "address"
},
{
"name": "createdAt",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "completedAt",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "disputeRaised",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "owner",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "pause",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "paused",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "playerMatches",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
},
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "raiseDispute",
"type": "function",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "refundDraw",
"type": "function",
"inputs": [
{
"name": "matchId",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "renounceOwnership",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "totalAdminEarnings",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "transferOwnership",
"type": "function",
"inputs": [
{
"name": "newOwner",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "unpause",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "withdrawAdminFees",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "receive",
"stateMutability": "payable"
}
]