Source Code
Latest 25 from a total of 760 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Request Live Tra... | 429294998 | 1 hr ago | IN | 0 ETH | 0.00001023 | ||||
| Request Live Tra... | 429294988 | 1 hr ago | IN | 0 ETH | 0.00001014 | ||||
| Request Live Tra... | 429282261 | 2 hrs ago | IN | 0 ETH | 0.00001005 | ||||
| Request Live Tra... | 429282054 | 2 hrs ago | IN | 0 ETH | 0.00001008 | ||||
| Request Live Tra... | 429118926 | 13 hrs ago | IN | 0 ETH | 0.0000113 | ||||
| Request Live Tra... | 429118605 | 13 hrs ago | IN | 0 ETH | 0.00001145 | ||||
| Request Live Tra... | 429118399 | 13 hrs ago | IN | 0 ETH | 0.00001133 | ||||
| Request Live Tra... | 429118380 | 13 hrs ago | IN | 0 ETH | 0.00001125 | ||||
| Request Live Tra... | 429095680 | 15 hrs ago | IN | 0 ETH | 0.00001325 | ||||
| Request Live Tra... | 429066544 | 17 hrs ago | IN | 0 ETH | 0.00002228 | ||||
| Request Live Tra... | 429066438 | 17 hrs ago | IN | 0 ETH | 0.00002285 | ||||
| Request Live Tra... | 429058875 | 17 hrs ago | IN | 0 ETH | 0.00004095 | ||||
| Request Live Tra... | 429057423 | 17 hrs ago | IN | 0 ETH | 0.00005619 | ||||
| Request Live Par... | 429057312 | 17 hrs ago | IN | 0 ETH | 0.0000823 | ||||
| Request Live Tra... | 429055164 | 18 hrs ago | IN | 0 ETH | 0.00008029 | ||||
| Request Live Tra... | 429053801 | 18 hrs ago | IN | 0 ETH | 0.00002237 | ||||
| Request Live Par... | 429000136 | 21 hrs ago | IN | 0 ETH | 0.00005343 | ||||
| Request Live Par... | 428999736 | 21 hrs ago | IN | 0 ETH | 0.0000993 | ||||
| Request Live Par... | 428999133 | 21 hrs ago | IN | 0 ETH | 0.00005784 | ||||
| Request Live Par... | 428998792 | 21 hrs ago | IN | 0 ETH | 0.00005721 | ||||
| Request Live Par... | 428998487 | 21 hrs ago | IN | 0 ETH | 0.00002499 | ||||
| Request Live Par... | 428997905 | 21 hrs ago | IN | 0 ETH | 0.00002838 | ||||
| Request Live Par... | 428997734 | 21 hrs ago | IN | 0 ETH | 0.0000338 | ||||
| Request Live Par... | 428997607 | 21 hrs ago | IN | 0 ETH | 0.00003502 | ||||
| Request Live Tra... | 428965457 | 24 hrs ago | IN | 0 ETH | 0.0000123 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LiveTradingProcessor
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 100 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// external
import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "../../interfaces/ISportsAMMV2.sol";
import "../../interfaces/IFreeBetsHolder.sol";
import "../../interfaces/ILiveTradingProcessor.sol";
contract LiveTradingProcessor is ChainlinkClient, Ownable, Pausable {
using Chainlink for Chainlink.Request;
using SafeERC20 for IERC20;
uint private constant ONE = 1e18;
uint private constant ODDS_LEN = 225;
ISportsAMMV2 public sportsAMM;
address public freeBetsHolder;
bytes32 public jobSpecId; // single job
uint public paymentAmount;
bytes32 public parlayJobSpecId; // parlay job
uint public maxAllowedExecutionDelay = 60;
// ===== Singles =====
mapping(bytes32 => ILiveTradingProcessor.LiveTradeData) public requestIdToTradeData;
// ===== Parlays =====
mapping(bytes32 => ILiveTradingProcessor.LiveParlayTradeData) public requestIdToParlayTradeData;
mapping(bytes32 => bool) public requestIdIsParlay;
// ===== Common =====
mapping(bytes32 => address) public requestIdToRequester;
mapping(bytes32 => bool) public requestIdToFulfillAllowed;
mapping(bytes32 => bool) public requestIdFulfilled;
mapping(bytes32 => uint) public timestampPerRequest;
uint public requestCounter;
mapping(uint => bytes32) public counterToRequestId;
mapping(bytes32 => address) public requestIdToTicketId;
/// @notice Constructor for LiveTradingProcessor.
/// @dev Sets Chainlink token/oracle, SportsAMM reference, job specs and payment amount.
/// @param _link LINK token address used for Chainlink payments
/// @param _oracle Chainlink oracle address
/// @param _sportsAMM SportsAMMV2 contract address
/// @param _jobSpecId Job spec id for SINGLE live verification requests
/// @param _parlayJobSpecId Job spec id for PARLAY live verification requests
/// @param _paymentAmount LINK payment amount per request
constructor(
address _link,
address _oracle,
address _sportsAMM,
bytes32 _jobSpecId,
bytes32 _parlayJobSpecId,
uint _paymentAmount
) Ownable(msg.sender) {
setChainlinkToken(_link);
setChainlinkOracle(_oracle);
sportsAMM = ISportsAMMV2(_sportsAMM);
jobSpecId = _jobSpecId;
paymentAmount = _paymentAmount;
parlayJobSpecId = _parlayJobSpecId;
}
/// @notice requestLiveTrade (SINGLE)
/// @dev Sends a Chainlink request for live trade verification for a single market.
/// Stores request metadata for later fulfillment and emits LiveTradeRequested.
/// @param _liveTradeData LiveTradeData describing the trade to be verified/executed
/// @return requestId Chainlink request id
function requestLiveTrade(
ILiveTradingProcessor.LiveTradeData calldata _liveTradeData
) external whenNotPaused returns (bytes32 requestId) {
require(
sportsAMM.riskManager().liveTradingPerSportAndTypeEnabled(_liveTradeData._sportId, _liveTradeData._typeId),
"Live trading not enabled on _sportId"
);
require(_liveTradeData._expectedQuote >= sportsAMM.riskManager().maxSupportedOdds(), "ExceededMaxOdds");
Chainlink.Request memory req = buildChainlinkRequest(jobSpecId, address(this), this.fulfillLiveTrade.selector);
req.add("mode", "single");
req.add("gameId", _liveTradeData._gameId);
req.addUint("sportId", _liveTradeData._sportId);
req.addUint("typeId", _liveTradeData._typeId);
req.addInt("line", _liveTradeData._line);
req.addUint("position", _liveTradeData._position);
req.addUint("buyInAmount", _liveTradeData._buyInAmount);
req.addUint("expectedQuote", _liveTradeData._expectedQuote);
req.addUint("additionalSlippage", _liveTradeData._additionalSlippage);
req.addUint("playerId", _liveTradeData._playerId);
// requester & collateral included for adapter-side logging/validation
req.add("requester", Strings.toHexString(msg.sender));
req.add("collateral", Strings.toHexString(_liveTradeData._collateral));
requestId = sendChainlinkRequest(req, paymentAmount);
timestampPerRequest[requestId] = block.timestamp;
requestIdToTradeData[requestId] = _liveTradeData;
requestIdToRequester[requestId] = msg.sender;
requestIdIsParlay[requestId] = false;
counterToRequestId[requestCounter] = requestId;
emit LiveTradeRequested(
msg.sender,
requestCounter,
requestId,
stringToBytes32(_liveTradeData._gameId),
_liveTradeData._sportId,
_liveTradeData._typeId,
_liveTradeData._line,
_liveTradeData._position,
_liveTradeData._buyInAmount,
_liveTradeData._expectedQuote,
_liveTradeData._collateral
);
requestCounter++;
}
/// @notice requestLiveParlayTrade (PARLAY)
/// @dev Sends a Chainlink request for live trade verification for a parlay (multi-leg) trade.
/// Validates that:
/// - parlay has > 1 leg
/// - live trading is enabled for each leg's (sportId, typeId)
/// Stores request metadata for later fulfillment and emits LiveParlayTradeRequested.
/// @param _parlay LiveParlayTradeData describing the parlay to be verified/executed
/// @return requestId Chainlink request id
function requestLiveParlayTrade(
ILiveTradingProcessor.LiveParlayTradeData calldata _parlay
) external whenNotPaused returns (bytes32 requestId) {
uint legsLen = _parlay.legs.length;
require(legsLen > 1, "Parlay must have > 1 leg");
for (uint i = 0; i < legsLen; ++i) {
ILiveTradingProcessor.LiveParlayLeg calldata leg = _parlay.legs[i];
require(
sportsAMM.riskManager().liveTradingPerSportAndTypeEnabled(leg.sportId, leg.typeId),
"Live trading not enabled on leg"
);
}
require(_parlay.expectedPayout >= sportsAMM.riskManager().maxSupportedOdds(), "ExceededMaxOdds");
Chainlink.Request memory req = buildChainlinkRequest(
parlayJobSpecId,
address(this),
this.fulfillLiveTradeParlay.selector
);
req.add("mode", "parlay");
// Chainlink request payload: arrays are provided as string arrays to be adapter-friendly.
string[] memory gameIds = new string[](legsLen);
string[] memory sportIds = new string[](legsLen);
string[] memory typeIds = new string[](legsLen);
string[] memory lines = new string[](legsLen);
string[] memory positions = new string[](legsLen);
string[] memory expectedLegOdds = new string[](legsLen);
string[] memory playerIds = new string[](legsLen);
for (uint i = 0; i < legsLen; ++i) {
ILiveTradingProcessor.LiveParlayLeg calldata leg = _parlay.legs[i];
gameIds[i] = leg.gameId;
sportIds[i] = Strings.toString(uint256(leg.sportId));
typeIds[i] = Strings.toString(uint256(leg.typeId));
lines[i] = _intToString(int256(leg.line));
positions[i] = Strings.toString(uint256(leg.position));
expectedLegOdds[i] = Strings.toString(uint256(leg.expectedLegOdd));
playerIds[i] = Strings.toString(uint256(leg.playerId));
}
req.addStringArray("gameIds", gameIds);
req.addStringArray("sportIds", sportIds);
req.addStringArray("typeIds", typeIds);
req.addStringArray("lines", lines);
req.addStringArray("positions", positions);
req.addStringArray("expectedLegOdds", expectedLegOdds);
req.addStringArray("playerIds", playerIds);
req.addUint("buyInAmount", _parlay.buyInAmount);
req.addUint("expectedQuote", _parlay.expectedPayout);
req.addUint("additionalSlippage", _parlay.additionalSlippage);
req.add("requester", Strings.toHexString(msg.sender));
req.add("collateral", Strings.toHexString(_parlay.collateral));
requestId = sendChainlinkRequest(req, paymentAmount);
timestampPerRequest[requestId] = block.timestamp;
requestIdToParlayTradeData[requestId] = _parlay;
requestIdToRequester[requestId] = msg.sender;
requestIdIsParlay[requestId] = true;
counterToRequestId[requestCounter] = requestId;
emit LiveParlayTradeRequested(msg.sender, requestCounter, requestId, uint16(legsLen), _parlay.buyInAmount);
requestCounter++;
}
// ============================
// Fulfill methods
// ============================
/// @notice fulfillLiveTrade (SINGLE)
/// @dev Chainlink callback for single live trade verification.
/// Requirements:
/// - request not already fulfilled
/// - request not timed out (timestampPerRequest + maxAllowedExecutionDelay)
/// - request must not be a parlay
/// - slippage constraint satisfied
/// If `_allow` is true, executes `sportsAMM.tradeLive(...)` for a single TradeData entry.
/// @param _requestId Chainlink request id being fulfilled
/// @param _allow Whether the trade is allowed after verification
/// @param _approvedQuote Approved quote (odds) for the selected position
function fulfillLiveTrade(
bytes32 _requestId,
bool _allow,
uint _approvedQuote
) external whenNotPaused recordChainlinkFulfillment(_requestId) {
require(!requestIdFulfilled[_requestId], "Request ID already fulfilled");
require((timestampPerRequest[_requestId] + maxAllowedExecutionDelay) > block.timestamp, "Request timed out");
require(!requestIdIsParlay[_requestId], "Request is parlay");
ILiveTradingProcessor.LiveTradeData memory lTradeData = requestIdToTradeData[_requestId];
address requester = requestIdToRequester[_requestId];
// Ensure approved quote respects additional slippage bound relative to expected quote.
require(
((ONE * _approvedQuote) / lTradeData._expectedQuote) <= (ONE + lTradeData._additionalSlippage),
"Slippage too high"
);
if (_allow) {
ISportsAMMV2.TradeData[] memory tradeData = new ISportsAMMV2.TradeData[](1);
tradeData[0] = _buildTradeDataSingle(lTradeData, _approvedQuote);
_executeTrade(
_requestId,
requester,
tradeData,
lTradeData._buyInAmount,
_approvedQuote,
lTradeData._referrer,
lTradeData._collateral
);
}
requestIdToFulfillAllowed[_requestId] = _allow;
requestIdFulfilled[_requestId] = true;
emit LiveTradeFulfilled(
requester,
_requestId,
_allow,
stringToBytes32(lTradeData._gameId),
lTradeData._sportId,
lTradeData._typeId,
lTradeData._line,
lTradeData._position,
lTradeData._buyInAmount,
_approvedQuote,
lTradeData._collateral,
block.timestamp
);
}
/// @notice fulfillLiveTradeParlay (PARLAY)
/// @dev Chainlink callback for parlay live trade verification.
/// Requirements:
/// - request not already fulfilled
/// - request not timed out (timestampPerRequest + maxAllowedExecutionDelay)
/// - request must be a parlay
/// - legsLen > 1 and approvedLegOdds length must match legsLen
/// - slippage constraint satisfied vs expectedPayout
/// If `_allow` is true, executes `sportsAMM.tradeLive(...)` for TradeData[] of length legsLen.
/// @param _requestId Chainlink request id being fulfilled
/// @param _allow Whether the trade is allowed after verification
/// @param _approvedQuote Approved quote for the overall parlay payout
/// @param _approvedLegOdds Approved odds per leg (must match legs length)
function fulfillLiveTradeParlay(
bytes32 _requestId,
bool _allow,
uint _approvedQuote,
uint[] calldata _approvedLegOdds
) external whenNotPaused recordChainlinkFulfillment(_requestId) {
require(!requestIdFulfilled[_requestId], "Request ID already fulfilled");
require((timestampPerRequest[_requestId] + maxAllowedExecutionDelay) > block.timestamp, "Request timed out");
require(requestIdIsParlay[_requestId], "Request is not parlay");
ILiveTradingProcessor.LiveParlayTradeData memory pTrade = requestIdToParlayTradeData[_requestId];
address requester = requestIdToRequester[_requestId];
uint legsLen = pTrade.legs.length;
require(legsLen > 1, "Parlay must have > 1 leg");
require(_approvedLegOdds.length == legsLen, "Bad leg odds length");
// Ensure approved quote respects additional slippage bound relative to expected payout.
require(((ONE * _approvedQuote) / pTrade.expectedPayout) <= (ONE + pTrade.additionalSlippage), "Slippage too high");
if (_allow) {
ISportsAMMV2.TradeData[] memory tradeData = new ISportsAMMV2.TradeData[](legsLen);
for (uint i = 0; i < legsLen; ++i) {
tradeData[i] = _buildTradeDataParlayLeg(pTrade.legs[i], _approvedLegOdds[i]);
}
_executeTrade(
_requestId,
requester,
tradeData,
pTrade.buyInAmount,
_approvedQuote,
pTrade.referrer,
pTrade.collateral
);
}
requestIdToFulfillAllowed[_requestId] = _allow;
requestIdFulfilled[_requestId] = true;
emit LiveParlayTradeFulfilled(requester, _requestId, _allow, uint16(legsLen), pTrade.buyInAmount, _approvedQuote);
}
// ============================
// Internal helpers
// ============================
/// @notice Executes a verified live trade via SportsAMM and performs post-trade confirmation if required.
/// @dev Stores the created ticket address for the request id and optionally confirms via FreeBetsHolder.
/// @param _requestId Chainlink request id associated with the trade
/// @param requester Original requester that initiated the trade request
/// @param tradeData TradeData array to pass to SportsAMMV2.tradeLive (len=1 for singles, len>1 for parlays)
/// @param buyInAmount Buy-in amount for the trade
/// @param approvedQuote Approved quote (overall payout) returned by the verifier
/// @param referrer Referrer address (if any)
/// @param collateral Collateral token used for the trade
function _executeTrade(
bytes32 _requestId,
address requester,
ISportsAMMV2.TradeData[] memory tradeData,
uint buyInAmount,
uint approvedQuote,
address referrer,
address collateral
) internal {
address _createdTicket = sportsAMM.tradeLive(tradeData, buyInAmount, approvedQuote, requester, referrer, collateral);
requestIdToTicketId[_requestId] = _createdTicket;
if (requester == freeBetsHolder) {
IFreeBetsHolder(freeBetsHolder).confirmLiveTrade(_requestId, _createdTicket, buyInAmount, collateral);
}
}
/// @notice Builds TradeData for a single-leg live trade.
/// @dev Creates ODDS_LEN-sized odds array with only selected position set to approvedLegOdd.
/// @param lTradeData Original live trade data requested by the user
/// @param approvedLegOdd Approved odd for the selected position
/// @return td TradeData struct to be passed to SportsAMMV2.tradeLive
function _buildTradeDataSingle(
ILiveTradingProcessor.LiveTradeData memory lTradeData,
uint approvedLegOdd
) internal view returns (ISportsAMMV2.TradeData memory td) {
bytes32[] memory merkleProofs;
uint[] memory odds = new uint[](ODDS_LEN);
odds[lTradeData._position] = approvedLegOdd;
ISportsAMMV2.CombinedPosition[][] memory comPositions = new ISportsAMMV2.CombinedPosition[][](ODDS_LEN);
td = ISportsAMMV2.TradeData(
stringToBytes32(lTradeData._gameId),
lTradeData._sportId,
lTradeData._typeId,
block.timestamp + 60,
0,
lTradeData._line,
lTradeData._playerId,
odds,
merkleProofs,
lTradeData._position,
comPositions
);
}
/// @notice Builds TradeData for a single parlay leg.
/// @dev Creates ODDS_LEN-sized odds array with only leg.position set to approvedLegOdd.
/// @param leg Parlay leg parameters
/// @param approvedLegOdd Approved odd for this specific leg/position
/// @return td TradeData struct to be passed to SportsAMMV2.tradeLive
function _buildTradeDataParlayLeg(
ILiveTradingProcessor.LiveParlayLeg memory leg,
uint approvedLegOdd
) internal view returns (ISportsAMMV2.TradeData memory td) {
bytes32[] memory merkleProofs;
uint[] memory odds = new uint[](ODDS_LEN);
odds[leg.position] = approvedLegOdd;
ISportsAMMV2.CombinedPosition[][] memory comPositions = new ISportsAMMV2.CombinedPosition[][](ODDS_LEN);
td = ISportsAMMV2.TradeData(
stringToBytes32(leg.gameId),
leg.sportId,
leg.typeId,
block.timestamp + 60,
0,
leg.line,
leg.playerId,
odds,
merkleProofs,
leg.position,
comPositions
);
}
/// @notice withdraw collateral in the contract
/// @dev Transfers the full balance of `collateral` held by this contract to `recipient`.
/// @param collateral ERC20 token address to withdraw
/// @param recipient Address receiving withdrawn collateral
function withdrawCollateral(address collateral, address recipient) external onlyOwner {
IERC20(collateral).safeTransfer(recipient, IERC20(collateral).balanceOf(address(this)));
}
//////////// SETTERS
/// @notice pause live trading
/// @dev Pauses or unpauses contract functions protected by whenNotPaused.
/// @param _setPausing whether to pause or unpause
function setPaused(bool _setPausing) external onlyOwner {
_setPausing ? _pause() : _unpause();
}
/// @notice Configuration setter
/// @dev Updates Chainlink and SportsAMM configuration, including both single and parlay job spec ids.
/// @param _link LINK token address used for Chainlink payments
/// @param _oracle Chainlink oracle address
/// @param _sportsAMM SportsAMMV2 contract address
/// @param _jobSpecId Job spec id for SINGLE live verification requests
/// @param _parlayJobSpecId Job spec id for PARLAY live verification requests
/// @param _paymentAmount LINK payment amount per request
function setConfiguration(
address _link,
address _oracle,
address _sportsAMM,
bytes32 _jobSpecId,
bytes32 _parlayJobSpecId,
uint _paymentAmount
) external onlyOwner {
setChainlinkToken(_link);
setChainlinkOracle(_oracle);
sportsAMM = ISportsAMMV2(_sportsAMM);
jobSpecId = _jobSpecId;
parlayJobSpecId = _parlayJobSpecId;
paymentAmount = _paymentAmount;
emit ContextReset(_link, _oracle, _sportsAMM, _jobSpecId, _parlayJobSpecId, _paymentAmount);
}
/// @notice sets the FreeBetsHolder address, required for handling ticket claiming via FreeBetsHolder
/// @param _freeBetsHolder FreeBetsHolder contract address
function setFreeBetsHolder(address _freeBetsHolder) external onlyOwner {
freeBetsHolder = _freeBetsHolder;
emit SetFreeBetsHolder(_freeBetsHolder);
}
/// @notice setMaxAllowedExecutionDelay
/// @dev Sets maximum allowed buffer for the Chainlink request to be executed.
/// @param _maxAllowedExecutionDelay maximum allowed buffer in seconds
function setMaxAllowedExecutionDelay(uint _maxAllowedExecutionDelay) external onlyOwner {
maxAllowedExecutionDelay = _maxAllowedExecutionDelay;
emit SetMaxAllowedExecutionDelay(_maxAllowedExecutionDelay);
}
//// GETTERS
/// @notice gets trade data struct for specified request ID (singles)
/// @param requestId request ID
/// @return liveTradeData Stored LiveTradeData for requestId
function getTradeData(bytes32 requestId) external view returns (ILiveTradingProcessor.LiveTradeData memory) {
return requestIdToTradeData[requestId];
}
/// @notice gets parlay trade data struct for specified request ID (parlays)
/// @param requestId request ID
/// @return parlayTradeData Stored LiveParlayTradeData for requestId
function getParlayTradeData(bytes32 requestId) external view returns (ILiveTradingProcessor.LiveParlayTradeData memory) {
return requestIdToParlayTradeData[requestId];
}
//// UTILITY
/// @notice Converts a string into bytes32 by taking the first 32 bytes.
/// @dev Returns 0x0 for empty strings. Used for gameId conversions.
function stringToBytes32(string memory source) internal pure returns (bytes32 result) {
bytes memory tempEmptyStringTest = bytes(source);
if (tempEmptyStringTest.length == 0) {
return 0x0;
}
assembly {
result := mload(add(source, 32))
}
}
/// @notice Converts signed integer into string representation.
/// @dev Used for encoding negative lines in Chainlink request arrays.
function _intToString(int256 value) internal pure returns (string memory) {
if (value >= 0) {
return Strings.toString(uint256(value));
}
return string(abi.encodePacked("-", Strings.toString(uint256(-value))));
}
/////// EVENTS
event ContextReset(
address _link,
address _oracle,
address _sportsAMM,
bytes32 _jobSpecId,
bytes32 _parlayJobSpecId,
uint _paymentAmount
);
event LiveTradeRequested(
address requester,
uint requestCounter,
bytes32 requestId,
bytes32 _gameId,
uint16 _sportId,
uint16 _typeId,
int24 _line,
uint8 _position,
uint _buyInAmount,
uint _expectedQuote,
address _collateral
);
event LiveTradeFulfilled(
address requester,
bytes32 requestId,
bool _allow,
bytes32 _gameId,
uint16 _sportId,
uint16 _typeId,
int24 _line,
uint8 _position,
uint _buyInAmount,
uint _expectedQuote,
address _collateral,
uint timestamp
);
event LiveParlayTradeRequested(
address requester,
uint requestCounter,
bytes32 requestId,
uint16 legsCount,
uint buyInAmount
);
event LiveParlayTradeFulfilled(
address requester,
bytes32 requestId,
bool _allow,
uint16 legsCount,
uint buyInAmount,
uint approvedQuote
);
event SetMaxAllowedExecutionDelay(uint _maxAllowedExecutionDelay);
event SetFreeBetsHolder(address _freeBetsHolder);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {CBORChainlink} from "./vendor/CBORChainlink.sol";
import {BufferChainlink} from "./vendor/BufferChainlink.sol";
/**
* @title Library for common Chainlink functions
* @dev Uses imported CBOR library for encoding to buffer
*/
library Chainlink {
uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase
using CBORChainlink for BufferChainlink.buffer;
struct Request {
bytes32 id;
address callbackAddress;
bytes4 callbackFunctionId;
uint256 nonce;
BufferChainlink.buffer buf;
}
/**
* @notice Initializes a Chainlink request
* @dev Sets the ID, callback address, and callback function signature on the request
* @param self The uninitialized request
* @param jobId The Job Specification ID
* @param callbackAddr The callback address
* @param callbackFunc The callback function signature
* @return The initialized request
*/
function initialize(
Request memory self,
bytes32 jobId,
address callbackAddr,
bytes4 callbackFunc
) internal pure returns (Chainlink.Request memory) {
BufferChainlink.init(self.buf, defaultBufferSize);
self.id = jobId;
self.callbackAddress = callbackAddr;
self.callbackFunctionId = callbackFunc;
return self;
}
/**
* @notice Sets the data for the buffer without encoding CBOR on-chain
* @dev CBOR can be closed with curly-brackets {} or they can be left off
* @param self The initialized request
* @param data The CBOR data
*/
function setBuffer(Request memory self, bytes memory data) internal pure {
BufferChainlink.init(self.buf, data.length);
BufferChainlink.append(self.buf, data);
}
/**
* @notice Adds a string value to the request with a given key name
* @param self The initialized request
* @param key The name of the key
* @param value The string value to add
*/
function add(
Request memory self,
string memory key,
string memory value
) internal pure {
self.buf.encodeString(key);
self.buf.encodeString(value);
}
/**
* @notice Adds a bytes value to the request with a given key name
* @param self The initialized request
* @param key The name of the key
* @param value The bytes value to add
*/
function addBytes(
Request memory self,
string memory key,
bytes memory value
) internal pure {
self.buf.encodeString(key);
self.buf.encodeBytes(value);
}
/**
* @notice Adds a int256 value to the request with a given key name
* @param self The initialized request
* @param key The name of the key
* @param value The int256 value to add
*/
function addInt(
Request memory self,
string memory key,
int256 value
) internal pure {
self.buf.encodeString(key);
self.buf.encodeInt(value);
}
/**
* @notice Adds a uint256 value to the request with a given key name
* @param self The initialized request
* @param key The name of the key
* @param value The uint256 value to add
*/
function addUint(
Request memory self,
string memory key,
uint256 value
) internal pure {
self.buf.encodeString(key);
self.buf.encodeUInt(value);
}
/**
* @notice Adds an array of strings to the request with a given key name
* @param self The initialized request
* @param key The name of the key
* @param values The array of string values to add
*/
function addStringArray(
Request memory self,
string memory key,
string[] memory values
) internal pure {
self.buf.encodeString(key);
self.buf.startArray();
for (uint256 i = 0; i < values.length; i++) {
self.buf.encodeString(values[i]);
}
self.buf.endSequence();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./Chainlink.sol";
import "./interfaces/ENSInterface.sol";
import "./interfaces/LinkTokenInterface.sol";
import "./interfaces/ChainlinkRequestInterface.sol";
import "./interfaces/OperatorInterface.sol";
import "./interfaces/PointerInterface.sol";
import {ENSResolver as ENSResolver_Chainlink} from "./vendor/ENSResolver.sol";
/**
* @title The ChainlinkClient contract
* @notice Contract writers can inherit this contract in order to create requests for the
* Chainlink network
*/
abstract contract ChainlinkClient {
using Chainlink for Chainlink.Request;
uint256 internal constant LINK_DIVISIBILITY = 10**18;
uint256 private constant AMOUNT_OVERRIDE = 0;
address private constant SENDER_OVERRIDE = address(0);
uint256 private constant ORACLE_ARGS_VERSION = 1;
uint256 private constant OPERATOR_ARGS_VERSION = 2;
bytes32 private constant ENS_TOKEN_SUBNAME = keccak256("link");
bytes32 private constant ENS_ORACLE_SUBNAME = keccak256("oracle");
address private constant LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571;
ENSInterface private s_ens;
bytes32 private s_ensNode;
LinkTokenInterface private s_link;
OperatorInterface private s_oracle;
uint256 private s_requestCount = 1;
mapping(bytes32 => address) private s_pendingRequests;
event ChainlinkRequested(bytes32 indexed id);
event ChainlinkFulfilled(bytes32 indexed id);
event ChainlinkCancelled(bytes32 indexed id);
/**
* @notice Creates a request that can hold additional parameters
* @param specId The Job Specification ID that the request will be created for
* @param callbackAddr address to operate the callback on
* @param callbackFunctionSignature function signature to use for the callback
* @return A Chainlink Request struct in memory
*/
function buildChainlinkRequest(
bytes32 specId,
address callbackAddr,
bytes4 callbackFunctionSignature
) internal pure returns (Chainlink.Request memory) {
Chainlink.Request memory req;
return req.initialize(specId, callbackAddr, callbackFunctionSignature);
}
/**
* @notice Creates a request that can hold additional parameters
* @param specId The Job Specification ID that the request will be created for
* @param callbackFunctionSignature function signature to use for the callback
* @return A Chainlink Request struct in memory
*/
function buildOperatorRequest(bytes32 specId, bytes4 callbackFunctionSignature)
internal
view
returns (Chainlink.Request memory)
{
Chainlink.Request memory req;
return req.initialize(specId, address(this), callbackFunctionSignature);
}
/**
* @notice Creates a Chainlink request to the stored oracle address
* @dev Calls `chainlinkRequestTo` with the stored oracle address
* @param req The initialized Chainlink Request
* @param payment The amount of LINK to send for the request
* @return requestId The request ID
*/
function sendChainlinkRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) {
return sendChainlinkRequestTo(address(s_oracle), req, payment);
}
/**
* @notice Creates a Chainlink request to the specified oracle address
* @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to
* send LINK which creates a request on the target oracle contract.
* Emits ChainlinkRequested event.
* @param oracleAddress The address of the oracle for the request
* @param req The initialized Chainlink Request
* @param payment The amount of LINK to send for the request
* @return requestId The request ID
*/
function sendChainlinkRequestTo(
address oracleAddress,
Chainlink.Request memory req,
uint256 payment
) internal returns (bytes32 requestId) {
uint256 nonce = s_requestCount;
s_requestCount = nonce + 1;
bytes memory encodedRequest = abi.encodeWithSelector(
ChainlinkRequestInterface.oracleRequest.selector,
SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address
AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent
req.id,
address(this),
req.callbackFunctionId,
nonce,
ORACLE_ARGS_VERSION,
req.buf.buf
);
return _rawRequest(oracleAddress, nonce, payment, encodedRequest);
}
/**
* @notice Creates a Chainlink request to the stored oracle address
* @dev This function supports multi-word response
* @dev Calls `sendOperatorRequestTo` with the stored oracle address
* @param req The initialized Chainlink Request
* @param payment The amount of LINK to send for the request
* @return requestId The request ID
*/
function sendOperatorRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) {
return sendOperatorRequestTo(address(s_oracle), req, payment);
}
/**
* @notice Creates a Chainlink request to the specified oracle address
* @dev This function supports multi-word response
* @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to
* send LINK which creates a request on the target oracle contract.
* Emits ChainlinkRequested event.
* @param oracleAddress The address of the oracle for the request
* @param req The initialized Chainlink Request
* @param payment The amount of LINK to send for the request
* @return requestId The request ID
*/
function sendOperatorRequestTo(
address oracleAddress,
Chainlink.Request memory req,
uint256 payment
) internal returns (bytes32 requestId) {
uint256 nonce = s_requestCount;
s_requestCount = nonce + 1;
bytes memory encodedRequest = abi.encodeWithSelector(
OperatorInterface.operatorRequest.selector,
SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address
AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent
req.id,
req.callbackFunctionId,
nonce,
OPERATOR_ARGS_VERSION,
req.buf.buf
);
return _rawRequest(oracleAddress, nonce, payment, encodedRequest);
}
/**
* @notice Make a request to an oracle
* @param oracleAddress The address of the oracle for the request
* @param nonce used to generate the request ID
* @param payment The amount of LINK to send for the request
* @param encodedRequest data encoded for request type specific format
* @return requestId The request ID
*/
function _rawRequest(
address oracleAddress,
uint256 nonce,
uint256 payment,
bytes memory encodedRequest
) private returns (bytes32 requestId) {
requestId = keccak256(abi.encodePacked(this, nonce));
s_pendingRequests[requestId] = oracleAddress;
emit ChainlinkRequested(requestId);
require(s_link.transferAndCall(oracleAddress, payment, encodedRequest), "unable to transferAndCall to oracle");
}
/**
* @notice Allows a request to be cancelled if it has not been fulfilled
* @dev Requires keeping track of the expiration value emitted from the oracle contract.
* Deletes the request from the `pendingRequests` mapping.
* Emits ChainlinkCancelled event.
* @param requestId The request ID
* @param payment The amount of LINK sent for the request
* @param callbackFunc The callback function specified for the request
* @param expiration The time of the expiration for the request
*/
function cancelChainlinkRequest(
bytes32 requestId,
uint256 payment,
bytes4 callbackFunc,
uint256 expiration
) internal {
OperatorInterface requested = OperatorInterface(s_pendingRequests[requestId]);
delete s_pendingRequests[requestId];
emit ChainlinkCancelled(requestId);
requested.cancelOracleRequest(requestId, payment, callbackFunc, expiration);
}
/**
* @notice the next request count to be used in generating a nonce
* @dev starts at 1 in order to ensure consistent gas cost
* @return returns the next request count to be used in a nonce
*/
function getNextRequestCount() internal view returns (uint256) {
return s_requestCount;
}
/**
* @notice Sets the stored oracle address
* @param oracleAddress The address of the oracle contract
*/
function setChainlinkOracle(address oracleAddress) internal {
s_oracle = OperatorInterface(oracleAddress);
}
/**
* @notice Sets the LINK token address
* @param linkAddress The address of the LINK token contract
*/
function setChainlinkToken(address linkAddress) internal {
s_link = LinkTokenInterface(linkAddress);
}
/**
* @notice Sets the Chainlink token address for the public
* network as given by the Pointer contract
*/
function setPublicChainlinkToken() internal {
setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress());
}
/**
* @notice Retrieves the stored address of the LINK token
* @return The address of the LINK token
*/
function chainlinkTokenAddress() internal view returns (address) {
return address(s_link);
}
/**
* @notice Retrieves the stored address of the oracle contract
* @return The address of the oracle contract
*/
function chainlinkOracleAddress() internal view returns (address) {
return address(s_oracle);
}
/**
* @notice Allows for a request which was created on another contract to be fulfilled
* on this contract
* @param oracleAddress The address of the oracle contract that will fulfill the request
* @param requestId The request ID used for the response
*/
function addChainlinkExternalRequest(address oracleAddress, bytes32 requestId) internal notPendingRequest(requestId) {
s_pendingRequests[requestId] = oracleAddress;
}
/**
* @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS
* @dev Accounts for subnodes having different resolvers
* @param ensAddress The address of the ENS contract
* @param node The ENS node hash
*/
function useChainlinkWithENS(address ensAddress, bytes32 node) internal {
s_ens = ENSInterface(ensAddress);
s_ensNode = node;
bytes32 linkSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_TOKEN_SUBNAME));
ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(linkSubnode));
setChainlinkToken(resolver.addr(linkSubnode));
updateChainlinkOracleWithENS();
}
/**
* @notice Sets the stored oracle contract with the address resolved by ENS
* @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously
*/
function updateChainlinkOracleWithENS() internal {
bytes32 oracleSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_ORACLE_SUBNAME));
ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(oracleSubnode));
setChainlinkOracle(resolver.addr(oracleSubnode));
}
/**
* @notice Ensures that the fulfillment is valid for this contract
* @dev Use if the contract developer prefers methods instead of modifiers for validation
* @param requestId The request ID for fulfillment
*/
function validateChainlinkCallback(bytes32 requestId)
internal
recordChainlinkFulfillment(requestId)
// solhint-disable-next-line no-empty-blocks
{
}
/**
* @dev Reverts if the sender is not the oracle of the request.
* Emits ChainlinkFulfilled event.
* @param requestId The request ID for fulfillment
*/
modifier recordChainlinkFulfillment(bytes32 requestId) {
require(msg.sender == s_pendingRequests[requestId], "Source must be the oracle of the request");
delete s_pendingRequests[requestId];
emit ChainlinkFulfilled(requestId);
_;
}
/**
* @dev Reverts if the request is already pending
* @param requestId The request ID for fulfillment
*/
modifier notPendingRequest(bytes32 requestId) {
require(s_pendingRequests[requestId] == address(0), "Request is already pending");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ChainlinkRequestInterface {
function oracleRequest(
address sender,
uint256 requestPrice,
bytes32 serviceAgreementID,
address callbackAddress,
bytes4 callbackFunctionId,
uint256 nonce,
uint256 dataVersion,
bytes calldata data
) external;
function cancelOracleRequest(
bytes32 requestId,
uint256 payment,
bytes4 callbackFunctionId,
uint256 expiration
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ENSInterface {
// Logged when the owner of a node assigns a new owner to a subnode.
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
// Logged when the owner of a node transfers ownership to a new account.
event Transfer(bytes32 indexed node, address owner);
// Logged when the resolver for a node changes.
event NewResolver(bytes32 indexed node, address resolver);
// Logged when the TTL of a node changes
event NewTTL(bytes32 indexed node, uint64 ttl);
function setSubnodeOwner(
bytes32 node,
bytes32 label,
address owner
) external;
function setResolver(bytes32 node, address resolver) external;
function setOwner(bytes32 node, address owner) external;
function setTTL(bytes32 node, uint64 ttl) external;
function owner(bytes32 node) external view returns (address);
function resolver(bytes32 node) external view returns (address);
function ttl(bytes32 node) external view returns (uint64);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./OracleInterface.sol";
import "./ChainlinkRequestInterface.sol";
interface OperatorInterface is OracleInterface, ChainlinkRequestInterface {
function operatorRequest(
address sender,
uint256 payment,
bytes32 specId,
bytes4 callbackFunctionId,
uint256 nonce,
uint256 dataVersion,
bytes calldata data
) external;
function fulfillOracleRequest2(
bytes32 requestId,
uint256 payment,
address callbackAddress,
bytes4 callbackFunctionId,
uint256 expiration,
bytes calldata data
) external returns (bool);
function ownerTransferAndCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool success);
function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable;
function getAuthorizedSenders() external returns (address[] memory);
function setAuthorizedSenders(address[] calldata senders) external;
function getForwarder() external returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface OracleInterface {
function fulfillOracleRequest(
bytes32 requestId,
uint256 payment,
address callbackAddress,
bytes4 callbackFunctionId,
uint256 expiration,
bytes32 data
) external returns (bool);
function isAuthorizedSender(address node) external view returns (bool);
function withdraw(address recipient, uint256 amount) external;
function withdrawable() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface PointerInterface {
function getAddress() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev A library for working with mutable byte buffers in Solidity.
*
* Byte buffers are mutable and expandable, and provide a variety of primitives
* for writing to them. At any time you can fetch a bytes object containing the
* current contents of the buffer. The bytes object should not be stored between
* operations, as it may change due to resizing of the buffer.
*/
library BufferChainlink {
/**
* @dev Represents a mutable buffer. Buffers have a current value (buf) and
* a capacity. The capacity may be longer than the current value, in
* which case it can be extended without the need to allocate more memory.
*/
struct buffer {
bytes buf;
uint256 capacity;
}
/**
* @dev Initializes a buffer with an initial capacity.
* @param buf The buffer to initialize.
* @param capacity The number of bytes of space to allocate the buffer.
* @return The buffer, for chaining.
*/
function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) {
if (capacity % 32 != 0) {
capacity += 32 - (capacity % 32);
}
// Allocate space for the buffer data
buf.capacity = capacity;
assembly {
let ptr := mload(0x40)
mstore(buf, ptr)
mstore(ptr, 0)
mstore(0x40, add(32, add(ptr, capacity)))
}
return buf;
}
/**
* @dev Initializes a new buffer from an existing bytes object.
* Changes to the buffer may mutate the original value.
* @param b The bytes object to initialize the buffer with.
* @return A new buffer.
*/
function fromBytes(bytes memory b) internal pure returns (buffer memory) {
buffer memory buf;
buf.buf = b;
buf.capacity = b.length;
return buf;
}
function resize(buffer memory buf, uint256 capacity) private pure {
bytes memory oldbuf = buf.buf;
init(buf, capacity);
append(buf, oldbuf);
}
function max(uint256 a, uint256 b) private pure returns (uint256) {
if (a > b) {
return a;
}
return b;
}
/**
* @dev Sets buffer length to 0.
* @param buf The buffer to truncate.
* @return The original buffer, for chaining..
*/
function truncate(buffer memory buf) internal pure returns (buffer memory) {
assembly {
let bufptr := mload(buf)
mstore(bufptr, 0)
}
return buf;
}
/**
* @dev Writes a byte string to a buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param off The start offset to write to.
* @param data The data to append.
* @param len The number of bytes to copy.
* @return The original buffer, for chaining.
*/
function write(
buffer memory buf,
uint256 off,
bytes memory data,
uint256 len
) internal pure returns (buffer memory) {
require(len <= data.length);
if (off + len > buf.capacity) {
resize(buf, max(buf.capacity, len + off) * 2);
}
uint256 dest;
uint256 src;
assembly {
// Memory address of the buffer data
let bufptr := mload(buf)
// Length of existing buffer data
let buflen := mload(bufptr)
// Start address = buffer address + offset + sizeof(buffer length)
dest := add(add(bufptr, 32), off)
// Update buffer length if we're extending it
if gt(add(len, off), buflen) {
mstore(bufptr, add(len, off))
}
src := add(data, 32)
}
// Copy word-length chunks while possible
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
unchecked {
uint256 mask = (256**(32 - len)) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
return buf;
}
/**
* @dev Appends a byte string to a buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @param len The number of bytes to copy.
* @return The original buffer, for chaining.
*/
function append(
buffer memory buf,
bytes memory data,
uint256 len
) internal pure returns (buffer memory) {
return write(buf, buf.buf.length, data, len);
}
/**
* @dev Appends a byte string to a buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer, for chaining.
*/
function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {
return write(buf, buf.buf.length, data, data.length);
}
/**
* @dev Writes a byte to the buffer. Resizes if doing so would exceed the
* capacity of the buffer.
* @param buf The buffer to append to.
* @param off The offset to write the byte at.
* @param data The data to append.
* @return The original buffer, for chaining.
*/
function writeUint8(
buffer memory buf,
uint256 off,
uint8 data
) internal pure returns (buffer memory) {
if (off >= buf.capacity) {
resize(buf, buf.capacity * 2);
}
assembly {
// Memory address of the buffer data
let bufptr := mload(buf)
// Length of existing buffer data
let buflen := mload(bufptr)
// Address = buffer address + sizeof(buffer length) + off
let dest := add(add(bufptr, off), 32)
mstore8(dest, data)
// Update buffer length if we extended it
if eq(off, buflen) {
mstore(bufptr, add(buflen, 1))
}
}
return buf;
}
/**
* @dev Appends a byte to the buffer. Resizes if doing so would exceed the
* capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer, for chaining.
*/
function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) {
return writeUint8(buf, buf.buf.length, data);
}
/**
* @dev Writes up to 32 bytes to the buffer. Resizes if doing so would
* exceed the capacity of the buffer.
* @param buf The buffer to append to.
* @param off The offset to write at.
* @param data The data to append.
* @param len The number of bytes to write (left-aligned).
* @return The original buffer, for chaining.
*/
function write(
buffer memory buf,
uint256 off,
bytes32 data,
uint256 len
) private pure returns (buffer memory) {
if (len + off > buf.capacity) {
resize(buf, (len + off) * 2);
}
unchecked {
uint256 mask = (256**len) - 1;
// Right-align data
data = data >> (8 * (32 - len));
assembly {
// Memory address of the buffer data
let bufptr := mload(buf)
// Address = buffer address + sizeof(buffer length) + off + len
let dest := add(add(bufptr, off), len)
mstore(dest, or(and(mload(dest), not(mask)), data))
// Update buffer length if we extended it
if gt(add(off, len), mload(bufptr)) {
mstore(bufptr, add(off, len))
}
}
}
return buf;
}
/**
* @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the
* capacity of the buffer.
* @param buf The buffer to append to.
* @param off The offset to write at.
* @param data The data to append.
* @return The original buffer, for chaining.
*/
function writeBytes20(
buffer memory buf,
uint256 off,
bytes20 data
) internal pure returns (buffer memory) {
return write(buf, off, bytes32(data), 20);
}
/**
* @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer, for chhaining.
*/
function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {
return write(buf, buf.buf.length, bytes32(data), 20);
}
/**
* @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer, for chaining.
*/
function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {
return write(buf, buf.buf.length, data, 32);
}
/**
* @dev Writes an integer to the buffer. Resizes if doing so would exceed
* the capacity of the buffer.
* @param buf The buffer to append to.
* @param off The offset to write at.
* @param data The data to append.
* @param len The number of bytes to write (right-aligned).
* @return The original buffer, for chaining.
*/
function writeInt(
buffer memory buf,
uint256 off,
uint256 data,
uint256 len
) private pure returns (buffer memory) {
if (len + off > buf.capacity) {
resize(buf, (len + off) * 2);
}
uint256 mask = (256**len) - 1;
assembly {
// Memory address of the buffer data
let bufptr := mload(buf)
// Address = buffer address + off + sizeof(buffer length) + len
let dest := add(add(bufptr, off), len)
mstore(dest, or(and(mload(dest), not(mask)), data))
// Update buffer length if we extended it
if gt(add(off, len), mload(bufptr)) {
mstore(bufptr, add(off, len))
}
}
return buf;
}
/**
* @dev Appends a byte to the end of the buffer. Resizes if doing so would
* exceed the capacity of the buffer.
* @param buf The buffer to append to.
* @param data The data to append.
* @return The original buffer.
*/
function appendInt(
buffer memory buf,
uint256 data,
uint256 len
) internal pure returns (buffer memory) {
return writeInt(buf, buf.buf.length, data, len);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.4.19;
import {BufferChainlink} from "./BufferChainlink.sol";
library CBORChainlink {
using BufferChainlink for BufferChainlink.buffer;
uint8 private constant MAJOR_TYPE_INT = 0;
uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1;
uint8 private constant MAJOR_TYPE_BYTES = 2;
uint8 private constant MAJOR_TYPE_STRING = 3;
uint8 private constant MAJOR_TYPE_ARRAY = 4;
uint8 private constant MAJOR_TYPE_MAP = 5;
uint8 private constant MAJOR_TYPE_TAG = 6;
uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7;
uint8 private constant TAG_TYPE_BIGNUM = 2;
uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3;
function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure {
if(value <= 23) {
buf.appendUint8(uint8((major << 5) | value));
} else if (value <= 0xFF) {
buf.appendUint8(uint8((major << 5) | 24));
buf.appendInt(value, 1);
} else if (value <= 0xFFFF) {
buf.appendUint8(uint8((major << 5) | 25));
buf.appendInt(value, 2);
} else if (value <= 0xFFFFFFFF) {
buf.appendUint8(uint8((major << 5) | 26));
buf.appendInt(value, 4);
} else {
buf.appendUint8(uint8((major << 5) | 27));
buf.appendInt(value, 8);
}
}
function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure {
buf.appendUint8(uint8((major << 5) | 31));
}
function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure {
if(value > 0xFFFFFFFFFFFFFFFF) {
encodeBigNum(buf, value);
} else {
encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value));
}
}
function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure {
if(value < -0x10000000000000000) {
encodeSignedBigNum(buf, value);
} else if(value > 0xFFFFFFFFFFFFFFFF) {
encodeBigNum(buf, uint(value));
} else if(value >= 0) {
encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(uint256(value)));
} else {
encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(uint256(-1 - value)));
}
}
function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure {
encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length));
buf.append(value);
}
function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure {
buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM));
encodeBytes(buf, abi.encode(value));
}
function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure {
buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM));
encodeBytes(buf, abi.encode(uint256(-1 - input)));
}
function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure {
encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length));
buf.append(bytes(value));
}
function startArray(BufferChainlink.buffer memory buf) internal pure {
encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY);
}
function startMap(BufferChainlink.buffer memory buf) internal pure {
encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP);
}
function endSequence(BufferChainlink.buffer memory buf) internal pure {
encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
abstract contract ENSResolver {
function addr(bytes32 node) public view virtual returns (address);
}// 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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../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 {
bool private _paused;
/**
* @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);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @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 {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @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());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IProxyBetting.sol";
interface IFreeBetsHolder is IProxyBetting {
function ticketToUser(address _createdTicket) external view returns (address);
function confirmLiveTrade(bytes32 requestId, address _createdTicket, uint _buyInAmount, address _collateral) external;
function confirmSGPTrade(bytes32 requestId, address _createdTicket, uint _buyInAmount, address _collateral) external;
function balancePerUserAndCollateral(address user, address collateral) external view returns (uint);
function freeBetExpiration(address user, address collateral) external view returns (uint);
function freeBetExpirationUpgrade() external view returns (uint);
function freeBetExpirationPeriod() external view returns (uint);
function confirmSpeedOrChainedSpeedMarketTrade(
bytes32 _requestId,
address _speedMarketAddress,
address _collateral,
uint _buyinAmount,
bool _isChained
) external;
function confirmSpeedMarketResolved(
address _resolvedTicket,
uint _exercized,
uint _buyInAmount,
address _collateral,
bool isChained
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface ILiveTradingProcessor {
struct LiveTradeData {
string _gameId;
uint16 _sportId;
uint16 _typeId;
int24 _line;
uint8 _position;
uint _buyInAmount;
uint _expectedQuote;
uint _additionalSlippage;
address _referrer;
address _collateral;
uint24 _playerId; // player props
}
struct LiveParlayLeg {
string gameId;
uint16 sportId;
uint16 typeId;
int24 line;
uint8 position;
uint expectedLegOdd; // optional; node-side hint
uint24 playerId;
}
struct LiveParlayTradeData {
LiveParlayLeg[] legs;
uint buyInAmount;
uint expectedPayout;
uint additionalSlippage;
address referrer;
address collateral;
}
// =========================
// Views
// =========================
function freeBetsHolder() external view returns (address);
function maxAllowedExecutionDelay() external view returns (uint);
function requestCounter() external view returns (uint);
function counterToRequestId(uint _counter) external view returns (bytes32);
function requestIdToRequester(bytes32 _requestId) external view returns (address);
function requestIdIsParlay(bytes32 _requestId) external view returns (bool);
function requestIdToTicketId(bytes32 _requestId) external view returns (address);
function requestIdFulfilled(bytes32 _requestId) external view returns (bool);
function timestampPerRequest(bytes32 _requestId) external view returns (uint);
function getTradeData(bytes32 _requestId) external view returns (LiveTradeData memory);
function getParlayTradeData(bytes32 _requestId) external view returns (LiveParlayTradeData memory);
// =========================
// Actions
// =========================
function requestLiveTrade(LiveTradeData calldata _liveTradeData) external returns (bytes32);
function requestLiveParlayTrade(LiveParlayTradeData calldata _parlay) external returns (bytes32);
/**
* @notice SINGLE fulfill (backwards-compatible with production)
*/
function fulfillLiveTrade(bytes32 _requestId, bool allow, uint approvedQuote) external;
/**
* @notice PARLAY fulfill (new)
* @dev approvedLegOdds.length must equal number of legs
*/
function fulfillLiveTradeParlay(
bytes32 _requestId,
bool allow,
uint approvedQuote,
uint[] calldata approvedLegOdds
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IProxyBetting {
function getActiveTicketsPerUser(uint _index, uint _pageSize, address _user) external view returns (address[] memory);
function numOfActiveTicketsPerUser(address _user) external view returns (uint);
function getResolvedTicketsPerUser(uint _index, uint _pageSize, address _user) external view returns (address[] memory);
function numOfResolvedTicketsPerUser(address _user) external view returns (uint);
function confirmTicketResolved(address _resolvedTicket) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/ISportsAMMV2Manager.sol";
import "../interfaces/ISportsAMMV2ResultManager.sol";
import "../interfaces/ISportsAMMV2RiskManager.sol";
import "../interfaces/ISportsAMMV2Manager.sol";
import "../interfaces/IFreeBetsHolder.sol";
import "../interfaces/IStakingThalesBettingProxy.sol";
interface ISportsAMMV2 {
enum TicketAction {
Exercise,
Cancel,
MarkLost
}
struct CombinedPosition {
uint16 typeId;
uint8 position;
int24 line;
}
struct TradeData {
bytes32 gameId;
uint16 sportId;
uint16 typeId;
uint maturity;
uint8 status;
int24 line;
uint24 playerId;
uint[] odds;
bytes32[] merkleProof;
uint8 position;
CombinedPosition[][] combinedPositions;
}
function defaultCollateral() external view returns (IERC20);
function manager() external view returns (ISportsAMMV2Manager);
function resultManager() external view returns (ISportsAMMV2ResultManager);
function safeBoxFee() external view returns (uint);
function handleTicketResolving(address _ticket, ISportsAMMV2.TicketAction action) external;
function riskManager() external view returns (ISportsAMMV2RiskManager);
function freeBetsHolder() external view returns (IFreeBetsHolder);
function stakingThalesBettingProxy() external view returns (IStakingThalesBettingProxy);
function tradeLive(
TradeData[] calldata _tradeData,
uint _buyInAmount,
uint _expectedQuote,
address _recipient,
address _referrer,
address _collateral
) external returns (address _createdTicket);
function trade(
TradeData[] calldata _tradeData,
uint _buyInAmount,
uint _expectedQuote,
uint _additionalSlippage,
address _referrer,
address _collateral,
bool _isEth
) external returns (address _createdTicket);
function tradeSystemBet(
TradeData[] calldata _tradeData,
uint _buyInAmount,
uint _expectedQuote,
uint _additionalSlippage,
address _referrer,
address _collateral,
bool _isEth,
uint8 _systemBetDenominator
) external returns (address _createdTicket);
function tradeSGP(
ISportsAMMV2.TradeData[] calldata _tradeData,
uint _buyInAmount,
uint _approvedQuote,
address _recipient,
address _referrer,
address _collateral
) external returns (address _createdTicket);
function rootPerGame(bytes32 game) external view returns (bytes32);
function getRootsPerGames(bytes32[] calldata _games) external view returns (bytes32[] memory _roots);
function paused() external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./ISportsAMMV2.sol";
interface ISportsAMMV2Manager {
enum Role {
ROOT_SETTING,
RISK_MANAGING,
MARKET_RESOLVING,
TICKET_PAUSER
}
function isWhitelistedAddress(address _address, Role role) external view returns (bool);
function decimals() external view returns (uint);
function feeToken() external view returns (address);
function isActiveTicket(address _ticket) external view returns (bool);
function getActiveTickets(uint _index, uint _pageSize) external view returns (address[] memory);
function numOfActiveTickets() external view returns (uint);
function getActiveTicketsPerUser(uint _index, uint _pageSize, address _user) external view returns (address[] memory);
function numOfActiveTicketsPerUser(address _user) external view returns (uint);
function getResolvedTicketsPerUser(uint _index, uint _pageSize, address _user) external view returns (address[] memory);
function numOfResolvedTicketsPerUser(address _user) external view returns (uint);
function getTicketsPerGame(uint _index, uint _pageSize, bytes32 _gameId) external view returns (address[] memory);
function numOfTicketsPerGame(bytes32 _gameId) external view returns (uint);
function isKnownTicket(address _ticket) external view returns (bool);
function sportsAMM() external view returns (address);
function getTicketsPerMarket(
uint _index,
uint _pageSize,
bytes32 _gameId,
uint _typeId,
uint _playerId
) external view returns (address[] memory);
function numOfTicketsPerMarket(bytes32 _gameId, uint _typeId, uint _playerId) external view returns (uint);
function addNewKnownTicket(ISportsAMMV2.TradeData[] memory _tradeData, address ticket, address user) external;
function resolveKnownTicket(address ticket, address ticketOwner) external;
function expireKnownTicket(address ticket, address ticketOwner) external;
function isSystemTicket(address _ticket) external view returns (bool);
function isSGPTicket(address _ticket) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./ISportsAMMV2.sol";
interface ISportsAMMV2ResultManager {
enum MarketPositionStatus {
Open,
Cancelled,
Winning,
Losing
}
function isMarketResolved(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
ISportsAMMV2.CombinedPosition[] memory combinedPositions
) external view returns (bool isResolved);
function getMarketPositionStatus(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _position,
ISportsAMMV2.CombinedPosition[] memory _combinedPositions
) external view returns (MarketPositionStatus status);
function isWinningMarketPosition(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _position,
ISportsAMMV2.CombinedPosition[] memory _combinedPositions
) external view returns (bool isWinning);
function isCancelledMarketPosition(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _position,
ISportsAMMV2.CombinedPosition[] memory _combinedPositions
) external view returns (bool isCancelled);
function getResultsPerMarket(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId
) external view returns (int24[] memory results);
function resultTypePerMarketType(uint _typeId) external view returns (uint8 marketType);
function isMarketResolvedAndPositionWinning(
bytes32 _gameId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _position,
ISportsAMMV2.CombinedPosition[] memory _combinedPositions
) external view returns (bool isResolved, bool isWinning);
function setResultsPerMarkets(
bytes32[] memory _gameIds,
uint16[] memory _typeIds,
uint24[] memory _playerIds,
int24[][] memory _results
) external;
function isGameCancelled(bytes32 _gameId) external view returns (bool);
function cancelGames(bytes32[] memory _gameIds) external;
function cancelMarkets(
bytes32[] memory _gameIds,
uint16[] memory _typeIds,
uint24[] memory _playerIds,
int24[] memory _lines
) external;
function cancelMarket(bytes32 _gameId, uint16 _typeId, uint24 _playerId, int24 _line) external;
function cancelGame(bytes32 _gameId) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./ISportsAMMV2.sol";
interface ISportsAMMV2RiskManager {
struct TypeCap {
uint typeId;
uint cap;
}
struct CapData {
uint capPerSport;
uint capPerChild;
TypeCap[] capPerType;
}
struct DynamicLiquidityData {
uint cutoffTimePerSport;
uint cutoffDividerPerSport;
}
struct RiskData {
uint sportId;
CapData capData;
uint riskMultiplierPerSport;
DynamicLiquidityData dynamicLiquidityData;
}
enum RiskStatus {
NoRisk,
OutOfLiquidity,
InvalidCombination
}
function minBuyInAmount() external view returns (uint);
function maxTicketSize() external view returns (uint);
function maxSupportedAmount() external view returns (uint);
function maxSupportedOdds() external view returns (uint);
function maxAllowedSystemCombinations() external view returns (uint);
function expiryDuration() external view returns (uint);
function liveTradingPerSportAndTypeEnabled(uint _sportId, uint _typeId) external view returns (bool _enabled);
function calculateCapToBeUsed(
bytes32 _gameId,
uint16 _sportId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _maturity,
bool _isLive
) external view returns (uint cap);
function calculateTotalRiskOnGame(
bytes32 _gameId,
uint16 _sportId,
uint _maturity
) external view returns (uint totalRisk);
function checkRisks(
ISportsAMMV2.TradeData[] memory _tradeData,
uint _buyInAmount,
bool _isLive,
uint8 _systemBetDenominator
) external view returns (ISportsAMMV2RiskManager.RiskStatus riskStatus, bool[] memory isMarketOutOfLiquidity);
function checkLimits(
uint _buyInAmount,
uint _totalQuote,
uint _payout,
uint _expectedPayout,
uint _additionalSlippage,
uint _ticketSize
) external view;
function spentOnGame(bytes32 _gameId) external view returns (uint);
function riskPerMarketTypeAndPosition(
bytes32 _gameId,
uint _typeId,
uint _playerId,
uint _position
) external view returns (int);
function checkAndUpdateRisks(
ISportsAMMV2.TradeData[] memory _tradeData,
uint _buyInAmount,
uint _payout,
bool _isLive,
uint8 _systemBetDenominator,
bool _isSGP
) external;
function verifyMerkleTree(ISportsAMMV2.TradeData memory _marketTradeData, bytes32 _rootPerGame) external pure;
function batchVerifyMerkleTree(
ISportsAMMV2.TradeData[] memory _marketTradeData,
bytes32[] memory _rootPerGame
) external pure;
function isSportIdFuture(uint16 _sportsId) external view returns (bool);
function sgpOnSportIdEnabled(uint16 _sportsId) external view returns (bool);
function getMaxSystemBetPayout(
ISportsAMMV2.TradeData[] memory _tradeData,
uint8 _systemBetDenominator,
uint _buyInAmount,
uint _addedPayoutPercentage
) external view returns (uint systemBetPayout, uint systemBetQuote);
function generateCombinations(uint8 n, uint8 k) external pure returns (uint8[][] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IProxyBetting.sol";
interface IStakingThalesBettingProxy is IProxyBetting {
function preConfirmLiveTrade(bytes32 requestId, uint _buyInAmount) external;
function confirmLiveTrade(bytes32 requestId, address _createdTicket, uint _buyInAmount) external;
function preConfirmSGPTrade(bytes32 requestId, uint _buyInAmount) external;
function confirmSGPTrade(bytes32 requestId, address _createdTicket, uint _buyInAmount) external;
}{
"optimizer": {
"enabled": true,
"runs": 100
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_link","type":"address"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"address","name":"_sportsAMM","type":"address"},{"internalType":"bytes32","name":"_jobSpecId","type":"bytes32"},{"internalType":"bytes32","name":"_parlayJobSpecId","type":"bytes32"},{"internalType":"uint256","name":"_paymentAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"StringsInsufficientHexLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ChainlinkRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_link","type":"address"},{"indexed":false,"internalType":"address","name":"_oracle","type":"address"},{"indexed":false,"internalType":"address","name":"_sportsAMM","type":"address"},{"indexed":false,"internalType":"bytes32","name":"_jobSpecId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"_parlayJobSpecId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_paymentAmount","type":"uint256"}],"name":"ContextReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"_allow","type":"bool"},{"indexed":false,"internalType":"uint16","name":"legsCount","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"buyInAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"approvedQuote","type":"uint256"}],"name":"LiveParlayTradeFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestCounter","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"legsCount","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"buyInAmount","type":"uint256"}],"name":"LiveParlayTradeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"_allow","type":"bool"},{"indexed":false,"internalType":"bytes32","name":"_gameId","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"_sportId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"_typeId","type":"uint16"},{"indexed":false,"internalType":"int24","name":"_line","type":"int24"},{"indexed":false,"internalType":"uint8","name":"_position","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_expectedQuote","type":"uint256"},{"indexed":false,"internalType":"address","name":"_collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LiveTradeFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestCounter","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"_gameId","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"_sportId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"_typeId","type":"uint16"},{"indexed":false,"internalType":"int24","name":"_line","type":"int24"},{"indexed":false,"internalType":"uint8","name":"_position","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_expectedQuote","type":"uint256"},{"indexed":false,"internalType":"address","name":"_collateral","type":"address"}],"name":"LiveTradeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_freeBetsHolder","type":"address"}],"name":"SetFreeBetsHolder","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_maxAllowedExecutionDelay","type":"uint256"}],"name":"SetMaxAllowedExecutionDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"counterToRequestId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freeBetsHolder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_requestId","type":"bytes32"},{"internalType":"bool","name":"_allow","type":"bool"},{"internalType":"uint256","name":"_approvedQuote","type":"uint256"}],"name":"fulfillLiveTrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_requestId","type":"bytes32"},{"internalType":"bool","name":"_allow","type":"bool"},{"internalType":"uint256","name":"_approvedQuote","type":"uint256"},{"internalType":"uint256[]","name":"_approvedLegOdds","type":"uint256[]"}],"name":"fulfillLiveTradeParlay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"getParlayTradeData","outputs":[{"components":[{"components":[{"internalType":"string","name":"gameId","type":"string"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"uint256","name":"expectedLegOdd","type":"uint256"},{"internalType":"uint24","name":"playerId","type":"uint24"}],"internalType":"struct ILiveTradingProcessor.LiveParlayLeg[]","name":"legs","type":"tuple[]"},{"internalType":"uint256","name":"buyInAmount","type":"uint256"},{"internalType":"uint256","name":"expectedPayout","type":"uint256"},{"internalType":"uint256","name":"additionalSlippage","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"internalType":"struct ILiveTradingProcessor.LiveParlayTradeData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"getTradeData","outputs":[{"components":[{"internalType":"string","name":"_gameId","type":"string"},{"internalType":"uint16","name":"_sportId","type":"uint16"},{"internalType":"uint16","name":"_typeId","type":"uint16"},{"internalType":"int24","name":"_line","type":"int24"},{"internalType":"uint8","name":"_position","type":"uint8"},{"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"internalType":"uint256","name":"_expectedQuote","type":"uint256"},{"internalType":"uint256","name":"_additionalSlippage","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint24","name":"_playerId","type":"uint24"}],"internalType":"struct ILiveTradingProcessor.LiveTradeData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"jobSpecId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAllowedExecutionDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"parlayJobSpecId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdFulfilled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdIsParlay","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToFulfillAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToParlayTradeData","outputs":[{"internalType":"uint256","name":"buyInAmount","type":"uint256"},{"internalType":"uint256","name":"expectedPayout","type":"uint256"},{"internalType":"uint256","name":"additionalSlippage","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToRequester","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToTicketId","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToTradeData","outputs":[{"internalType":"string","name":"_gameId","type":"string"},{"internalType":"uint16","name":"_sportId","type":"uint16"},{"internalType":"uint16","name":"_typeId","type":"uint16"},{"internalType":"int24","name":"_line","type":"int24"},{"internalType":"uint8","name":"_position","type":"uint8"},{"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"internalType":"uint256","name":"_expectedQuote","type":"uint256"},{"internalType":"uint256","name":"_additionalSlippage","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint24","name":"_playerId","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"string","name":"gameId","type":"string"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"uint256","name":"expectedLegOdd","type":"uint256"},{"internalType":"uint24","name":"playerId","type":"uint24"}],"internalType":"struct ILiveTradingProcessor.LiveParlayLeg[]","name":"legs","type":"tuple[]"},{"internalType":"uint256","name":"buyInAmount","type":"uint256"},{"internalType":"uint256","name":"expectedPayout","type":"uint256"},{"internalType":"uint256","name":"additionalSlippage","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"internalType":"struct ILiveTradingProcessor.LiveParlayTradeData","name":"_parlay","type":"tuple"}],"name":"requestLiveParlayTrade","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"_gameId","type":"string"},{"internalType":"uint16","name":"_sportId","type":"uint16"},{"internalType":"uint16","name":"_typeId","type":"uint16"},{"internalType":"int24","name":"_line","type":"int24"},{"internalType":"uint8","name":"_position","type":"uint8"},{"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"internalType":"uint256","name":"_expectedQuote","type":"uint256"},{"internalType":"uint256","name":"_additionalSlippage","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint24","name":"_playerId","type":"uint24"}],"internalType":"struct ILiveTradingProcessor.LiveTradeData","name":"_liveTradeData","type":"tuple"}],"name":"requestLiveTrade","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_link","type":"address"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"address","name":"_sportsAMM","type":"address"},{"internalType":"bytes32","name":"_jobSpecId","type":"bytes32"},{"internalType":"bytes32","name":"_parlayJobSpecId","type":"bytes32"},{"internalType":"uint256","name":"_paymentAmount","type":"uint256"}],"name":"setConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_freeBetsHolder","type":"address"}],"name":"setFreeBetsHolder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAllowedExecutionDelay","type":"uint256"}],"name":"setMaxAllowedExecutionDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_setPausing","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sportsAMM","outputs":[{"internalType":"contract ISportsAMMV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"timestampPerRequest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040526001600455603c600c553480156200001b57600080fd5b5060405162004f9338038062004f938339810160408190526200003e916200015c565b33806200006557604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200007081620000ed565b506006805460ff60a01b19169055600280546001600160a01b0319166001600160a01b038816179055600380546001600160a01b0319166001600160a01b038716179055600780546001600160a01b0319166001600160a01b039590951694909417909355600991909155600a91909155600b5550620001c29050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200015757600080fd5b919050565b60008060008060008060c087890312156200017657600080fd5b62000181876200013f565b955062000191602088016200013f565b9450620001a1604088016200013f565b9350606087015192506080870151915060a087015190509295509295509295565b614dc180620001d26000396000f3fe608060405234801561001057600080fd5b50600436106101a55760003560e01c806394f2f593116100ef578063c65a88e811610092578063c65a88e814610417578063c6a85f6e1461043a578063c99252881461045d578063cbbe361d14610470578063ce18a83714610490578063e27a9abc146104a3578063f1c9144f146104cd578063f2fde38b146104e057600080fd5b806394f2f5931461031a578063973a814e146103235780639a9950471461032c578063a6f75b181461033f578063b08a979d14610352578063b099d572146103d2578063bfc69e83146103e5578063c35905c61461040e57600080fd5b8063679c4de111610157578063679c4de114610273578063715018a61461028657806371b00be81461028e5780637ff39d2914610297578063805661b0146102cd57806383223eb5146102e05780638da5cb5b146102e957806390421b7c146102fa57600080fd5b806301432bf2146101aa57806316c38b3c146101e257806319d85ec0146101f75780632afdebb11461020a5780635bcbd6a81461022a5780635c975abb1461024b578063653318f814610253575b600080fd5b6101cd6101b83660046139f9565b60126020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6101f56101f0366004613a20565b6104f3565b005b6101f5610205366004613a52565b610513565b61021d6102183660046139f9565b6105de565b6040516101d99190613b14565b61023d610238366004613bdf565b610779565b6040519081526020016101d9565b6101cd61121e565b61023d6102613660046139f9565b60136020526000908152604090205481565b6101f5610281366004613c19565b61122e565b6101f56112bc565b61023d60095481565b6102c06102a53660046139f9565b6010602052600090815260409020546001600160a01b031681565b6040516101d99190613c52565b6101f56102db366004613c66565b6112d0565b61023d600c5481565b6006546001600160a01b03166102c0565b61023d6103083660046139f9565b60156020526000908152604090205481565b61023d600b5481565b61023d60145481565b6101f561033a3660046139f9565b61132e565b6101f561034d366004613c83565b61136b565b61039e6103603660046139f9565b600e60205260009081526040902060018101546002820154600383015460048401546005909401549293919290916001600160a01b03908116911685565b604080519586526020860194909452928401919091526001600160a01b03908116606084015216608082015260a0016101d9565b61023d6103e0366004613d1b565b6118c1565b6102c06103f33660046139f9565b6016602052600090815260409020546001600160a01b031681565b61023d600a5481565b6101cd6104253660046139f9565b600f6020526000908152604090205460ff1681565b6101cd6104483660046139f9565b60116020526000908152604090205460ff1681565b6007546102c0906001600160a01b031681565b61048361047e3660046139f9565b612005565b6040516101d99190613d56565b6008546102c0906001600160a01b031681565b6104b66104b13660046139f9565b6121f6565b6040516101d99b9a99989796959493929190613e65565b6101f56104db366004613ee3565b6122f6565b6101f56104ee366004613c66565b612706565b6104fb612741565b8061050b5761050861276e565b50565b6105086127bd565b61051b612741565b600280546001600160a01b0319166001600160a01b038816179055600380546001600160a01b0319166001600160a01b038716179055600780546001600160a01b0319166001600160a01b038681169182179092556009859055600b849055600a8390556040805189841681529288166020840152820152606081018490526080810183905260a081018290527f605eb9e491eeddbc501664783694a220b259a9a1f6da73ad50e982bdee1754969060c0015b60405180910390a1505050505050565b6040805161016081018252606080825260006020830181905292820183905281018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526000828152600d6020526040908190208151610160810190925280548290829061066090613f1b565b80601f016020809104026020016040519081016040528092919081815260200182805461068c90613f1b565b80156106d95780601f106106ae576101008083540402835291602001916106d9565b820191906000526020600020905b8154815290600101906020018083116106bc57829003601f168201915b5050509183525050600182015461ffff8082166020840152620100008204166040830152600160201b8104600290810b6060840152600160381b90910460ff16608083015282015460a0820152600382015460c0820152600482015460e082015260058201546001600160a01b03908116610100830152600690920154918216610120820152600160a01b90910462ffffff166101409091015292915050565b6000610783612800565b600061078f8380613f4f565b915050600181116107bb5760405162461bcd60e51b81526004016107b290613f9f565b60405180910390fd5b60005b8181101561096157366107d18580613f4f565b838181106107e1576107e1613fd1565b90506020028101906107f39190613fe7565b9050600760009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa158015610848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086c9190614007565b6001600160a01b031663ce440b9361088a6040840160208501614034565b61089a6060850160408601614034565b6040516001600160e01b031960e085901b16815261ffff928316600482015291166024820152604401602060405180830381865afa1580156108e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109049190614051565b6109505760405162461bcd60e51b815260206004820152601f60248201527f4c6976652074726164696e67206e6f7420656e61626c6564206f6e206c65670060448201526064016107b2565b5061095a81614084565b90506107be565b50600760009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d99190614007565b6001600160a01b031663e88698bf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3a919061409d565b83604001351015610a5d5760405162461bcd60e51b81526004016107b2906140b6565b6000610a73600b543063a6f75b1860e01b612826565b9050610ac4604051806040016040528060048152602001636d6f646560e01b815250604051806040016040528060068152602001657061726c617960d01b8152508361284d9092919063ffffffff16565b6000826001600160401b03811115610ade57610ade6140df565b604051908082528060200260200182016040528015610b1157816020015b6060815260200190600190039081610afc5790505b5090506000836001600160401b03811115610b2e57610b2e6140df565b604051908082528060200260200182016040528015610b6157816020015b6060815260200190600190039081610b4c5790505b5090506000846001600160401b03811115610b7e57610b7e6140df565b604051908082528060200260200182016040528015610bb157816020015b6060815260200190600190039081610b9c5790505b5090506000856001600160401b03811115610bce57610bce6140df565b604051908082528060200260200182016040528015610c0157816020015b6060815260200190600190039081610bec5790505b5090506000866001600160401b03811115610c1e57610c1e6140df565b604051908082528060200260200182016040528015610c5157816020015b6060815260200190600190039081610c3c5790505b5090506000876001600160401b03811115610c6e57610c6e6140df565b604051908082528060200260200182016040528015610ca157816020015b6060815260200190600190039081610c8c5790505b5090506000886001600160401b03811115610cbe57610cbe6140df565b604051908082528060200260200182016040528015610cf157816020015b6060815260200190600190039081610cdc5790505b50905060005b89811015610edd5736610d0a8d80613f4f565b83818110610d1a57610d1a613fd1565b9050602002810190610d2c9190613fe7565b9050610d3881806140f5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250508b518c92508591508110610d8057610d80613fd1565b6020026020010181905250610daa816020016020810190610da19190614034565b61ffff16612870565b888381518110610dbc57610dbc613fd1565b6020908102919091010152610dda610da16060830160408401614034565b878381518110610dec57610dec613fd1565b6020908102919091010152610e12610e0a608083016060840161414a565b60020b612902565b868381518110610e2457610e24613fd1565b6020908102919091010152610e4a610e4260a0830160808401614176565b60ff16612870565b858381518110610e5c57610e5c613fd1565b6020026020010181905250610e748160a00135612870565b848381518110610e8657610e86613fd1565b6020908102919091010152610eae610ea460e0830160c084016141a4565b62ffffff16612870565b838381518110610ec057610ec0613fd1565b60200260200101819052505080610ed690614084565b9050610cf7565b5060408051808201909152600781526667616d6549647360c81b6020820152610f0890899089612952565b60408051808201909152600881526773706f727449647360c01b6020820152610f3390899088612952565b6040805180820190915260078152667479706549647360c81b6020820152610f5d90899087612952565b6040805180820190915260058152646c696e657360d81b6020820152610f8590899086612952565b604080518082019091526009815268706f736974696f6e7360b81b6020820152610fb190899085612952565b60408051808201909152600f81526e65787065637465644c65674f64647360881b6020820152610fe390899084612952565b604080518082019091526009815268706c6179657249647360b81b602082015261100f90899083612952565b61104b6040518060400160405280600b81526020016a189d5e525b905b5bdd5b9d60aa1b8152508c602001358a6129ca9092919063ffffffff16565b604080518082018252600d81526c657870656374656451756f746560981b602082015261107d918a91908e01356129ca565b6040805180820190915260128152716164646974696f6e616c536c69707061676560701b60208201526110b690899060608e01356129ca565b6110ec604051806040016040528060098152602001683932b8bab2b9ba32b960b91b8152506110e4336129e8565b8a919061284d565b61112d6040518060400160405280600a81526020016918dbdb1b185d195c985b60b21b8152506110e48d60a00160208101906111289190613c66565b6129e8565b61113988600a546129fe565b6000818152601360209081526040808320429055600e9091529020909a508b906111638282614623565b505060008a815260106020908152604080832080546001600160a01b03191633908117909155600f8352818420805460ff1916600117905560148054855260158452938290208e9055925481519384528383015282018c905261ffff8b1660608301528c013560808201527f49f9ae6cc4633cb9c99638c964ae59e7f2eaea5e53a2beb1e6f76f7bf8f4370b9060a00160405180910390a16014805490600061120b83614084565b9190505550505050505050505050919050565b600654600160a01b900460ff1690565b611236612741565b6112b881836001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016112669190613c52565b602060405180830381865afa158015611283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a7919061409d565b6001600160a01b0385169190612a18565b5050565b6112c4612741565b6112ce6000612a6a565b565b6112d8612741565b600880546001600160a01b0319166001600160a01b0383161790556040517fc238ff72ce9e31f22c0ef8bf1c701fcc6afd3ed4edc2224a63f16346b68420fb90611323908390613c52565b60405180910390a150565b611336612741565b600c8190556040518181527fa1d20d22955d911c8b338eeec58c0fa61197b85b255251efe74df475baa5c73890602001611323565b611373612800565b60008581526005602052604090205485906001600160a01b031633146113ab5760405162461bcd60e51b81526004016107b2906146c2565b60008181526005602052604080822080546001600160a01b03191690555182917f7cc135e0cebb02c3480ae5d74d377283180a2601f8f644edf7987b009316c63a91a260008681526012602052604090205460ff161561141d5760405162461bcd60e51b81526004016107b29061470a565b600c54600087815260136020526040902054429161143a91614741565b116114575760405162461bcd60e51b81526004016107b290614754565b6000868152600f602052604090205460ff166114ad5760405162461bcd60e51b815260206004820152601560248201527452657175657374206973206e6f74207061726c617960581b60448201526064016107b2565b6000868152600e602090815260408083208151815460e09481028201850190935260c08101838152909391928492849190879085015b8282101561160457838290600052602060002090600402016040518060e001604052908160008201805461151690613f1b565b80601f016020809104026020016040519081016040528092919081815260200182805461154290613f1b565b801561158f5780601f106115645761010080835404028352916020019161158f565b820191906000526020600020905b81548152906001019060200180831161157257829003601f168201915b505050918352505060018281015461ffff8082166020808601919091526201000083049091166040850152600160201b8204600290810b6060860152600160381b90920460ff1660808501529084015460a084015260039093015462ffffff1660c090920191909152918352920191016114e3565b5050509082525060018281015460208084019190915260028401546040808501919091526003850154606085015260048501546001600160a01b039081166080860152600590950154851660a09094019390935260008c815260109091529190912054835151939450909116919081116116905760405162461bcd60e51b81526004016107b290613f9f565b8481146116d55760405162461bcd60e51b8152602060048201526013602482015272084c2c840d8cace40dec8c8e640d8cadccee8d606b1b60448201526064016107b2565b60608301516116ec90670de0b6b3a7640000614741565b604084015161170389670de0b6b3a76400006141c1565b61170d9190614795565b111561172b5760405162461bcd60e51b81526004016107b2906147a9565b871561181d576000816001600160401b0381111561174b5761174b6140df565b60405190808252806020026020018201604052801561178457816020015b61177161394c565b8152602001906001900390816117695790505b50905060005b828110156117ff576117d1856000015182815181106117ab576117ab613fd1565b60200260200101518989848181106117c5576117c5613fd1565b90506020020135612abc565b8282815181106117e3576117e3613fd1565b6020026020010181905250806117f890614084565b905061178a565b5061181b8a848387602001518c89608001518a60a00151612bdc565b505b600089815260116020908152604080832080548c151560ff199182168117909255601284529382902080549094166001179093558582015181516001600160a01b03871681529283018d90529082019290925261ffff83166060820152608081019190915260a081018890527f7ae269cd4fee93b8f25452870350fd171bb1368d74b259d94ccf7a971b044ed79060c00160405180910390a1505050505050505050565b60006118cb612800565b600760009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa15801561191e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119429190614007565b6001600160a01b031663ce440b936119606040850160208601614034565b6119706060860160408701614034565b6040516001600160e01b031960e085901b16815261ffff928316600482015291166024820152604401602060405180830381865afa1580156119b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119da9190614051565b611a325760405162461bcd60e51b8152602060048201526024808201527f4c6976652074726164696e67206e6f7420656e61626c6564206f6e205f73706f6044820152631c9d125960e21b60648201526084016107b2565b600760009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa99190614007565b6001600160a01b031663e88698bf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a919061409d565b8260c001351015611b2d5760405162461bcd60e51b81526004016107b2906140b6565b6000611b436009543063f1c9144f60e01b612826565b9050611b94604051806040016040528060048152602001636d6f646560e01b8152506040518060400160405280600681526020016573696e676c6560d01b8152508361284d9092919063ffffffff16565b60408051808201909152600681526519d85b59525960d21b6020820152611bfd90611bbf85806140f5565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525086949392505061284d9050565b611c3f604051806040016040528060078152602001661cdc1bdc9d125960ca1b815250846020016020810190611c339190614034565b83919061ffff166129ca565b60408051808201825260068152651d1e5c19525960d21b6020820152611c6f91611c339060608701908701614034565b6040805180820190915260048152636c696e6560e01b6020820152611ca990611c9e608086016060870161414a565b83919060020b612d17565b6040805180820190915260088152673837b9b4ba34b7b760c11b6020820152611ce790611cdc60a0860160808701614176565b83919060ff166129ca565b60408051808201909152600b81526a189d5e525b905b5bdd5b9d60aa1b6020820152611d1990829060a08601356129ca565b60408051808201909152600d81526c657870656374656451756f746560981b6020820152611d4d90829060c08601356129ca565b6040805180820190915260128152716164646974696f6e616c536c69707061676560701b6020820152611d8690829060e08601356129ca565b6040805180820190915260088152671c1b185e595c925960c21b6020820152611dc890611dbb610160860161014087016141a4565b83919062ffffff166129ca565b611dfe604051806040016040528060098152602001683932b8bab2b9ba32b960b91b815250611df6336129e8565b83919061284d565b60408051808201909152600a81526918dbdb1b185d195c985b60b21b6020820152611e3890611df661112861014087016101208801613c66565b611e4481600a546129fe565b6000818152601360209081526040808320429055600d90915290209092508390611e6e82826147d4565b5050600082815260106020908152604080832080546001600160a01b03191633908117909155600f8352818420805460ff1916905560148054855260159093529220849055547fdc457bcbffcdb3995df4b3bb7a325fe68d19b75af17c94b8d1d277a85691e20f919084611f1f611ee588806140f5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d3592505050565b611f2f6040890160208a01614034565b611f3f60608a0160408b01614034565b611f4f60808b0160608c0161414a565b611f5f60a08c0160808d01614176565b8b60a001358c60c001358d610120016020810190611f7d9190613c66565b604080516001600160a01b039c8d168152602081019b909b528a0198909852606089019690965261ffff94851660808901529390921660a087015260020b60c086015260ff1660e0850152610100840152610120830152919091166101408201526101600160405180910390a160148054906000611ffa83614084565b919050555050919050565b6120506040518060c001604052806060815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b031681525090565b6000828152600e602090815260408083208151815460e09481028201850190935260c08101838152909491938593919285929185015b828210156121a757838290600052602060002090600402016040518060e00160405290816000820180546120b990613f1b565b80601f01602080910402602001604051908101604052809291908181526020018280546120e590613f1b565b80156121325780601f1061210757610100808354040283529160200191612132565b820191906000526020600020905b81548152906001019060200180831161211557829003601f168201915b505050918352505060018281015461ffff8082166020808601919091526201000083049091166040850152600160201b8204600290810b6060860152600160381b90920460ff1660808501529084015460a084015260039093015462ffffff1660c09092019190915291835292019101612086565b5050509082525060018201546020820152600282015460408201526003820154606082015260048201546001600160a01b03908116608083015260059092015490911660a09091015292915050565b600d6020526000908152604090208054819061221190613f1b565b80601f016020809104026020016040519081016040528092919081815260200182805461223d90613f1b565b801561228a5780601f1061225f5761010080835404028352916020019161228a565b820191906000526020600020905b81548152906001019060200180831161226d57829003601f168201915b505050506001830154600280850154600386015460048701546005880154600690980154969761ffff808716986201000088049091169750600160201b870490950b95600160381b900460ff16946001600160a01b0391821691811690600160a01b900462ffffff168b565b6122fe612800565b60008381526005602052604090205483906001600160a01b031633146123365760405162461bcd60e51b81526004016107b2906146c2565b60008181526005602052604080822080546001600160a01b03191690555182917f7cc135e0cebb02c3480ae5d74d377283180a2601f8f644edf7987b009316c63a91a260008481526012602052604090205460ff16156123a85760405162461bcd60e51b81526004016107b29061470a565b600c5460008581526013602052604090205442916123c591614741565b116123e25760405162461bcd60e51b81526004016107b290614754565b6000848152600f602052604090205460ff16156124355760405162461bcd60e51b815260206004820152601160248201527052657175657374206973207061726c617960781b60448201526064016107b2565b6000848152600d60205260408082208151610160810190925280548290829061245d90613f1b565b80601f016020809104026020016040519081016040528092919081815260200182805461248990613f1b565b80156124d65780601f106124ab576101008083540402835291602001916124d6565b820191906000526020600020905b8154815290600101906020018083116124b957829003601f168201915b5050509183525050600182015461ffff808216602080850191909152620100008304909116604080850191909152600160201b8304600290810b6060860152600160381b90930460ff1660808501529184015460a0840152600384015460c0840152600484015460e08085019190915260058501546001600160a01b03908116610100860152600690950154808616610120860152600160a01b900462ffffff166101409094019390935260008a8152601090915220549083015192935016906125a890670de0b6b3a7640000614741565b60c08301516125bf86670de0b6b3a76400006141c1565b6125c99190614795565b11156125e75760405162461bcd60e51b81526004016107b2906147a9565b841561266857604080516001808252818301909252600091816020015b61260c61394c565b81526020019060019003908161260457905050905061262b8386612d54565b8160008151811061263e5761263e613fd1565b60200260200101819052506126668783838660a0015189886101000151896101200151612bdc565b505b6000868152601160209081526040808320805489151560ff199182161790915560129092529091208054909116600117905581517fe16fea440372e1dff8f7e8cb79dcc6e6af20f2af3a278835a2049243b25d03ca908290889088906126cd90612d35565b86602001518760400151886060015189608001518a60a001518d8c6101200151426040516105ce9c9b9a999897969594939291906148a6565b61270e612741565b6001600160a01b038116612738576000604051631e4fbdf760e01b81526004016107b29190613c52565b61050881612a6a565b6006546001600160a01b031633146112ce573360405163118cdaa760e01b81526004016107b29190613c52565b612776612e75565b6006805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516127b39190613c52565b60405180910390a1565b6127c5612800565b6006805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586127a63390565b61280861121e565b156112ce5760405163d93c066560e01b815260040160405180910390fd5b61282e6139aa565b6128366139aa565b61284281868686612e9a565b9150505b9392505050565b608083015161285c9083612ee0565b608083015161286b9082612ee0565b505050565b6060600061287d83612ef7565b60010190506000816001600160401b0381111561289c5761289c6140df565b6040519080825280601f01601f1916602001820160405280156128c6576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846128d057509392505050565b60606000821261291b5761291582612870565b92915050565b61292c61292783614928565b612870565b60405160200161293c9190614944565b6040516020818303038152906040529050919050565b60808301516129619083612ee0565b61296e8360800151612fcf565b60005b81518110156129bc576129aa82828151811061298f5761298f613fd1565b60200260200101518560800151612ee090919063ffffffff16565b806129b481614084565b915050612971565b5061286b8360800151612fda565b60808301516129d99083612ee0565b608083015161286b9082612fe5565b60606129156001600160a01b038316601461300a565b600354600090612846906001600160a01b03168484613181565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261286b908490613214565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612ac461394c565b6040805160e1808252611c4082019092526060916000919060208201611c20803683370190505090508381866080015160ff1681518110612b0757612b07613fd1565b60209081029190910101526040805160e1808252611c408201909252600091816020015b6060815260200190600190039081612b2b579050509050604051806101600160405280612b5b8860000151612d35565b8152602001876020015161ffff168152602001876040015161ffff16815260200142603c612b899190614741565b8152602001600060ff168152602001876060015160020b81526020018760c0015162ffffff168152602001838152602001848152602001876080015160ff16815260200182815250935050505092915050565b600754604051637240d1a160e11b81526000916001600160a01b03169063e481a34290612c17908990899089908d908a908a90600401614a39565b6020604051808303816000875af1158015612c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5a9190614007565b600089815260166020526040902080546001600160a01b0319166001600160a01b038381169190911790915560085491925090811690881603612d0d5760085460405163a12d5b0760e01b8152600481018a90526001600160a01b0383811660248301526044820188905284811660648301529091169063a12d5b0790608401600060405180830381600087803b158015612cf457600080fd5b505af1158015612d08573d6000803e3d6000fd5b505050505b5050505050505050565b6080830151612d269083612ee0565b608083015161286b908261326e565b805160009082908203612d4b5750600092915050565b50506020015190565b612d5c61394c565b6040805160e1808252611c4082019092526060916000919060208201611c20803683370190505090508381866080015160ff1681518110612d9f57612d9f613fd1565b60209081029190910101526040805160e1808252611c408201909252600091816020015b6060815260200190600190039081612dc3579050509050604051806101600160405280612df38860000151612d35565b8152602001876020015161ffff168152602001876040015161ffff16815260200142603c612e219190614741565b8152602001600060ff168152602001876060015160020b815260200187610140015162ffffff168152602001838152602001848152602001876080015160ff16815260200182815250935050505092915050565b612e7d61121e565b6112ce57604051638dfc202b60e01b815260040160405180910390fd5b612ea26139aa565b612eb285608001516101006132cd565b50508284526001600160a01b03821660208501526001600160e01b031981166040850152835b949350505050565b612eed8260038351613325565b61286b8282613432565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612f365772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612f62576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612f8057662386f26fc10000830492506010015b6305f5e1008310612f98576305f5e100830492506008015b6127108310612fac57612710830492506004015b60648310612fbe576064830492506002015b600a83106129155760010192915050565b61050881600461344c565b61050881600761344c565b6001600160401b03811115612ffe576112b88282613461565b6112b882600083613325565b606082600061301a8460026141c1565b613025906002614741565b6001600160401b0381111561303c5761303c6140df565b6040519080825280601f01601f191660200182016040528015613066576020820181803683370190505b509050600360fc1b8160008151811061308157613081613fd1565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106130b0576130b0613fd1565b60200101906001600160f81b031916908160001a90535060006130d48560026141c1565b6130df906001614741565b90505b6001811115613157576f181899199a1a9b1b9c1cb0b131b232b360811b83600f166010811061311357613113613fd1565b1a60f81b82828151811061312957613129613fd1565b60200101906001600160f81b031916908160001a90535060049290921c9161315081614b8c565b90506130e2565b508115612ed85760405163e22e27eb60e01b815260048101869052602481018590526044016107b2565b600454600090613192816001614741565b600455835160408086015160808701515191516000936320214ca360e11b936131ca9386938493923092918a91600191602401614ba3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905061320a86838684613498565b9695505050505050565b60006132296001600160a01b038416836135f6565b9050805160001415801561324e57508080602001905181019061324c9190614051565b155b1561286b5782604051635274afe760e01b81526004016107b29190613c52565b67ffffffffffffffff19811215613289576112b88282613604565b6001600160401b038113156132a2576112b88282613461565b600081126132b6576112b882600083613325565b6112b88260016132c884600019614c0b565b613325565b6132d56139df565b6132e0602083614c32565b15613308576132f0602083614c32565b6132fb906020614c46565b6133059083614741565b91505b506020828101829052604080518085526000815290920101905290565b6017816001600160401b03161161334f576133498360e0600585901b168317613632565b50505050565b60ff816001600160401b03161161338b57613375836018611fe0600586901b1617613632565b50613349836001600160401b038316600161364a565b61ffff816001600160401b0316116133c8576133b2836019611fe0600586901b1617613632565b50613349836001600160401b038316600261364a565b63ffffffff816001600160401b031611613407576133f183601a611fe0600586901b1617613632565b50613349836001600160401b038316600461364a565b61341c83601b611fe0600586901b1617613632565b50613349836001600160401b038316600861364a565b61343a6139df565b61284683846000015151848551613663565b61286b82601f611fe0600585901b1617613632565b61346c8260c2613632565b506112b8828260405160200161348491815260200190565b604051602081830303815290604052613740565b6040516bffffffffffffffffffffffff193060601b1660208201526034810184905260009060540160408051808303601f1901815282825280516020918201206000818152600590925291812080546001600160a01b0319166001600160a01b038a1617905590925082917fb5e6e01e79f91267dc17b4e6314d5d4d03593d2ceee0fbb452b750bd70ea5af99190a2600254604051630200057560e51b81526001600160a01b0390911690634000aea09061355b90889087908790600401614c59565b6020604051808303816000875af115801561357a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359e9190614051565b612ed85760405162461bcd60e51b815260206004820152602360248201527f756e61626c6520746f207472616e73666572416e6443616c6c20746f206f7261604482015262636c6560e81b60648201526084016107b2565b60606128468383600061374d565b61360f8260c3613632565b506112b88261362083600019614c0b565b60405160200161348491815260200190565b61363a6139df565b61284683846000015151846137e0565b6136526139df565b612ed884856000015151858561382e565b61366b6139df565b825182111561367957600080fd5b60208501516136888386614741565b11156136bb576136bb856136ab876020015187866136a69190614741565b6138a2565b6136b69060026141c1565b6138b9565b6000808651805187602083010193508088870111156136da5787860182525b505050602084015b6020841061371a57805182526136f9602083614741565b9150613706602082614741565b9050613713602085614c46565b93506136e2565b51815160001960208690036101000a019081169019919091161790525083949350505050565b612eed8260028351613325565b606081471015613772573060405163cd78605960e01b81526004016107b29190613c52565b600080856001600160a01b0316848660405161378e9190614c89565b60006040518083038185875af1925050503d80600081146137cb576040519150601f19603f3d011682016040523d82523d6000602084013e6137d0565b606091505b509150915061320a8683836138d0565b6137e86139df565b836020015183106138085761380884856020015160026136b691906141c1565b8351805160208583010184815350808503613824576001810182525b5093949350505050565b6138366139df565b60208501516138458584614741565b111561385957613859856136ab8685614741565b6000600161386984610100614d7f565b6138739190614c46565b90508551838682010185831982511617815250805184870111156138975783860181525b509495945050505050565b6000818311156138b3575081612915565b50919050565b81516138c583836132cd565b506133498382613432565b6060826138e5576138e082613923565b612846565b81511580156138fc57506001600160a01b0384163b155b1561391c5783604051639996b31560e01b81526004016107b29190613c52565b5080612846565b8051156139335780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201819052610100820181905261012082019290925261014081019190915290565b6040805160a0810182526000808252602082018190529181018290526060810191909152608081016139da6139df565b905290565b604051806040016040528060608152602001600081525090565b600060208284031215613a0b57600080fd5b5035919050565b801515811461050857600080fd5b600060208284031215613a3257600080fd5b813561284681613a12565b6001600160a01b038116811461050857600080fd5b60008060008060008060c08789031215613a6b57600080fd5b8635613a7681613a3d565b95506020870135613a8681613a3d565b94506040870135613a9681613a3d565b959894975094956060810135955060808101359460a0909101359350915050565b60005b83811015613ad2578181015183820152602001613aba565b50506000910152565b60008151808452613af3816020860160208601613ab7565b601f01601f19169290920160200192915050565b6001600160a01b03169052565b6020815260008251610160806020850152613b33610180850183613adb565b91506020850151613b4a604086018261ffff169052565b50604085015161ffff81166060860152506060850151613b6f608086018260020b9052565b50608085015160ff811660a08601525060a085015160c085015260c085015160e085015260e0850151610100818187015280870151915050610120613bb681870183613b07565b8601519050610140613bca86820183613b07565b9095015162ffffff1693019290925250919050565b600060208284031215613bf157600080fd5b81356001600160401b03811115613c0757600080fd5b820160c0818503121561284657600080fd5b60008060408385031215613c2c57600080fd5b8235613c3781613a3d565b91506020830135613c4781613a3d565b809150509250929050565b6001600160a01b0391909116815260200190565b600060208284031215613c7857600080fd5b813561284681613a3d565b600080600080600060808688031215613c9b57600080fd5b853594506020860135613cad81613a12565b93506040860135925060608601356001600160401b0380821115613cd057600080fd5b818801915088601f830112613ce457600080fd5b813581811115613cf357600080fd5b8960208260051b8501011115613d0857600080fd5b9699959850939650602001949392505050565b600060208284031215613d2d57600080fd5b81356001600160401b03811115613d4357600080fd5b8201610160818503121561284657600080fd5b6000602080835260e0808401855160c0808588015282825180855261010094508489019150848160051b8a01019450868401935060005b81811015613e125789860360ff1901835284518051888852613db189890182613adb565b828b015161ffff9081168a8d0152604080850151909116908a015260608084015160020b908a015260808084015160ff16908a015260a080840151908a01529186015162ffffff169786019790975295509387019391870191600101613d8d565b505050848801516040880152604088015160608801526060880151608088015260808801519450613e4660a0880186613b07565b60a08801519450613e5981880186613b07565b50909695505050505050565b6000610160808352613e798184018f613adb565b61ffff9d8e1660208501529b909c1660408301525060029890980b606089015260ff96909616608088015260a087019490945260c086019290925260e08501526001600160a01b039081166101008501521661012083015262ffffff166101409091015292915050565b600080600060608486031215613ef857600080fd5b833592506020840135613f0a81613a12565b929592945050506040919091013590565b600181811c90821680613f2f57607f821691505b6020821081036138b357634e487b7160e01b600052602260045260246000fd5b6000808335601e19843603018112613f6657600080fd5b8301803591506001600160401b03821115613f8057600080fd5b6020019150600581901b3603821315613f9857600080fd5b9250929050565b6020808252601890820152775061726c6179206d7573742068617665203e2031206c656760401b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000823560de19833603018112613ffd57600080fd5b9190910192915050565b60006020828403121561401957600080fd5b815161284681613a3d565b61ffff8116811461050857600080fd5b60006020828403121561404657600080fd5b813561284681614024565b60006020828403121561406357600080fd5b815161284681613a12565b634e487b7160e01b600052601160045260246000fd5b6000600182016140965761409661406e565b5060010190565b6000602082840312156140af57600080fd5b5051919050565b6020808252600f908201526e45786365656465644d61784f64647360881b604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6000808335601e1984360301811261410c57600080fd5b8301803591506001600160401b0382111561412657600080fd5b602001915036819003821315613f9857600080fd5b8060020b811461050857600080fd5b60006020828403121561415c57600080fd5b81356128468161413b565b60ff8116811461050857600080fd5b60006020828403121561418857600080fd5b813561284681614167565b62ffffff8116811461050857600080fd5b6000602082840312156141b657600080fd5b813561284681614193565b80820281158282048414176129155761291561406e565b5b818110156112b857600081556001016141d9565b600019600383901b1c191660019190911b1790565b601f82111561286b57806000526020600020601f840160051c810160208510156142295750805b61423b601f850160051c8301826141d8565b5050505050565b6001600160401b03831115614259576142596140df565b61426d836142678354613f1b565b83614202565b6000601f84116001811461429b57600085156142895750838201355b61429386826141ed565b84555061423b565b600083815260209020601f19861690835b828110156142cc57868501358255602094850194600190920191016142ac565b50868210156142e95760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000813561291581614024565b600081356129158161413b565b6000813561291581614167565b6000813561291581614193565b61433982836140f5565b6001600160401b03811115614350576143506140df565b6143648161435e8554613f1b565b85614202565b6000601f82116001811461439257600083156143805750838201355b61438a84826141ed565b8655506143ec565b600085815260209020601f19841690835b828110156143c357868501358255602094850194600190920191016143a3565b50848210156143e05760001960f88660031b161c19848701351681555b505060018360011b0185555b5050505060018101614416614403602085016142fb565b825461ffff191661ffff91909116178255565b61443f614425604085016142fb565b825463ffff0000191660109190911b63ffff000016178255565b61447061444e60608501614308565b825460209190911b66ffffff000000001666ffffff0000000019909116178255565b61449d61447f60808501614315565b82805460ff60381b191660389290921b60ff60381b16919091179055565b5060a082013560028201556112b86144b760c08401614322565b6003830162ffffff821662ffffff198254161781555050565b600160401b8311156144e4576144e46140df565b8054838255808410156145b05760026001600160fe1b03828116831461450c5761450c61406e565b808616861461451d5761451d61406e565b5060008381526020812086831b81019084841b015b808210156145ab576145448254613f1b565b801561458e57601f8082116001811461455f5785855561458b565b60008581526020902061457c83850160051c8201600183016141d8565b50600085815260208120818755555b50505b508260018301558284830155826003830155600482019150614532565b505050505b5060008181526020812083915b858110156145ee576145d86145d28487613fe7565b8361432f565b60209290920191600491909101906001016145bd565b505050505050565b6000813561291581613a3d565b80546001600160a01b0319166001600160a01b0392909216919091179055565b8135601e1983360301811261463757600080fd5b820180356001600160401b0381111561464f57600080fd5b6020820191508060051b360382131561466757600080fd5b6146728183856144d0565b50506020820135600182015560408201356002820155606082013560038201556146aa6146a1608084016145f6565b60048301614603565b6112b86146b960a084016145f6565b60058301614603565b60208082526028908201527f536f75726365206d75737420626520746865206f7261636c65206f6620746865604082015267081c995c5d595cdd60c21b606082015260800190565b6020808252601c908201527f5265717565737420494420616c72656164792066756c66696c6c656400000000604082015260600190565b808201808211156129155761291561406e565b60208082526011908201527014995c5d595cdd081d1a5b5959081bdd5d607a1b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b6000826147a4576147a461477f565b500490565b6020808252601190820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604082015260600190565b6147de82836140f5565b6147e9818385614242565b5050600181016147fe614403602085016142fb565b61480d614425604085016142fb565b61481c61444e60608501614308565b61482b61447f60808501614315565b5060a0820135600282015560c0820135600382015560e0820135600482015561485a6146b961010084016145f6565b6006810161487461486e61012085016145f6565b82614603565b61286b6148846101408501614322565b82805462ffffff60a01b191660a09290921b62ffffff60a01b16919091179055565b6001600160a01b038d168152602081018c90528a15156040820152606081018a905261ffff8981166080830152881660a0820152600287900b60c082015260ff861660e0820152610100810185905261012081018490526101808101614910610140830185613b07565b826101608301529d9c50505050505050505050505050565b6000600160ff1b820161493d5761493d61406e565b5060000390565b602d60f81b815260008251614960816001850160208701613ab7565b9190910160010192915050565b600081518084526020808501945080840160005b8381101561389757815187529582019590820190600101614981565b600081518084526020808501808196508360051b810191508286016000805b86811015614a2b578385038a52825180518087529087019087870190845b81811015614a16578351805161ffff1684528a81015160ff168b85015260409081015160020b90840152928901926060909201916001016149da565b50509a87019a955050918501916001016149bc565b509298975050505050505050565b600060c0808301818452808a5180835260e092508286019150828160051b8701016020808e0160005b84811015614b445789840360df190186528151805185528381015161ffff90811685870152604080830151909116908601526060808201519086015260808082015160ff169086015260a08082015160020b908601528881015162ffffff16898601528781015161016089870181905290614adf8288018261496d565b9150506101008083015187830382890152614afa838261496d565b9250505061012080830151614b138289018260ff169052565b50506101408083015192508682038188015250614b30818361499d565b978501979550505090820190600101614a62565b50508196508c81890152505050505050856040830152614b676060830186613b07565b614b746080830185613b07565b614b8160a0830184613b07565b979650505050505050565b600081614b9b57614b9b61406e565b506000190190565b6001600160a01b0389811682526020820189905260408201889052861660608201526001600160e01b03198516608082015260a0810184905260c0810183905261010060e08201819052600090614bfc83820185613adb565b9b9a5050505050505050505050565b8181036000831280158383131683831282161715614c2b57614c2b61406e565b5092915050565b600082614c4157614c4161477f565b500690565b818103818111156129155761291561406e565b60018060a01b0384168152826020820152606060408201526000614c806060830184613adb565b95945050505050565b60008251613ffd818460208701613ab7565b600181815b80851115614cd6578160001904821115614cbc57614cbc61406e565b80851615614cc957918102915b93841c9390800290614ca0565b509250929050565b600082614ced57506001612915565b81614cfa57506000612915565b8160018114614d105760028114614d1a57614d36565b6001915050612915565b60ff841115614d2b57614d2b61406e565b50506001821b612915565b5060208310610133831016604e8410600b8410161715614d59575081810a612915565b614d638383614c9b565b8060001904821115614d7757614d7761406e565b029392505050565b60006128468383614cde56fea264697066735822122087fa58f50dda5e3e024188f1a14ed7a1d4e86b164f7a175bf68c314bdd1eb3eb64736f6c63430008140033000000000000000000000000d11f8cbf170c112e146b28025ce388c2fe9010c1000000000000000000000000739347344c4f2101f7bea345307fcd619956cbc0000000000000000000000000fb64e79a562f7250131cf528242ceb10fdc82395643165393936366334623864343837383863356337633339623563383835326438663362376635613664366134633761396437653263326636633961346535310000000000000000000000000000000000000000000000000de0b6b3a7640000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101a55760003560e01c806394f2f593116100ef578063c65a88e811610092578063c65a88e814610417578063c6a85f6e1461043a578063c99252881461045d578063cbbe361d14610470578063ce18a83714610490578063e27a9abc146104a3578063f1c9144f146104cd578063f2fde38b146104e057600080fd5b806394f2f5931461031a578063973a814e146103235780639a9950471461032c578063a6f75b181461033f578063b08a979d14610352578063b099d572146103d2578063bfc69e83146103e5578063c35905c61461040e57600080fd5b8063679c4de111610157578063679c4de114610273578063715018a61461028657806371b00be81461028e5780637ff39d2914610297578063805661b0146102cd57806383223eb5146102e05780638da5cb5b146102e957806390421b7c146102fa57600080fd5b806301432bf2146101aa57806316c38b3c146101e257806319d85ec0146101f75780632afdebb11461020a5780635bcbd6a81461022a5780635c975abb1461024b578063653318f814610253575b600080fd5b6101cd6101b83660046139f9565b60126020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6101f56101f0366004613a20565b6104f3565b005b6101f5610205366004613a52565b610513565b61021d6102183660046139f9565b6105de565b6040516101d99190613b14565b61023d610238366004613bdf565b610779565b6040519081526020016101d9565b6101cd61121e565b61023d6102613660046139f9565b60136020526000908152604090205481565b6101f5610281366004613c19565b61122e565b6101f56112bc565b61023d60095481565b6102c06102a53660046139f9565b6010602052600090815260409020546001600160a01b031681565b6040516101d99190613c52565b6101f56102db366004613c66565b6112d0565b61023d600c5481565b6006546001600160a01b03166102c0565b61023d6103083660046139f9565b60156020526000908152604090205481565b61023d600b5481565b61023d60145481565b6101f561033a3660046139f9565b61132e565b6101f561034d366004613c83565b61136b565b61039e6103603660046139f9565b600e60205260009081526040902060018101546002820154600383015460048401546005909401549293919290916001600160a01b03908116911685565b604080519586526020860194909452928401919091526001600160a01b03908116606084015216608082015260a0016101d9565b61023d6103e0366004613d1b565b6118c1565b6102c06103f33660046139f9565b6016602052600090815260409020546001600160a01b031681565b61023d600a5481565b6101cd6104253660046139f9565b600f6020526000908152604090205460ff1681565b6101cd6104483660046139f9565b60116020526000908152604090205460ff1681565b6007546102c0906001600160a01b031681565b61048361047e3660046139f9565b612005565b6040516101d99190613d56565b6008546102c0906001600160a01b031681565b6104b66104b13660046139f9565b6121f6565b6040516101d99b9a99989796959493929190613e65565b6101f56104db366004613ee3565b6122f6565b6101f56104ee366004613c66565b612706565b6104fb612741565b8061050b5761050861276e565b50565b6105086127bd565b61051b612741565b600280546001600160a01b0319166001600160a01b038816179055600380546001600160a01b0319166001600160a01b038716179055600780546001600160a01b0319166001600160a01b038681169182179092556009859055600b849055600a8390556040805189841681529288166020840152820152606081018490526080810183905260a081018290527f605eb9e491eeddbc501664783694a220b259a9a1f6da73ad50e982bdee1754969060c0015b60405180910390a1505050505050565b6040805161016081018252606080825260006020830181905292820183905281018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526000828152600d6020526040908190208151610160810190925280548290829061066090613f1b565b80601f016020809104026020016040519081016040528092919081815260200182805461068c90613f1b565b80156106d95780601f106106ae576101008083540402835291602001916106d9565b820191906000526020600020905b8154815290600101906020018083116106bc57829003601f168201915b5050509183525050600182015461ffff8082166020840152620100008204166040830152600160201b8104600290810b6060840152600160381b90910460ff16608083015282015460a0820152600382015460c0820152600482015460e082015260058201546001600160a01b03908116610100830152600690920154918216610120820152600160a01b90910462ffffff166101409091015292915050565b6000610783612800565b600061078f8380613f4f565b915050600181116107bb5760405162461bcd60e51b81526004016107b290613f9f565b60405180910390fd5b60005b8181101561096157366107d18580613f4f565b838181106107e1576107e1613fd1565b90506020028101906107f39190613fe7565b9050600760009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa158015610848573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086c9190614007565b6001600160a01b031663ce440b9361088a6040840160208501614034565b61089a6060850160408601614034565b6040516001600160e01b031960e085901b16815261ffff928316600482015291166024820152604401602060405180830381865afa1580156108e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109049190614051565b6109505760405162461bcd60e51b815260206004820152601f60248201527f4c6976652074726164696e67206e6f7420656e61626c6564206f6e206c65670060448201526064016107b2565b5061095a81614084565b90506107be565b50600760009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d99190614007565b6001600160a01b031663e88698bf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3a919061409d565b83604001351015610a5d5760405162461bcd60e51b81526004016107b2906140b6565b6000610a73600b543063a6f75b1860e01b612826565b9050610ac4604051806040016040528060048152602001636d6f646560e01b815250604051806040016040528060068152602001657061726c617960d01b8152508361284d9092919063ffffffff16565b6000826001600160401b03811115610ade57610ade6140df565b604051908082528060200260200182016040528015610b1157816020015b6060815260200190600190039081610afc5790505b5090506000836001600160401b03811115610b2e57610b2e6140df565b604051908082528060200260200182016040528015610b6157816020015b6060815260200190600190039081610b4c5790505b5090506000846001600160401b03811115610b7e57610b7e6140df565b604051908082528060200260200182016040528015610bb157816020015b6060815260200190600190039081610b9c5790505b5090506000856001600160401b03811115610bce57610bce6140df565b604051908082528060200260200182016040528015610c0157816020015b6060815260200190600190039081610bec5790505b5090506000866001600160401b03811115610c1e57610c1e6140df565b604051908082528060200260200182016040528015610c5157816020015b6060815260200190600190039081610c3c5790505b5090506000876001600160401b03811115610c6e57610c6e6140df565b604051908082528060200260200182016040528015610ca157816020015b6060815260200190600190039081610c8c5790505b5090506000886001600160401b03811115610cbe57610cbe6140df565b604051908082528060200260200182016040528015610cf157816020015b6060815260200190600190039081610cdc5790505b50905060005b89811015610edd5736610d0a8d80613f4f565b83818110610d1a57610d1a613fd1565b9050602002810190610d2c9190613fe7565b9050610d3881806140f5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250508b518c92508591508110610d8057610d80613fd1565b6020026020010181905250610daa816020016020810190610da19190614034565b61ffff16612870565b888381518110610dbc57610dbc613fd1565b6020908102919091010152610dda610da16060830160408401614034565b878381518110610dec57610dec613fd1565b6020908102919091010152610e12610e0a608083016060840161414a565b60020b612902565b868381518110610e2457610e24613fd1565b6020908102919091010152610e4a610e4260a0830160808401614176565b60ff16612870565b858381518110610e5c57610e5c613fd1565b6020026020010181905250610e748160a00135612870565b848381518110610e8657610e86613fd1565b6020908102919091010152610eae610ea460e0830160c084016141a4565b62ffffff16612870565b838381518110610ec057610ec0613fd1565b60200260200101819052505080610ed690614084565b9050610cf7565b5060408051808201909152600781526667616d6549647360c81b6020820152610f0890899089612952565b60408051808201909152600881526773706f727449647360c01b6020820152610f3390899088612952565b6040805180820190915260078152667479706549647360c81b6020820152610f5d90899087612952565b6040805180820190915260058152646c696e657360d81b6020820152610f8590899086612952565b604080518082019091526009815268706f736974696f6e7360b81b6020820152610fb190899085612952565b60408051808201909152600f81526e65787065637465644c65674f64647360881b6020820152610fe390899084612952565b604080518082019091526009815268706c6179657249647360b81b602082015261100f90899083612952565b61104b6040518060400160405280600b81526020016a189d5e525b905b5bdd5b9d60aa1b8152508c602001358a6129ca9092919063ffffffff16565b604080518082018252600d81526c657870656374656451756f746560981b602082015261107d918a91908e01356129ca565b6040805180820190915260128152716164646974696f6e616c536c69707061676560701b60208201526110b690899060608e01356129ca565b6110ec604051806040016040528060098152602001683932b8bab2b9ba32b960b91b8152506110e4336129e8565b8a919061284d565b61112d6040518060400160405280600a81526020016918dbdb1b185d195c985b60b21b8152506110e48d60a00160208101906111289190613c66565b6129e8565b61113988600a546129fe565b6000818152601360209081526040808320429055600e9091529020909a508b906111638282614623565b505060008a815260106020908152604080832080546001600160a01b03191633908117909155600f8352818420805460ff1916600117905560148054855260158452938290208e9055925481519384528383015282018c905261ffff8b1660608301528c013560808201527f49f9ae6cc4633cb9c99638c964ae59e7f2eaea5e53a2beb1e6f76f7bf8f4370b9060a00160405180910390a16014805490600061120b83614084565b9190505550505050505050505050919050565b600654600160a01b900460ff1690565b611236612741565b6112b881836001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016112669190613c52565b602060405180830381865afa158015611283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a7919061409d565b6001600160a01b0385169190612a18565b5050565b6112c4612741565b6112ce6000612a6a565b565b6112d8612741565b600880546001600160a01b0319166001600160a01b0383161790556040517fc238ff72ce9e31f22c0ef8bf1c701fcc6afd3ed4edc2224a63f16346b68420fb90611323908390613c52565b60405180910390a150565b611336612741565b600c8190556040518181527fa1d20d22955d911c8b338eeec58c0fa61197b85b255251efe74df475baa5c73890602001611323565b611373612800565b60008581526005602052604090205485906001600160a01b031633146113ab5760405162461bcd60e51b81526004016107b2906146c2565b60008181526005602052604080822080546001600160a01b03191690555182917f7cc135e0cebb02c3480ae5d74d377283180a2601f8f644edf7987b009316c63a91a260008681526012602052604090205460ff161561141d5760405162461bcd60e51b81526004016107b29061470a565b600c54600087815260136020526040902054429161143a91614741565b116114575760405162461bcd60e51b81526004016107b290614754565b6000868152600f602052604090205460ff166114ad5760405162461bcd60e51b815260206004820152601560248201527452657175657374206973206e6f74207061726c617960581b60448201526064016107b2565b6000868152600e602090815260408083208151815460e09481028201850190935260c08101838152909391928492849190879085015b8282101561160457838290600052602060002090600402016040518060e001604052908160008201805461151690613f1b565b80601f016020809104026020016040519081016040528092919081815260200182805461154290613f1b565b801561158f5780601f106115645761010080835404028352916020019161158f565b820191906000526020600020905b81548152906001019060200180831161157257829003601f168201915b505050918352505060018281015461ffff8082166020808601919091526201000083049091166040850152600160201b8204600290810b6060860152600160381b90920460ff1660808501529084015460a084015260039093015462ffffff1660c090920191909152918352920191016114e3565b5050509082525060018281015460208084019190915260028401546040808501919091526003850154606085015260048501546001600160a01b039081166080860152600590950154851660a09094019390935260008c815260109091529190912054835151939450909116919081116116905760405162461bcd60e51b81526004016107b290613f9f565b8481146116d55760405162461bcd60e51b8152602060048201526013602482015272084c2c840d8cace40dec8c8e640d8cadccee8d606b1b60448201526064016107b2565b60608301516116ec90670de0b6b3a7640000614741565b604084015161170389670de0b6b3a76400006141c1565b61170d9190614795565b111561172b5760405162461bcd60e51b81526004016107b2906147a9565b871561181d576000816001600160401b0381111561174b5761174b6140df565b60405190808252806020026020018201604052801561178457816020015b61177161394c565b8152602001906001900390816117695790505b50905060005b828110156117ff576117d1856000015182815181106117ab576117ab613fd1565b60200260200101518989848181106117c5576117c5613fd1565b90506020020135612abc565b8282815181106117e3576117e3613fd1565b6020026020010181905250806117f890614084565b905061178a565b5061181b8a848387602001518c89608001518a60a00151612bdc565b505b600089815260116020908152604080832080548c151560ff199182168117909255601284529382902080549094166001179093558582015181516001600160a01b03871681529283018d90529082019290925261ffff83166060820152608081019190915260a081018890527f7ae269cd4fee93b8f25452870350fd171bb1368d74b259d94ccf7a971b044ed79060c00160405180910390a1505050505050505050565b60006118cb612800565b600760009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa15801561191e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119429190614007565b6001600160a01b031663ce440b936119606040850160208601614034565b6119706060860160408701614034565b6040516001600160e01b031960e085901b16815261ffff928316600482015291166024820152604401602060405180830381865afa1580156119b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119da9190614051565b611a325760405162461bcd60e51b8152602060048201526024808201527f4c6976652074726164696e67206e6f7420656e61626c6564206f6e205f73706f6044820152631c9d125960e21b60648201526084016107b2565b600760009054906101000a90046001600160a01b03166001600160a01b031663478426636040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa99190614007565b6001600160a01b031663e88698bf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a919061409d565b8260c001351015611b2d5760405162461bcd60e51b81526004016107b2906140b6565b6000611b436009543063f1c9144f60e01b612826565b9050611b94604051806040016040528060048152602001636d6f646560e01b8152506040518060400160405280600681526020016573696e676c6560d01b8152508361284d9092919063ffffffff16565b60408051808201909152600681526519d85b59525960d21b6020820152611bfd90611bbf85806140f5565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525086949392505061284d9050565b611c3f604051806040016040528060078152602001661cdc1bdc9d125960ca1b815250846020016020810190611c339190614034565b83919061ffff166129ca565b60408051808201825260068152651d1e5c19525960d21b6020820152611c6f91611c339060608701908701614034565b6040805180820190915260048152636c696e6560e01b6020820152611ca990611c9e608086016060870161414a565b83919060020b612d17565b6040805180820190915260088152673837b9b4ba34b7b760c11b6020820152611ce790611cdc60a0860160808701614176565b83919060ff166129ca565b60408051808201909152600b81526a189d5e525b905b5bdd5b9d60aa1b6020820152611d1990829060a08601356129ca565b60408051808201909152600d81526c657870656374656451756f746560981b6020820152611d4d90829060c08601356129ca565b6040805180820190915260128152716164646974696f6e616c536c69707061676560701b6020820152611d8690829060e08601356129ca565b6040805180820190915260088152671c1b185e595c925960c21b6020820152611dc890611dbb610160860161014087016141a4565b83919062ffffff166129ca565b611dfe604051806040016040528060098152602001683932b8bab2b9ba32b960b91b815250611df6336129e8565b83919061284d565b60408051808201909152600a81526918dbdb1b185d195c985b60b21b6020820152611e3890611df661112861014087016101208801613c66565b611e4481600a546129fe565b6000818152601360209081526040808320429055600d90915290209092508390611e6e82826147d4565b5050600082815260106020908152604080832080546001600160a01b03191633908117909155600f8352818420805460ff1916905560148054855260159093529220849055547fdc457bcbffcdb3995df4b3bb7a325fe68d19b75af17c94b8d1d277a85691e20f919084611f1f611ee588806140f5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d3592505050565b611f2f6040890160208a01614034565b611f3f60608a0160408b01614034565b611f4f60808b0160608c0161414a565b611f5f60a08c0160808d01614176565b8b60a001358c60c001358d610120016020810190611f7d9190613c66565b604080516001600160a01b039c8d168152602081019b909b528a0198909852606089019690965261ffff94851660808901529390921660a087015260020b60c086015260ff1660e0850152610100840152610120830152919091166101408201526101600160405180910390a160148054906000611ffa83614084565b919050555050919050565b6120506040518060c001604052806060815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b031681525090565b6000828152600e602090815260408083208151815460e09481028201850190935260c08101838152909491938593919285929185015b828210156121a757838290600052602060002090600402016040518060e00160405290816000820180546120b990613f1b565b80601f01602080910402602001604051908101604052809291908181526020018280546120e590613f1b565b80156121325780601f1061210757610100808354040283529160200191612132565b820191906000526020600020905b81548152906001019060200180831161211557829003601f168201915b505050918352505060018281015461ffff8082166020808601919091526201000083049091166040850152600160201b8204600290810b6060860152600160381b90920460ff1660808501529084015460a084015260039093015462ffffff1660c09092019190915291835292019101612086565b5050509082525060018201546020820152600282015460408201526003820154606082015260048201546001600160a01b03908116608083015260059092015490911660a09091015292915050565b600d6020526000908152604090208054819061221190613f1b565b80601f016020809104026020016040519081016040528092919081815260200182805461223d90613f1b565b801561228a5780601f1061225f5761010080835404028352916020019161228a565b820191906000526020600020905b81548152906001019060200180831161226d57829003601f168201915b505050506001830154600280850154600386015460048701546005880154600690980154969761ffff808716986201000088049091169750600160201b870490950b95600160381b900460ff16946001600160a01b0391821691811690600160a01b900462ffffff168b565b6122fe612800565b60008381526005602052604090205483906001600160a01b031633146123365760405162461bcd60e51b81526004016107b2906146c2565b60008181526005602052604080822080546001600160a01b03191690555182917f7cc135e0cebb02c3480ae5d74d377283180a2601f8f644edf7987b009316c63a91a260008481526012602052604090205460ff16156123a85760405162461bcd60e51b81526004016107b29061470a565b600c5460008581526013602052604090205442916123c591614741565b116123e25760405162461bcd60e51b81526004016107b290614754565b6000848152600f602052604090205460ff16156124355760405162461bcd60e51b815260206004820152601160248201527052657175657374206973207061726c617960781b60448201526064016107b2565b6000848152600d60205260408082208151610160810190925280548290829061245d90613f1b565b80601f016020809104026020016040519081016040528092919081815260200182805461248990613f1b565b80156124d65780601f106124ab576101008083540402835291602001916124d6565b820191906000526020600020905b8154815290600101906020018083116124b957829003601f168201915b5050509183525050600182015461ffff808216602080850191909152620100008304909116604080850191909152600160201b8304600290810b6060860152600160381b90930460ff1660808501529184015460a0840152600384015460c0840152600484015460e08085019190915260058501546001600160a01b03908116610100860152600690950154808616610120860152600160a01b900462ffffff166101409094019390935260008a8152601090915220549083015192935016906125a890670de0b6b3a7640000614741565b60c08301516125bf86670de0b6b3a76400006141c1565b6125c99190614795565b11156125e75760405162461bcd60e51b81526004016107b2906147a9565b841561266857604080516001808252818301909252600091816020015b61260c61394c565b81526020019060019003908161260457905050905061262b8386612d54565b8160008151811061263e5761263e613fd1565b60200260200101819052506126668783838660a0015189886101000151896101200151612bdc565b505b6000868152601160209081526040808320805489151560ff199182161790915560129092529091208054909116600117905581517fe16fea440372e1dff8f7e8cb79dcc6e6af20f2af3a278835a2049243b25d03ca908290889088906126cd90612d35565b86602001518760400151886060015189608001518a60a001518d8c6101200151426040516105ce9c9b9a999897969594939291906148a6565b61270e612741565b6001600160a01b038116612738576000604051631e4fbdf760e01b81526004016107b29190613c52565b61050881612a6a565b6006546001600160a01b031633146112ce573360405163118cdaa760e01b81526004016107b29190613c52565b612776612e75565b6006805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516127b39190613c52565b60405180910390a1565b6127c5612800565b6006805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586127a63390565b61280861121e565b156112ce5760405163d93c066560e01b815260040160405180910390fd5b61282e6139aa565b6128366139aa565b61284281868686612e9a565b9150505b9392505050565b608083015161285c9083612ee0565b608083015161286b9082612ee0565b505050565b6060600061287d83612ef7565b60010190506000816001600160401b0381111561289c5761289c6140df565b6040519080825280601f01601f1916602001820160405280156128c6576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846128d057509392505050565b60606000821261291b5761291582612870565b92915050565b61292c61292783614928565b612870565b60405160200161293c9190614944565b6040516020818303038152906040529050919050565b60808301516129619083612ee0565b61296e8360800151612fcf565b60005b81518110156129bc576129aa82828151811061298f5761298f613fd1565b60200260200101518560800151612ee090919063ffffffff16565b806129b481614084565b915050612971565b5061286b8360800151612fda565b60808301516129d99083612ee0565b608083015161286b9082612fe5565b60606129156001600160a01b038316601461300a565b600354600090612846906001600160a01b03168484613181565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261286b908490613214565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612ac461394c565b6040805160e1808252611c4082019092526060916000919060208201611c20803683370190505090508381866080015160ff1681518110612b0757612b07613fd1565b60209081029190910101526040805160e1808252611c408201909252600091816020015b6060815260200190600190039081612b2b579050509050604051806101600160405280612b5b8860000151612d35565b8152602001876020015161ffff168152602001876040015161ffff16815260200142603c612b899190614741565b8152602001600060ff168152602001876060015160020b81526020018760c0015162ffffff168152602001838152602001848152602001876080015160ff16815260200182815250935050505092915050565b600754604051637240d1a160e11b81526000916001600160a01b03169063e481a34290612c17908990899089908d908a908a90600401614a39565b6020604051808303816000875af1158015612c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5a9190614007565b600089815260166020526040902080546001600160a01b0319166001600160a01b038381169190911790915560085491925090811690881603612d0d5760085460405163a12d5b0760e01b8152600481018a90526001600160a01b0383811660248301526044820188905284811660648301529091169063a12d5b0790608401600060405180830381600087803b158015612cf457600080fd5b505af1158015612d08573d6000803e3d6000fd5b505050505b5050505050505050565b6080830151612d269083612ee0565b608083015161286b908261326e565b805160009082908203612d4b5750600092915050565b50506020015190565b612d5c61394c565b6040805160e1808252611c4082019092526060916000919060208201611c20803683370190505090508381866080015160ff1681518110612d9f57612d9f613fd1565b60209081029190910101526040805160e1808252611c408201909252600091816020015b6060815260200190600190039081612dc3579050509050604051806101600160405280612df38860000151612d35565b8152602001876020015161ffff168152602001876040015161ffff16815260200142603c612e219190614741565b8152602001600060ff168152602001876060015160020b815260200187610140015162ffffff168152602001838152602001848152602001876080015160ff16815260200182815250935050505092915050565b612e7d61121e565b6112ce57604051638dfc202b60e01b815260040160405180910390fd5b612ea26139aa565b612eb285608001516101006132cd565b50508284526001600160a01b03821660208501526001600160e01b031981166040850152835b949350505050565b612eed8260038351613325565b61286b8282613432565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612f365772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612f62576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612f8057662386f26fc10000830492506010015b6305f5e1008310612f98576305f5e100830492506008015b6127108310612fac57612710830492506004015b60648310612fbe576064830492506002015b600a83106129155760010192915050565b61050881600461344c565b61050881600761344c565b6001600160401b03811115612ffe576112b88282613461565b6112b882600083613325565b606082600061301a8460026141c1565b613025906002614741565b6001600160401b0381111561303c5761303c6140df565b6040519080825280601f01601f191660200182016040528015613066576020820181803683370190505b509050600360fc1b8160008151811061308157613081613fd1565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106130b0576130b0613fd1565b60200101906001600160f81b031916908160001a90535060006130d48560026141c1565b6130df906001614741565b90505b6001811115613157576f181899199a1a9b1b9c1cb0b131b232b360811b83600f166010811061311357613113613fd1565b1a60f81b82828151811061312957613129613fd1565b60200101906001600160f81b031916908160001a90535060049290921c9161315081614b8c565b90506130e2565b508115612ed85760405163e22e27eb60e01b815260048101869052602481018590526044016107b2565b600454600090613192816001614741565b600455835160408086015160808701515191516000936320214ca360e11b936131ca9386938493923092918a91600191602401614ba3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905061320a86838684613498565b9695505050505050565b60006132296001600160a01b038416836135f6565b9050805160001415801561324e57508080602001905181019061324c9190614051565b155b1561286b5782604051635274afe760e01b81526004016107b29190613c52565b67ffffffffffffffff19811215613289576112b88282613604565b6001600160401b038113156132a2576112b88282613461565b600081126132b6576112b882600083613325565b6112b88260016132c884600019614c0b565b613325565b6132d56139df565b6132e0602083614c32565b15613308576132f0602083614c32565b6132fb906020614c46565b6133059083614741565b91505b506020828101829052604080518085526000815290920101905290565b6017816001600160401b03161161334f576133498360e0600585901b168317613632565b50505050565b60ff816001600160401b03161161338b57613375836018611fe0600586901b1617613632565b50613349836001600160401b038316600161364a565b61ffff816001600160401b0316116133c8576133b2836019611fe0600586901b1617613632565b50613349836001600160401b038316600261364a565b63ffffffff816001600160401b031611613407576133f183601a611fe0600586901b1617613632565b50613349836001600160401b038316600461364a565b61341c83601b611fe0600586901b1617613632565b50613349836001600160401b038316600861364a565b61343a6139df565b61284683846000015151848551613663565b61286b82601f611fe0600585901b1617613632565b61346c8260c2613632565b506112b8828260405160200161348491815260200190565b604051602081830303815290604052613740565b6040516bffffffffffffffffffffffff193060601b1660208201526034810184905260009060540160408051808303601f1901815282825280516020918201206000818152600590925291812080546001600160a01b0319166001600160a01b038a1617905590925082917fb5e6e01e79f91267dc17b4e6314d5d4d03593d2ceee0fbb452b750bd70ea5af99190a2600254604051630200057560e51b81526001600160a01b0390911690634000aea09061355b90889087908790600401614c59565b6020604051808303816000875af115801561357a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359e9190614051565b612ed85760405162461bcd60e51b815260206004820152602360248201527f756e61626c6520746f207472616e73666572416e6443616c6c20746f206f7261604482015262636c6560e81b60648201526084016107b2565b60606128468383600061374d565b61360f8260c3613632565b506112b88261362083600019614c0b565b60405160200161348491815260200190565b61363a6139df565b61284683846000015151846137e0565b6136526139df565b612ed884856000015151858561382e565b61366b6139df565b825182111561367957600080fd5b60208501516136888386614741565b11156136bb576136bb856136ab876020015187866136a69190614741565b6138a2565b6136b69060026141c1565b6138b9565b6000808651805187602083010193508088870111156136da5787860182525b505050602084015b6020841061371a57805182526136f9602083614741565b9150613706602082614741565b9050613713602085614c46565b93506136e2565b51815160001960208690036101000a019081169019919091161790525083949350505050565b612eed8260028351613325565b606081471015613772573060405163cd78605960e01b81526004016107b29190613c52565b600080856001600160a01b0316848660405161378e9190614c89565b60006040518083038185875af1925050503d80600081146137cb576040519150601f19603f3d011682016040523d82523d6000602084013e6137d0565b606091505b509150915061320a8683836138d0565b6137e86139df565b836020015183106138085761380884856020015160026136b691906141c1565b8351805160208583010184815350808503613824576001810182525b5093949350505050565b6138366139df565b60208501516138458584614741565b111561385957613859856136ab8685614741565b6000600161386984610100614d7f565b6138739190614c46565b90508551838682010185831982511617815250805184870111156138975783860181525b509495945050505050565b6000818311156138b3575081612915565b50919050565b81516138c583836132cd565b506133498382613432565b6060826138e5576138e082613923565b612846565b81511580156138fc57506001600160a01b0384163b155b1561391c5783604051639996b31560e01b81526004016107b29190613c52565b5080612846565b8051156139335780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201819052610100820181905261012082019290925261014081019190915290565b6040805160a0810182526000808252602082018190529181018290526060810191909152608081016139da6139df565b905290565b604051806040016040528060608152602001600081525090565b600060208284031215613a0b57600080fd5b5035919050565b801515811461050857600080fd5b600060208284031215613a3257600080fd5b813561284681613a12565b6001600160a01b038116811461050857600080fd5b60008060008060008060c08789031215613a6b57600080fd5b8635613a7681613a3d565b95506020870135613a8681613a3d565b94506040870135613a9681613a3d565b959894975094956060810135955060808101359460a0909101359350915050565b60005b83811015613ad2578181015183820152602001613aba565b50506000910152565b60008151808452613af3816020860160208601613ab7565b601f01601f19169290920160200192915050565b6001600160a01b03169052565b6020815260008251610160806020850152613b33610180850183613adb565b91506020850151613b4a604086018261ffff169052565b50604085015161ffff81166060860152506060850151613b6f608086018260020b9052565b50608085015160ff811660a08601525060a085015160c085015260c085015160e085015260e0850151610100818187015280870151915050610120613bb681870183613b07565b8601519050610140613bca86820183613b07565b9095015162ffffff1693019290925250919050565b600060208284031215613bf157600080fd5b81356001600160401b03811115613c0757600080fd5b820160c0818503121561284657600080fd5b60008060408385031215613c2c57600080fd5b8235613c3781613a3d565b91506020830135613c4781613a3d565b809150509250929050565b6001600160a01b0391909116815260200190565b600060208284031215613c7857600080fd5b813561284681613a3d565b600080600080600060808688031215613c9b57600080fd5b853594506020860135613cad81613a12565b93506040860135925060608601356001600160401b0380821115613cd057600080fd5b818801915088601f830112613ce457600080fd5b813581811115613cf357600080fd5b8960208260051b8501011115613d0857600080fd5b9699959850939650602001949392505050565b600060208284031215613d2d57600080fd5b81356001600160401b03811115613d4357600080fd5b8201610160818503121561284657600080fd5b6000602080835260e0808401855160c0808588015282825180855261010094508489019150848160051b8a01019450868401935060005b81811015613e125789860360ff1901835284518051888852613db189890182613adb565b828b015161ffff9081168a8d0152604080850151909116908a015260608084015160020b908a015260808084015160ff16908a015260a080840151908a01529186015162ffffff169786019790975295509387019391870191600101613d8d565b505050848801516040880152604088015160608801526060880151608088015260808801519450613e4660a0880186613b07565b60a08801519450613e5981880186613b07565b50909695505050505050565b6000610160808352613e798184018f613adb565b61ffff9d8e1660208501529b909c1660408301525060029890980b606089015260ff96909616608088015260a087019490945260c086019290925260e08501526001600160a01b039081166101008501521661012083015262ffffff166101409091015292915050565b600080600060608486031215613ef857600080fd5b833592506020840135613f0a81613a12565b929592945050506040919091013590565b600181811c90821680613f2f57607f821691505b6020821081036138b357634e487b7160e01b600052602260045260246000fd5b6000808335601e19843603018112613f6657600080fd5b8301803591506001600160401b03821115613f8057600080fd5b6020019150600581901b3603821315613f9857600080fd5b9250929050565b6020808252601890820152775061726c6179206d7573742068617665203e2031206c656760401b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000823560de19833603018112613ffd57600080fd5b9190910192915050565b60006020828403121561401957600080fd5b815161284681613a3d565b61ffff8116811461050857600080fd5b60006020828403121561404657600080fd5b813561284681614024565b60006020828403121561406357600080fd5b815161284681613a12565b634e487b7160e01b600052601160045260246000fd5b6000600182016140965761409661406e565b5060010190565b6000602082840312156140af57600080fd5b5051919050565b6020808252600f908201526e45786365656465644d61784f64647360881b604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6000808335601e1984360301811261410c57600080fd5b8301803591506001600160401b0382111561412657600080fd5b602001915036819003821315613f9857600080fd5b8060020b811461050857600080fd5b60006020828403121561415c57600080fd5b81356128468161413b565b60ff8116811461050857600080fd5b60006020828403121561418857600080fd5b813561284681614167565b62ffffff8116811461050857600080fd5b6000602082840312156141b657600080fd5b813561284681614193565b80820281158282048414176129155761291561406e565b5b818110156112b857600081556001016141d9565b600019600383901b1c191660019190911b1790565b601f82111561286b57806000526020600020601f840160051c810160208510156142295750805b61423b601f850160051c8301826141d8565b5050505050565b6001600160401b03831115614259576142596140df565b61426d836142678354613f1b565b83614202565b6000601f84116001811461429b57600085156142895750838201355b61429386826141ed565b84555061423b565b600083815260209020601f19861690835b828110156142cc57868501358255602094850194600190920191016142ac565b50868210156142e95760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000813561291581614024565b600081356129158161413b565b6000813561291581614167565b6000813561291581614193565b61433982836140f5565b6001600160401b03811115614350576143506140df565b6143648161435e8554613f1b565b85614202565b6000601f82116001811461439257600083156143805750838201355b61438a84826141ed565b8655506143ec565b600085815260209020601f19841690835b828110156143c357868501358255602094850194600190920191016143a3565b50848210156143e05760001960f88660031b161c19848701351681555b505060018360011b0185555b5050505060018101614416614403602085016142fb565b825461ffff191661ffff91909116178255565b61443f614425604085016142fb565b825463ffff0000191660109190911b63ffff000016178255565b61447061444e60608501614308565b825460209190911b66ffffff000000001666ffffff0000000019909116178255565b61449d61447f60808501614315565b82805460ff60381b191660389290921b60ff60381b16919091179055565b5060a082013560028201556112b86144b760c08401614322565b6003830162ffffff821662ffffff198254161781555050565b600160401b8311156144e4576144e46140df565b8054838255808410156145b05760026001600160fe1b03828116831461450c5761450c61406e565b808616861461451d5761451d61406e565b5060008381526020812086831b81019084841b015b808210156145ab576145448254613f1b565b801561458e57601f8082116001811461455f5785855561458b565b60008581526020902061457c83850160051c8201600183016141d8565b50600085815260208120818755555b50505b508260018301558284830155826003830155600482019150614532565b505050505b5060008181526020812083915b858110156145ee576145d86145d28487613fe7565b8361432f565b60209290920191600491909101906001016145bd565b505050505050565b6000813561291581613a3d565b80546001600160a01b0319166001600160a01b0392909216919091179055565b8135601e1983360301811261463757600080fd5b820180356001600160401b0381111561464f57600080fd5b6020820191508060051b360382131561466757600080fd5b6146728183856144d0565b50506020820135600182015560408201356002820155606082013560038201556146aa6146a1608084016145f6565b60048301614603565b6112b86146b960a084016145f6565b60058301614603565b60208082526028908201527f536f75726365206d75737420626520746865206f7261636c65206f6620746865604082015267081c995c5d595cdd60c21b606082015260800190565b6020808252601c908201527f5265717565737420494420616c72656164792066756c66696c6c656400000000604082015260600190565b808201808211156129155761291561406e565b60208082526011908201527014995c5d595cdd081d1a5b5959081bdd5d607a1b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b6000826147a4576147a461477f565b500490565b6020808252601190820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604082015260600190565b6147de82836140f5565b6147e9818385614242565b5050600181016147fe614403602085016142fb565b61480d614425604085016142fb565b61481c61444e60608501614308565b61482b61447f60808501614315565b5060a0820135600282015560c0820135600382015560e0820135600482015561485a6146b961010084016145f6565b6006810161487461486e61012085016145f6565b82614603565b61286b6148846101408501614322565b82805462ffffff60a01b191660a09290921b62ffffff60a01b16919091179055565b6001600160a01b038d168152602081018c90528a15156040820152606081018a905261ffff8981166080830152881660a0820152600287900b60c082015260ff861660e0820152610100810185905261012081018490526101808101614910610140830185613b07565b826101608301529d9c50505050505050505050505050565b6000600160ff1b820161493d5761493d61406e565b5060000390565b602d60f81b815260008251614960816001850160208701613ab7565b9190910160010192915050565b600081518084526020808501945080840160005b8381101561389757815187529582019590820190600101614981565b600081518084526020808501808196508360051b810191508286016000805b86811015614a2b578385038a52825180518087529087019087870190845b81811015614a16578351805161ffff1684528a81015160ff168b85015260409081015160020b90840152928901926060909201916001016149da565b50509a87019a955050918501916001016149bc565b509298975050505050505050565b600060c0808301818452808a5180835260e092508286019150828160051b8701016020808e0160005b84811015614b445789840360df190186528151805185528381015161ffff90811685870152604080830151909116908601526060808201519086015260808082015160ff169086015260a08082015160020b908601528881015162ffffff16898601528781015161016089870181905290614adf8288018261496d565b9150506101008083015187830382890152614afa838261496d565b9250505061012080830151614b138289018260ff169052565b50506101408083015192508682038188015250614b30818361499d565b978501979550505090820190600101614a62565b50508196508c81890152505050505050856040830152614b676060830186613b07565b614b746080830185613b07565b614b8160a0830184613b07565b979650505050505050565b600081614b9b57614b9b61406e565b506000190190565b6001600160a01b0389811682526020820189905260408201889052861660608201526001600160e01b03198516608082015260a0810184905260c0810183905261010060e08201819052600090614bfc83820185613adb565b9b9a5050505050505050505050565b8181036000831280158383131683831282161715614c2b57614c2b61406e565b5092915050565b600082614c4157614c4161477f565b500690565b818103818111156129155761291561406e565b60018060a01b0384168152826020820152606060408201526000614c806060830184613adb565b95945050505050565b60008251613ffd818460208701613ab7565b600181815b80851115614cd6578160001904821115614cbc57614cbc61406e565b80851615614cc957918102915b93841c9390800290614ca0565b509250929050565b600082614ced57506001612915565b81614cfa57506000612915565b8160018114614d105760028114614d1a57614d36565b6001915050612915565b60ff841115614d2b57614d2b61406e565b50506001821b612915565b5060208310610133831016604e8410600b8410161715614d59575081810a612915565b614d638383614c9b565b8060001904821115614d7757614d7761406e565b029392505050565b60006128468383614cde56fea264697066735822122087fa58f50dda5e3e024188f1a14ed7a1d4e86b164f7a175bf68c314bdd1eb3eb64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d11f8cbf170c112e146b28025ce388c2fe9010c1000000000000000000000000739347344c4f2101f7bea345307fcd619956cbc0000000000000000000000000fb64e79a562f7250131cf528242ceb10fdc82395643165393936366334623864343837383863356337633339623563383835326438663362376635613664366134633761396437653263326636633961346535310000000000000000000000000000000000000000000000000de0b6b3a7640000
-----Decoded View---------------
Arg [0] : _link (address): 0xd11f8CbF170c112e146b28025cE388C2FE9010C1
Arg [1] : _oracle (address): 0x739347344c4F2101F7Bea345307fcD619956CbC0
Arg [2] : _sportsAMM (address): 0xfb64E79A562F7250131cf528242CEB10fDC82395
Arg [3] : _jobSpecId (bytes32): 0x6431653939363663346238643438373838633563376333396235633838353264
Arg [4] : _parlayJobSpecId (bytes32): 0x3866336237663561366436613463376139643765326332663663396134653531
Arg [5] : _paymentAmount (uint256): 1000000000000000000
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000d11f8cbf170c112e146b28025ce388c2fe9010c1
Arg [1] : 000000000000000000000000739347344c4f2101f7bea345307fcd619956cbc0
Arg [2] : 000000000000000000000000fb64e79a562f7250131cf528242ceb10fdc82395
Arg [3] : 6431653939363663346238643438373838633563376333396235633838353264
Arg [4] : 3866336237663561366436613463376139643765326332663663396134653531
Arg [5] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.