Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"@openzeppelin/contracts/access/Ownable.sol": {
"content": "// 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/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
"
},
"@openzeppelin/contracts/utils/Context.sol": {
"content": "// 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;
}
}
"
},
"lib/chainlink-brownie-contracts/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// solhint-disable-next-line interface-starts-with-i
interface LinkTokenInterface {
function allowance(address owner, address spender) external view returns (uint256 remaining);
function approve(address spender, uint256 value) external returns (bool success);
function balanceOf(address owner) external view returns (uint256 balance);
function decimals() external view returns (uint8 decimalPlaces);
function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
function increaseApproval(address spender, uint256 subtractedValue) external;
function name() external view returns (string memory tokenName);
function symbol() external view returns (string memory tokenSymbol);
function totalSupply() external view returns (uint256 totalTokensIssued);
function transfer(address to, uint256 value) external returns (bool success);
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
function transferFrom(address from, address to, uint256 value) external returns (bool success);
}
"
},
"lib/chainlink-brownie-contracts/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IVRFV2PlusWrapper {
/**
* @return the request ID of the most recent VRF V2 request made by this wrapper. This should only
* be relied option within the same transaction that the request was made.
*/
function lastRequestId() external view returns (uint256);
/**
* @notice Calculates the price of a VRF request with the given callbackGasLimit at the current
* @notice block.
*
* @dev This function relies on the transaction gas price which is not automatically set during
* @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function.
*
* @param _callbackGasLimit is the gas limit used to estimate the price.
* @param _numWords is the number of words to request.
*/
function calculateRequestPrice(uint32 _callbackGasLimit, uint32 _numWords) external view returns (uint256);
/**
* @notice Calculates the price of a VRF request in native with the given callbackGasLimit at the current
* @notice block.
*
* @dev This function relies on the transaction gas price which is not automatically set during
* @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function.
*
* @param _callbackGasLimit is the gas limit used to estimate the price.
* @param _numWords is the number of words to request.
*/
function calculateRequestPriceNative(uint32 _callbackGasLimit, uint32 _numWords) external view returns (uint256);
/**
* @notice Estimates the price of a VRF request with a specific gas limit and gas price.
*
* @dev This is a convenience function that can be called in simulation to better understand
* @dev pricing.
*
* @param _callbackGasLimit is the gas limit used to estimate the price.
* @param _numWords is the number of words to request.
* @param _requestGasPriceWei is the gas price in wei used for the estimation.
*/
function estimateRequestPrice(
uint32 _callbackGasLimit,
uint32 _numWords,
uint256 _requestGasPriceWei
) external view returns (uint256);
/**
* @notice Estimates the price of a VRF request in native with a specific gas limit and gas price.
*
* @dev This is a convenience function that can be called in simulation to better understand
* @dev pricing.
*
* @param _callbackGasLimit is the gas limit used to estimate the price.
* @param _numWords is the number of words to request.
* @param _requestGasPriceWei is the gas price in wei used for the estimation.
*/
function estimateRequestPriceNative(
uint32 _callbackGasLimit,
uint32 _numWords,
uint256 _requestGasPriceWei
) external view returns (uint256);
/**
* @notice Requests randomness from the VRF V2 wrapper, paying in native token.
*
* @param _callbackGasLimit is the gas limit for the request.
* @param _requestConfirmations number of request confirmations to wait before serving a request.
* @param _numWords is the number of words to request.
*/
function requestRandomWordsInNative(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords,
bytes calldata extraArgs
) external payable returns (uint256 requestId);
function link() external view returns (address);
function linkNativeFeed() external view returns (address);
}
"
},
"lib/chainlink-brownie-contracts/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
// End consumer library.
library VRFV2PlusClient {
// extraArgs will evolve to support new features
bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256("VRF ExtraArgsV1"));
struct ExtraArgsV1 {
bool nativePayment;
}
struct RandomWordsRequest {
bytes32 keyHash;
uint256 subId;
uint16 requestConfirmations;
uint32 callbackGasLimit;
uint32 numWords;
bytes extraArgs;
}
function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs);
}
}
"
},
"lib/chainlink-brownie-contracts/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol";
import {IVRFV2PlusWrapper} from "./interfaces/IVRFV2PlusWrapper.sol";
/**
*
* @notice Interface for contracts using VRF randomness through the VRF V2 wrapper
* ********************************************************************************
* @dev PURPOSE
*
* @dev Create VRF V2+ requests without the need for subscription management. Rather than creating
* @dev and funding a VRF V2+ subscription, a user can use this wrapper to create one off requests,
* @dev paying up front rather than at fulfillment.
*
* @dev Since the price is determined using the gas price of the request transaction rather than
* @dev the fulfillment transaction, the wrapper charges an additional premium on callback gas
* @dev usage, in addition to some extra overhead costs associated with the VRFV2Wrapper contract.
* *****************************************************************************
* @dev USAGE
*
* @dev Calling contracts must inherit from VRFV2PlusWrapperConsumerBase. The consumer must be funded
* @dev with enough LINK or ether to make the request, otherwise requests will revert. To request randomness,
* @dev call the 'requestRandomWords' function with the desired VRF parameters. This function handles
* @dev paying for the request based on the current pricing.
*
* @dev Consumers must implement the fullfillRandomWords function, which will be called during
* @dev fulfillment with the randomness result.
*/
abstract contract VRFV2PlusWrapperConsumerBase {
error OnlyVRFWrapperCanFulfill(address have, address want);
LinkTokenInterface internal immutable i_linkToken;
IVRFV2PlusWrapper public immutable i_vrfV2PlusWrapper;
/**
* @param _vrfV2PlusWrapper is the address of the VRFV2Wrapper contract
*/
constructor(address _vrfV2PlusWrapper) {
IVRFV2PlusWrapper vrfV2PlusWrapper = IVRFV2PlusWrapper(_vrfV2PlusWrapper);
i_linkToken = LinkTokenInterface(vrfV2PlusWrapper.link());
i_vrfV2PlusWrapper = vrfV2PlusWrapper;
}
/**
* @dev Requests randomness from the VRF V2+ wrapper.
*
* @param _callbackGasLimit is the gas limit that should be used when calling the consumer's
* fulfillRandomWords function.
* @param _requestConfirmations is the number of confirmations to wait before fulfilling the
* request. A higher number of confirmations increases security by reducing the likelihood
* that a chain re-org changes a published randomness outcome.
* @param _numWords is the number of random words to request.
*
* @return requestId is the VRF V2+ request ID of the newly created randomness request.
*/
// solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
function requestRandomness(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords,
bytes memory extraArgs
) internal returns (uint256 requestId, uint256 reqPrice) {
reqPrice = i_vrfV2PlusWrapper.calculateRequestPrice(_callbackGasLimit, _numWords);
i_linkToken.transferAndCall(
address(i_vrfV2PlusWrapper),
reqPrice,
abi.encode(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs)
);
return (i_vrfV2PlusWrapper.lastRequestId(), reqPrice);
}
// solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
function requestRandomnessPayInNative(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords,
bytes memory extraArgs
) internal returns (uint256 requestId, uint256 requestPrice) {
requestPrice = i_vrfV2PlusWrapper.calculateRequestPriceNative(_callbackGasLimit, _numWords);
return (
i_vrfV2PlusWrapper.requestRandomWordsInNative{value: requestPrice}(
_callbackGasLimit,
_requestConfirmations,
_numWords,
extraArgs
),
requestPrice
);
}
/**
* @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must
* @notice implement it.
*
* @param _requestId is the VRF V2 request ID.
* @param _randomWords is the randomness result.
*/
// solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore
function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal virtual;
function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external {
address vrfWrapperAddr = address(i_vrfV2PlusWrapper);
if (msg.sender != vrfWrapperAddr) {
revert OnlyVRFWrapperCanFulfill(msg.sender, vrfWrapperAddr);
}
fulfillRandomWords(_requestId, _randomWords);
}
/// @notice getBalance returns the native balance of the consumer contract
function getBalance() public view returns (uint256) {
return address(this).balance;
}
/// @notice getLinkToken returns the link token contract
function getLinkToken() public view returns (LinkTokenInterface) {
return i_linkToken;
}
}
"
},
"src/BettingManager.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import {VRFV2PlusWrapperConsumerBase} from "lib/chainlink-brownie-contracts/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol";
import {VRFV2PlusClient} from "lib/chainlink-brownie-contracts/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
import {LinkTokenInterface} from "lib/chainlink-brownie-contracts/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import "./ICoinFlipBetting.sol";
contract BettingManager is VRFV2PlusWrapperConsumerBase, Ownable {
// Chainlink VRF Configuration for Direct Funding (from official docs)
uint32 public callbackGasLimit = 300000;
uint16 public requestConfirmations = 3;
uint32 public numWords = 1;
address public linkAddress;
address public wrapperAddress;
// Manager State
address public factory;
uint256 private nextRequestId = 1;
// VRF Request tracking
struct RequestStatus {
uint256 paid;
bool fulfilled;
uint256[] randomWords;
uint256 betId;
address player1;
address player2;
address bettingContract; // Add this field
}
mapping(uint256 => RequestStatus) public s_requests;
uint256[] public requestIds;
uint256 public lastRequestId;
// Mappings
mapping(address => mapping(uint256 => bool)) public playerBets;
mapping(uint256 => uint256) public betToRequest; // betId -> requestId
mapping(uint256 => uint256) public requestToBet; // requestId -> betId
mapping(address => bool) public whitelistBettingContracts;
// Events
event VRFRequested(uint256 indexed requestId, uint256 indexed betId, address player1, address player2);
event VRFFulfilled(uint256 indexed requestId, uint256 indexed betId, uint256 randomness);
event RequestSent(uint256 requestId, uint32 numWords);
event RequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment);
event Received(address sender, uint256 value);
event BettingContractRegistered(address indexed bettingContract, address indexed token, uint256 timestamp);
// Errors
error OnlyWhitelistedBettingContracts();
error OnlyFactory();
error InsufficientETHForVRF();
error VRFRequestFailed();
error RequestNotFound();
constructor(
address _factory,
address _wrapperAddress,
address _linkAddress
) VRFV2PlusWrapperConsumerBase(_wrapperAddress) Ownable(msg.sender) {
factory = _factory;
wrapperAddress = _wrapperAddress;
linkAddress = _linkAddress;
}
/**
* @dev Set factory address (only owner)
*/
function setFactory(address _factory) external onlyOwner {
factory = _factory;
}
modifier onlyFactory() {
if (msg.sender != factory) revert OnlyFactory();
_;
}
/**
* @dev Request VRF with ETH payment (called by betting contracts)
*/
function requestVRF(
uint256 _betId,
address _player1,
address _player2
) external payable returns (uint256) {
if (!whitelistBettingContracts[msg.sender]) revert OnlyWhitelistedBettingContracts();
// Calculate VRF cost
uint256 vrfCost = getVRFCost();
if (msg.value < vrfCost) revert InsufficientETHForVRF();
// Register player bets
playerBets[_player1][_betId] = true;
playerBets[_player2][_betId] = true;
// Request randomness using ETH (enableNativePayment = true)
bytes memory extraArgs = VRFV2PlusClient._argsToBytes(
VRFV2PlusClient.ExtraArgsV1({nativePayment: true})
);
uint256 requestId;
uint256 reqPrice;
(requestId, reqPrice) = requestRandomnessPayInNative(
callbackGasLimit,
requestConfirmations,
numWords,
extraArgs
);
// Store request details
s_requests[requestId] = RequestStatus({
paid: reqPrice,
randomWords: new uint256[](0),
fulfilled: false,
betId: _betId,
player1: _player1,
player2: _player2,
bettingContract: msg.sender
});
requestIds.push(requestId);
lastRequestId = requestId;
// Update mappings
betToRequest[_betId] = requestId;
requestToBet[requestId] = _betId;
emit VRFRequested(requestId, _betId, _player1, _player2);
emit RequestSent(requestId, numWords);
// Refund excess ETH
if (msg.value > reqPrice) {
payable(msg.sender).transfer(msg.value - reqPrice);
}
return requestId;
}
/**
* @dev Fulfill randomness callback from VRF Coordinator
*/
function fulfillRandomWords(
uint256 requestId,
uint256[] memory randomWords
) internal override {
require(s_requests[requestId].paid > 0, "request not found");
s_requests[requestId].fulfilled = true;
s_requests[requestId].randomWords = randomWords;
uint256 betId = requestToBet[requestId];
uint256 randomness = randomWords[0];
emit VRFFulfilled(requestId, betId, randomness);
emit RequestFulfilled(requestId, randomWords, s_requests[requestId].paid);
// Notify the betting contract
address bettingContract = s_requests[requestId].bettingContract;
try ICoinFlipBetting(bettingContract).fulfillVRF(betId, randomness) {
// Success
} catch {
// Handle failure gracefully
}
}
/**
* @dev Register player bet
*/
function registerPlayerBet(address _player, uint256 _betId) external {
if (!whitelistBettingContracts[msg.sender]) revert OnlyWhitelistedBettingContracts();
playerBets[_player][_betId] = true;
}
/**
* @dev Register betting contract (called by factory)
*/
function registerBettingContract(address _bettingContract, address _token) external {
if (msg.sender != factory) revert OnlyFactory();
whitelistBettingContracts[_bettingContract] = true;
emit BettingContractRegistered(_bettingContract, _token, block.timestamp);
}
/**
* @dev Get VRF cost in ETH
*/
function getVRFCost() public view returns (uint256) {
return i_vrfV2PlusWrapper.calculateRequestPriceNative(callbackGasLimit, numWords);
}
/**
* @dev Get request status
*/
function getRequestStatus(
uint256 requestId
) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) {
require(s_requests[requestId].paid > 0, "request not found");
RequestStatus memory request = s_requests[requestId];
return (request.paid, request.fulfilled, request.randomWords);
}
/**
* @dev Withdraw LINK tokens (only owner)
*/
function withdrawLink() external onlyOwner {
LinkTokenInterface link = LinkTokenInterface(linkAddress);
require(
link.transfer(msg.sender, link.balanceOf(address(this))),
"Unable to transfer"
);
}
/**
* @dev Withdraw ETH (only owner)
*/
function withdrawNative(uint256 amount) external onlyOwner {
(bool success, ) = payable(owner()).call{value: amount}("");
require(success, "withdrawNative failed");
}
/**
* @dev Emergency ETH withdrawal (only owner)
*/
function emergencyWithdraw() external onlyOwner {
payable(owner()).transfer(address(this).balance);
}
/**
* @dev Receive ETH
*/
receive() external payable {
emit Received(msg.sender, msg.value);
}
/**
* @dev Get contract ETH balance
*/
function getContractBalance() external view returns (uint256) {
return address(this).balance;
}
} "
},
"src/ICoinFlipBetting.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface ICoinFlipBetting {
// Enums
enum BetResult { PENDING, HEADS, TAILS }
enum BetStatus { OPEN, MATCHED, COMPLETED, CANCELLED }
// Structs
struct Bet {
uint256 betId;
address creator;
address joiner;
uint256 amount;
BetResult creatorChoice;
BetResult result;
BetStatus status;
uint256 requestId;
uint256 createdAt;
uint256 matchedTime;
uint256 completedAt;
address winner;
}
// Events for comprehensive tracking
event BetCreated(
uint256 indexed betId,
address indexed creator,
uint256 amount,
BetResult creatorChoice,
uint256 timestamp
);
event BetJoined(
uint256 indexed betId,
address indexed joiner,
uint256 timestamp
);
event VRFRequested(
uint256 indexed betId,
uint256 indexed requestId,
uint256 timestamp
);
event VRFResponseReceived(
uint256 indexed betId,
uint256 indexed requestId,
uint256 randomNumber,
BetResult result,
uint256 timestamp
);
event BetCompleted(
uint256 indexed betId,
address indexed winner,
address indexed loser,
uint256 winnerAmount,
uint256 feeAmount,
BetResult result,
uint256 timestamp
);
event BetCancelled(
uint256 indexed betId,
address indexed creator,
uint256 refundAmount,
uint256 timestamp
);
event FeeWithdrawn(
address indexed provider,
uint256 amount,
uint256 timestamp
);
event EmergencyWithdraw(
address indexed user,
uint256 amount,
uint256 timestamp
);
// Events for minimum amount updates
event MinimumAmountUpdated(
uint256 oldMinimumAmount,
uint256 newMinimumAmount,
uint256 timestamp
);
// Functions
function createBet(uint256 _amount, BetResult _choice) external returns (uint256 betId);
function joinBet(uint256 _betId) external payable;
function cancelBet(uint256 _betId) external;
function withdrawFees() external;
function emergencyWithdraw(uint256 _betId) external;
function fulfillVRF(uint256 _betId, uint256 _randomNumber) external;
// View functions
function getBet(uint256 _betId) external view returns (Bet memory);
function getBetsByCreator(address _creator) external view returns (uint256[] memory);
function getBetsByJoiner(address _joiner) external view returns (uint256[] memory);
function getAcceptedToken() external view returns (address);
function getBettingProvider() external view returns (address);
function getFeePercentage() external view returns (uint256);
function getAccumulatedFees() external view returns (uint256);
function getTotalBets() external view returns (uint256);
function getActiveBets() external view returns (uint256);
function getVRFCost() external view returns (uint256);
function getMinimumAmount() external view returns (uint256);
// Minimum amount management functions
function updateMinimumAmount(uint256 _newMinimumAmount) external;
} "
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}
}}
Submitted on: 2025-09-21 11:33:17
Comments
Log in to comment.
No comments yet.