Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SportsAMMV2RiskManager
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.20;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
// internal
import "../../utils/proxy/ProxyReentrancyGuard.sol";
import "../../utils/proxy/ProxyOwned.sol";
import "../../utils/proxy/ProxyPausable.sol";
import "../../interfaces/ISportsAMMV2Manager.sol";
import "../../interfaces/ISportsAMMV2RiskManager.sol";
import "../../interfaces/ISportsAMMV2.sol";
import "../../interfaces/ISportsAMMV2ResultManager.sol";
/// @title Sports AMM V2 Risk Manager contract
/// @author vladan
contract SportsAMMV2RiskManager is Initializable, ProxyOwned, ProxyPausable, ProxyReentrancyGuard {
/* ========== CONST VARIABLES ========== */
uint public constant DEFAULT_DYNAMIC_LIQUIDITY_CUTOFF_DIVIDER = 2e18;
uint private constant ONE = 1e18;
/* ========== ERRORS ========== */
error InvalidCap();
error InvalidOdds();
error InvalidPosition();
error MarketNotTrading();
error ExceededMarketPositionRisk();
error ExceededGameRisk();
error InvalidCombination();
error ExceededSGPRisk();
error InvalidInput();
error InvalidAddress();
error MismatchedInputs();
error EmptyArrays();
error ExceededMaxCombinations();
error BadRangeForK();
error DividerOutOfRange();
error LowBuyIn();
error ExceededMaxOdds();
error ExceededMaxAmount();
error SlippageTooHigh();
error ExceededMaxSize();
error CantParlayFutures();
error MultiplierTooHigh();
/* ========== STATE VARIABLES ========== */
// sports manager contract address
ISportsAMMV2Manager public manager;
// result manager address
ISportsAMMV2ResultManager public resultManager;
// sports AMM address
ISportsAMMV2 public sportsAMM;
// default cap for all sports
uint public defaultCap;
// cap per specific sport
mapping(uint => uint) public capPerSport;
// cap per all child markets of specific sport
mapping(uint => uint) public capPerSportChild;
// cap per type for specific sport
mapping(uint => mapping(uint => uint)) public capPerSportAndType;
// cap per specific market
mapping(bytes32 => mapping(uint => mapping(uint => mapping(int => uint)))) public capPerMarket;
// default risk multiplier used to calculate total risk on the game
uint public defaultRiskMultiplier;
// risk multiplier per sport used to calculate total risk on the game
mapping(uint => uint) public riskMultiplierPerSport;
// risk multiplier per game used to calculate total risk on the game
mapping(bytes32 => uint) public riskMultiplierPerGame;
// max available cap
uint public maxCap;
// max available risk multiplier
uint public maxRiskMultiplier;
// time before maturity when to start increasing the liquidity linearly
mapping(uint => uint) public dynamicLiquidityCutoffTimePerSport;
// divider on how much liquidity is available before cut off time
mapping(uint => uint) public dynamicLiquidityCutoffDividerPerSport;
mapping(uint => mapping(uint => bool)) public liveTradingPerSportAndTypeEnabled;
mapping(uint => bool) public combiningPerSportEnabled;
// stores current risk per market type and position, defined with gameId -> typeId -> playerId
mapping(bytes32 => mapping(uint => mapping(uint => mapping(uint => int)))) public riskPerMarketTypeAndPosition;
// spent on game (parent market together with all child markets)
mapping(bytes32 => uint) public spentOnGame;
// minimum ticket buy-in amount
uint public minBuyInAmount;
// maximum ticket size
uint public maxTicketSize;
// maximum supported payout amount
uint public maxSupportedAmount;
// maximum supported ticket odds
uint public maxSupportedOdds;
// the period of time in seconds before a market is matured and begins to be restricted for AMM trading
uint public minimalTimeLeftToMaturity;
// the period of time in seconds after maturity when ticket expires
uint public expiryDuration;
// divider on how much of cap should be used on live betting
mapping(uint => uint) public liveCapDividerPerSport;
// default live cap divider
uint public defaultLiveCapDivider;
// store whether a sportId is a futures market type
mapping(uint16 => bool) public isSportIdFuture;
// the maximum number of combinations on a system ticket
uint public maxAllowedSystemCombinations;
// store whether a sportId is a futures market type
mapping(uint16 => bool) public sgpOnSportIdEnabled;
// spent on sgp per game
mapping(bytes32 => uint) public sgpSpentOnGame;
// sgp cap divider
uint public sgpCapDivider;
// sgp risk per combination
mapping(bytes32 => uint) public sgpRiskPerCombination;
/* ========== CONSTRUCTOR ========== */
function initialize(
address _owner,
ISportsAMMV2Manager _manager,
ISportsAMMV2ResultManager _resultManager,
uint _defaultCap,
uint _defaultRiskMultiplier,
uint _maxCap,
uint _maxRiskMultiplier
) public initializer {
setOwner(_owner);
initNonReentrant();
manager = _manager;
resultManager = _resultManager;
defaultCap = _defaultCap;
defaultRiskMultiplier = _defaultRiskMultiplier;
maxCap = _maxCap;
maxRiskMultiplier = _maxRiskMultiplier;
}
/* ========== EXTERNAL READ FUNCTIONS ========== */
/// @notice calculate which cap needs to be applied to the given game
/// @param _gameId to get cap for
/// @param _sportId to get cap for
/// @param _typeId to get cap for
/// @param _playerId to get cap for
/// @param _maturity used for dynamic liquidity check
/// @param _line used for dynamic liquidity check
/// @param _isLive whether this is a live bet
/// @return cap cap to use
function calculateCapToBeUsed(
bytes32 _gameId,
uint16 _sportId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _maturity,
bool _isLive
) external view returns (uint cap) {
return _calculateCapToBeUsed(_gameId, _sportId, _typeId, _playerId, _line, _maturity, _isLive);
}
/// @notice calculate max available total risk on game
/// @param _gameId to total risk for
/// @param _sportId to total risk for
/// @return totalRisk total risk
function calculateTotalRiskOnGame(
bytes32 _gameId,
uint16 _sportId,
uint _maturity
) external view returns (uint totalRisk) {
(totalRisk, ) = _calculateTotalRiskOnGame(_gameId, _sportId, _maturity);
}
/// @notice check risk for ticket
/// @param _tradeData trade data with all market info needed for ticket
/// @param _buyInAmount ticket buy-in amount
/// @param _systemBetDenominator in case of system bets, otherwise 0
/// @return riskStatus risk status
/// @return isMarketOutOfLiquidity array of boolean values that indicates if some market is out of liquidity
function checkRisks(
ISportsAMMV2.TradeData[] memory _tradeData,
uint _buyInAmount,
bool _isLive,
uint8 _systemBetDenominator
) external view returns (ISportsAMMV2RiskManager.RiskStatus riskStatus, bool[] memory isMarketOutOfLiquidity) {
uint numOfMarkets = _tradeData.length;
isMarketOutOfLiquidity = new bool[](numOfMarkets);
bool isFutureOnParlay;
bool isSystemBet = _systemBetDenominator > 1;
for (uint i; i < numOfMarkets; ++i) {
ISportsAMMV2.TradeData memory marketTradeData = _tradeData[i];
isFutureOnParlay = isSportIdFuture[marketTradeData.sportId] && numOfMarkets > 1;
if (marketTradeData.odds[marketTradeData.position] == 0 || marketTradeData.odds[marketTradeData.position] >= ONE)
revert InvalidOdds();
uint amountToBuy = (ONE * _buyInAmount) / marketTradeData.odds[marketTradeData.position];
uint marketRiskAmount = amountToBuy - _buyInAmount;
if (isSystemBet) {
marketRiskAmount = (marketRiskAmount * ONE * _systemBetDenominator) / (numOfMarkets * ONE);
}
if (isFutureOnParlay || _isInvalidCombinationOnTicket(_tradeData, marketTradeData, i)) {
riskStatus = ISportsAMMV2RiskManager.RiskStatus.InvalidCombination;
} else if (
_isRiskPerMarketAndPositionExceeded(marketTradeData, marketRiskAmount, _isLive) ||
_isRiskPerGameExceeded(marketTradeData, marketRiskAmount)
) {
isMarketOutOfLiquidity[i] = true;
// only set if no previous status was set
if (riskStatus == ISportsAMMV2RiskManager.RiskStatus.NoRisk) {
riskStatus = ISportsAMMV2RiskManager.RiskStatus.OutOfLiquidity;
}
}
}
}
/// @notice check limits for ticket
/// @param _buyInAmount ticket buy-in amount
/// @param _totalQuote ticket quote
/// @param _payout actual payout
/// @param _expectedPayout expected payout got from quote method
/// @param _additionalSlippage slippage tolerance
/// @param _ticketSize number of games in ticket
function checkLimits(
uint _buyInAmount,
uint _totalQuote,
uint _payout,
uint _expectedPayout,
uint _additionalSlippage,
uint _ticketSize
) external view {
// apply all checks
if (_buyInAmount < minBuyInAmount) revert LowBuyIn();
if (_totalQuote < maxSupportedOdds) revert ExceededMaxOdds();
if ((_payout - _buyInAmount) > maxSupportedAmount) revert ExceededMaxAmount();
if ((ONE * _expectedPayout) / _payout > ONE + _additionalSlippage) revert SlippageTooHigh();
if (_ticketSize > maxTicketSize) revert ExceededMaxSize();
}
/// @notice returns risk data for given sports and types
/// @param _sportIds sport IDs to get data for
/// @param _typeIds type IDs to get data for
/// @return riskData risk data
function getRiskData(
uint[] memory _sportIds,
uint[] memory _typeIds
) external view returns (ISportsAMMV2RiskManager.RiskData[] memory riskData) {
riskData = new ISportsAMMV2RiskManager.RiskData[](_sportIds.length);
for (uint i; i < _sportIds.length; ++i) {
uint sportId = _sportIds[i];
ISportsAMMV2RiskManager.TypeCap[] memory capPerType = new ISportsAMMV2RiskManager.TypeCap[](_typeIds.length);
for (uint j = 0; j < _typeIds.length; j++) {
uint typeId = _typeIds[j];
capPerType[j] = ISportsAMMV2RiskManager.TypeCap(typeId, capPerSportAndType[sportId][typeId]);
}
ISportsAMMV2RiskManager.CapData memory capData = ISportsAMMV2RiskManager.CapData(
capPerSport[sportId],
capPerSportChild[sportId],
capPerType
);
ISportsAMMV2RiskManager.DynamicLiquidityData memory dynamicLiquidityData = ISportsAMMV2RiskManager
.DynamicLiquidityData(
dynamicLiquidityCutoffTimePerSport[sportId],
dynamicLiquidityCutoffDividerPerSport[sportId]
);
riskData[i] = ISportsAMMV2RiskManager.RiskData(
sportId,
capData,
riskMultiplierPerSport[sportId],
dynamicLiquidityData
);
}
}
/**
* @notice Calculates the maximum system bet payout based on trade data, system bet denominator, and buy-in amount.
* @dev This function computes the payout for a system bet based on the provided data and conditions.
* @param _tradeData The array of trade data for the markets involved in the bet.
* @param _systemBetDenominator The system bet denominator to adjust the payout calculation.
* @param _buyInAmount The amount of collateral staked by the user in the system bet.
* @param _addedPayoutPercentage The bonus payout in case THALES is used
* @return systemBetPayout The calculated payout amount based on the input parameters.
* @return systemBetQuote The calculated quote odds based on the input parameters.
*/
function getMaxSystemBetPayout(
ISportsAMMV2.TradeData[] memory _tradeData,
uint8 _systemBetDenominator,
uint _buyInAmount,
uint _addedPayoutPercentage
) external view returns (uint systemBetPayout, uint systemBetQuote) {
uint8[][] memory systemCombinations = generateCombinations(uint8(_tradeData.length), _systemBetDenominator);
uint totalCombinations = systemCombinations.length;
if (totalCombinations > maxAllowedSystemCombinations) revert ExceededMaxCombinations();
uint buyinPerCombination = ((_buyInAmount * ONE) / totalCombinations) / ONE;
// Loop through each stored combination
for (uint i; i < totalCombinations; ++i) {
uint8[] memory currentCombination = systemCombinations[i];
uint combinationQuote;
for (uint8 j = 0; j < currentCombination.length; j++) {
uint8 marketIndex = currentCombination[j];
uint odds = _tradeData[marketIndex].odds[_tradeData[marketIndex].position];
odds = (odds * ONE) / ((ONE + _addedPayoutPercentage) - (_addedPayoutPercentage * odds) / ONE);
combinationQuote = combinationQuote == 0 ? odds : (combinationQuote * odds) / ONE;
}
if (combinationQuote > 0) {
uint combinationPayout = (buyinPerCombination * ONE) / combinationQuote;
systemBetPayout += combinationPayout;
}
}
systemBetQuote = (ONE * _buyInAmount) / systemBetPayout;
}
/* ========== SYSTEM BET UTILS ========== */
/**
* @notice Generates all unique combinations of size `k` from a set of integers {0, 1, ..., n-1}.
* @dev Uses `uint8` to reduce gas costs since `n` is guaranteed to be <= 15.
* @param n The size of the set (must be greater than `k`).
* @param k The size of each combination (must be greater than 1 and less than `n`).
* @return combinations A 2D array where each sub-array is a unique combination of `k` integers.
*/
function generateCombinations(uint8 n, uint8 k) public pure returns (uint8[][] memory) {
if (k <= 1 || k >= n) revert BadRangeForK();
// Calculate the number of combinations: n! / (k! * (n-k)!)
uint combinationsCount = 1;
for (uint8 i = 0; i < k; ++i) {
combinationsCount = (combinationsCount * (n - i)) / (i + 1);
}
// Initialize combinations array
uint8[][] memory combinations = new uint8[][](combinationsCount);
// Generate combinations
uint8[] memory indices = new uint8[](k);
for (uint8 i = 0; i < k; ++i) {
indices[i] = i;
}
uint index = 0;
while (true) {
// Add the current combination
uint8[] memory combination = new uint8[](k);
for (uint8 i = 0; i < k; ++i) {
combination[i] = indices[i];
}
combinations[index] = combination;
index++;
// Generate the next combination
bool done = true;
for (uint8 i = k; i > 0; i--) {
if (indices[i - 1] < n - (k - (i - 1))) {
indices[i - 1]++;
for (uint8 j = i; j < k; j++) {
indices[j] = indices[j - 1] + 1;
}
done = false;
break;
}
}
if (done) {
break;
}
}
return combinations;
}
/* ========== EXTERNAL WRITE FUNCTIONS ========== */
/// @notice check and update risks for ticket
/// @param _tradeData trade data with all market info needed for ticket
/// @param _buyInAmount ticket buy-in amount
/// @param _payout ticket _payout
/// @param _isLive whether this ticket is live
/// @param _systemBetDenominator in case of system bets, otherwise 0
/// @param _isSGP whether this ticket is SGP
function checkAndUpdateRisks(
ISportsAMMV2.TradeData[] memory _tradeData,
uint _buyInAmount,
uint _payout,
bool _isLive,
uint8 _systemBetDenominator,
bool _isSGP
) external onlySportsAMM(msg.sender) {
uint numOfMarkets = _tradeData.length;
for (uint i; i < numOfMarkets; ++i) {
ISportsAMMV2.TradeData memory marketTradeData = _tradeData[i];
if (isSportIdFuture[marketTradeData.sportId] && _tradeData.length > 1) {
revert CantParlayFutures();
}
uint[] memory odds = marketTradeData.odds;
uint8 position = marketTradeData.position;
if (odds.length <= position) revert InvalidPosition();
if (!_isMarketInAMMTrading(marketTradeData)) revert MarketNotTrading();
uint amountToBuy = odds[position] == 0 ? 0 : (ONE * _buyInAmount) / odds[position];
if (amountToBuy > _buyInAmount) {
uint marketRiskAmount = amountToBuy - _buyInAmount;
// for system bet
if (_systemBetDenominator > 1) {
marketRiskAmount = (marketRiskAmount * ONE * _systemBetDenominator) / (numOfMarkets * ONE);
_buyInAmount = (_buyInAmount * ONE * _systemBetDenominator) / (numOfMarkets * ONE);
}
if (_isRiskPerMarketAndPositionExceeded(marketTradeData, marketRiskAmount, _isLive))
revert ExceededMarketPositionRisk();
if (_isRiskPerGameExceeded(marketTradeData, marketRiskAmount)) revert ExceededGameRisk();
if (!_isSGP && _isInvalidCombinationOnTicket(_tradeData, marketTradeData, i)) revert InvalidCombination();
_updateRisk(marketTradeData, marketRiskAmount, _buyInAmount);
}
}
if (_isSGP) {
uint marketRiskAmount = _payout - _buyInAmount;
if (_isSGPRiskExceeded(_tradeData, marketRiskAmount)) revert ExceededSGPRisk();
sgpSpentOnGame[_tradeData[0].gameId] += marketRiskAmount;
sgpRiskPerCombination[getSGPHash(_tradeData)] += marketRiskAmount;
}
}
/// @notice verifies the merkle root is the one that is expected
/// @param _marketTradeData trade data with all market info needed for ticket
/// @param _rootPerGame to verify against
function verifyMerkleTree(ISportsAMMV2.TradeData memory _marketTradeData, bytes32 _rootPerGame) external pure {
_verifyMerkleTree(_marketTradeData, _rootPerGame);
}
/// @notice Batch verification of multiple market trade data against respective roots
/// @param _marketTradeData array of trade data with all market info needed for ticket
/// @param _rootPerGame array of merkle roots to verify against
function batchVerifyMerkleTree(
ISportsAMMV2.TradeData[] memory _marketTradeData,
bytes32[] memory _rootPerGame
) external pure {
if (_marketTradeData.length != _rootPerGame.length) revert MismatchedInputs();
for (uint i; i < _marketTradeData.length; ++i) {
_verifyMerkleTree(_marketTradeData[i], _rootPerGame[i]);
}
}
function _verifyMerkleTree(ISportsAMMV2.TradeData memory _marketTradeData, bytes32 _rootPerGame) internal pure {
bytes32 leaf = _computeMerkleLeaf(_marketTradeData);
require(MerkleProof.verify(_marketTradeData.merkleProof, _rootPerGame, leaf), "Proof is not valid");
}
/// @notice Computes the merkle leaf from trade data
/// @param _marketTradeData trade data with all market info needed for ticket
/// @return leaf computed merkle leaf
function _computeMerkleLeaf(ISportsAMMV2.TradeData memory _marketTradeData) private pure returns (bytes32) {
bytes memory encodePackedOutput = abi.encodePacked(
_marketTradeData.gameId,
uint(_marketTradeData.sportId),
uint(_marketTradeData.typeId),
_marketTradeData.maturity,
uint(_marketTradeData.status),
int(_marketTradeData.line),
uint(_marketTradeData.playerId),
_marketTradeData.odds
);
for (uint i; i < _marketTradeData.combinedPositions.length; ++i) {
for (uint j; j < _marketTradeData.combinedPositions[i].length; ++j) {
encodePackedOutput = abi.encodePacked(
encodePackedOutput,
uint(_marketTradeData.combinedPositions[i][j].typeId),
uint(_marketTradeData.combinedPositions[i][j].position),
int(_marketTradeData.combinedPositions[i][j].line)
);
}
}
return keccak256(encodePackedOutput);
}
/**
* @notice Reads the total risk stored for a given Same Game Parlay (SGP) combination.
* @dev Computes the SGP hash and retrieves the associated risk amount.
* @param trades The array of `TradeData` structs representing the parlay selections.
* @return uint The total risk amount associated with the given SGP.
*/
function getSGPCombinationRisk(ISportsAMMV2.TradeData[] memory trades) external view returns (uint) {
bytes32 sgpHash = getSGPHash(trades);
return sgpRiskPerCombination[sgpHash];
}
/* ========== INTERNAL FUNCTIONS ========== */
function _isMarketInAMMTrading(ISportsAMMV2.TradeData memory _marketTradeData) internal view returns (bool isTrading) {
uint maturity = _marketTradeData.maturity;
bool isResolved = resultManager.isMarketResolved(
_marketTradeData.gameId,
_marketTradeData.typeId,
_marketTradeData.playerId,
_marketTradeData.line,
_marketTradeData.combinedPositions[_marketTradeData.position]
);
if (_marketTradeData.status == 0 && !isResolved) {
if (maturity >= block.timestamp) {
isTrading = (maturity - block.timestamp) > minimalTimeLeftToMaturity;
}
}
}
function _isRiskPerMarketAndPositionExceeded(
ISportsAMMV2.TradeData memory _marketTradeData,
uint marketRiskAmount,
bool _isLive
) internal view returns (bool) {
bytes32 gameId = _marketTradeData.gameId;
uint16 typeId = _marketTradeData.typeId;
uint24 playerId = _marketTradeData.playerId;
return
riskPerMarketTypeAndPosition[gameId][typeId][playerId][_marketTradeData.position] + int(marketRiskAmount) >
int(
_calculateCapToBeUsed(
gameId,
_marketTradeData.sportId,
typeId,
playerId,
_marketTradeData.line,
_marketTradeData.maturity,
_isLive
)
);
}
function _isRiskPerGameExceeded(
ISportsAMMV2.TradeData memory _marketTradeData,
uint marketRiskAmount
) internal view returns (bool) {
bytes32 gameId = _marketTradeData.gameId;
(uint totalRisk, ) = _calculateTotalRiskOnGame(gameId, _marketTradeData.sportId, _marketTradeData.maturity);
return (spentOnGame[gameId] + marketRiskAmount) > totalRisk;
}
function _isSGPRiskExceeded(
ISportsAMMV2.TradeData[] memory _marketTradeData,
uint marketRiskAmount
) internal view returns (bool) {
uint sgpDividerToUse = sgpCapDivider > 0 ? sgpCapDivider : 2;
(uint totalRisk, uint capToBeUsed) = _calculateTotalRiskOnGame(
_marketTradeData[0].gameId,
_marketTradeData[0].sportId,
_marketTradeData[0].maturity
);
bool totalSGPRiskExceeded = (sgpSpentOnGame[_marketTradeData[0].gameId] + marketRiskAmount) >
(totalRisk / sgpDividerToUse);
// risk for a unique SGP combination cant exceed moneyline cap / sgpDivider
bool combinationSGPRiskExceeded = sgpRiskPerCombination[getSGPHash(_marketTradeData)] + marketRiskAmount >
(capToBeUsed / sgpDividerToUse);
return totalSGPRiskExceeded || combinationSGPRiskExceeded;
}
function _isInvalidCombinationOnTicket(
ISportsAMMV2.TradeData[] memory _tradeData,
ISportsAMMV2.TradeData memory _currentTradaData,
uint currentIndex
) internal view returns (bool isInvalid) {
for (uint j = currentIndex + 1; j < _tradeData.length; ++j) {
ISportsAMMV2.TradeData memory tradeDataToCheckAgainst = _tradeData[j];
if (
_currentTradaData.gameId == tradeDataToCheckAgainst.gameId &&
_currentTradaData.sportId == tradeDataToCheckAgainst.sportId
) {
if (
!combiningPerSportEnabled[_currentTradaData.sportId] ||
_currentTradaData.playerId == tradeDataToCheckAgainst.playerId ||
_currentTradaData.playerId == 0 ||
tradeDataToCheckAgainst.playerId == 0
) {
isInvalid = true;
break;
}
}
}
}
function _updateRisk(ISportsAMMV2.TradeData memory _marketTradeData, uint marketRiskAmount, uint _buyInAmount) internal {
bytes32 gameId = _marketTradeData.gameId;
uint16 typeId = _marketTradeData.typeId;
uint24 playerId = _marketTradeData.playerId;
uint8 position = _marketTradeData.position;
uint256 len = _marketTradeData.odds.length;
bool isBigMarket = len > 32;
for (uint256 j; j < len; ++j) {
int currentRisk = riskPerMarketTypeAndPosition[gameId][typeId][playerId][j];
if (j == position) {
// Selected position – always add risk
riskPerMarketTypeAndPosition[gameId][typeId][playerId][j] = currentRisk + int(marketRiskAmount);
} else {
// Small markets – keep old behavior (hedge on all positions) OR
// Big markets – only adjust if there was already some risk
if (!isBigMarket || currentRisk > 0) {
riskPerMarketTypeAndPosition[gameId][typeId][playerId][j] = currentRisk - int(_buyInAmount);
}
}
}
spentOnGame[gameId] += marketRiskAmount;
}
function _calculateRiskMultiplier(bytes32 _gameId, uint16 _sportId) internal view returns (uint gameRisk) {
gameRisk = riskMultiplierPerGame[_gameId];
if (gameRisk == 0) {
uint riskPerSport = riskMultiplierPerSport[_sportId];
gameRisk = riskPerSport > 0 ? riskPerSport : defaultRiskMultiplier;
}
}
function _calculateCapToBeUsed(
bytes32 _gameId,
uint16 _sportId,
uint16 _typeId,
uint24 _playerId,
int24 _line,
uint _maturity,
bool _isLive
) internal view returns (uint cap) {
if (_maturity > block.timestamp) {
cap = capPerMarket[_gameId][_typeId][_playerId][_line] > 0
? capPerMarket[_gameId][_typeId][_playerId][_line]
: capPerMarket[_gameId][_typeId][0][0];
if (cap == 0) {
uint sportCap = capPerSport[_sportId];
sportCap = sportCap > 0 ? sportCap : defaultCap;
cap = sportCap;
if (_typeId > 0) {
// Check for explicitly set moneyline market cap
uint typeCap = capPerSportAndType[_sportId][_typeId];
uint moneylineMarketCap = capPerMarket[_gameId][0][0][0];
if (moneylineMarketCap > 0) {
cap = (moneylineMarketCap / 2 < typeCap || typeCap == 0) ? moneylineMarketCap / 2 : typeCap;
} else {
cap = typeCap;
if (cap == 0) {
uint childCap = capPerSportChild[_sportId];
cap = childCap > 0 ? childCap : sportCap / 2;
}
}
}
}
if (_isLive) {
cap =
cap /
(
liveCapDividerPerSport[_sportId] > 0 ? liveCapDividerPerSport[_sportId] : defaultLiveCapDivider > 0
? defaultLiveCapDivider
: 1
);
}
uint dynamicLiquidityCutoffTime = dynamicLiquidityCutoffTimePerSport[_sportId];
if (dynamicLiquidityCutoffTime > 0) {
uint timeToStart = _maturity - block.timestamp;
uint cutOffLiquidity = (cap * ONE) /
(
dynamicLiquidityCutoffDividerPerSport[_sportId] > 0
? dynamicLiquidityCutoffDividerPerSport[_sportId]
: DEFAULT_DYNAMIC_LIQUIDITY_CUTOFF_DIVIDER
);
if (timeToStart >= dynamicLiquidityCutoffTime) {
cap = cutOffLiquidity;
} else {
uint remainingFromCutOff = cap - cutOffLiquidity;
cap =
cutOffLiquidity +
(((dynamicLiquidityCutoffTime - timeToStart) * remainingFromCutOff) / dynamicLiquidityCutoffTime);
}
}
}
}
function _calculateTotalRiskOnGame(
bytes32 _gameId,
uint16 _sportId,
uint _maturity
) internal view returns (uint totalRisk, uint capToBeUsed) {
// get cap for parent market
capToBeUsed = _calculateCapToBeUsed(_gameId, _sportId, 0, 0, 0, _maturity, false);
totalRisk = (capToBeUsed * _calculateRiskMultiplier(_gameId, _sportId));
}
/* ========== SETTERS ========== */
/// @notice sets whether props SGPs are allowed on the given sport
/// @param _sportID sport to set enabled for
/// @param _enabled true/false
function setCombiningPerSportEnabled(uint _sportID, bool _enabled) external onlyOwner {
combiningPerSportEnabled[_sportID] = _enabled;
emit SetCombiningPerSportEnabled(_sportID, _enabled);
}
/// @notice sets the max cap and max risk multiplier
/// @param _maxCap max cap
/// @param _maxRiskMultiplier max risk multiplier
function setMaxCapAndMaxRiskMultiplier(uint _maxCap, uint _maxRiskMultiplier) external onlyOwner {
if (_maxCap <= defaultCap || _maxRiskMultiplier <= defaultRiskMultiplier) revert InvalidInput();
maxCap = _maxCap;
maxRiskMultiplier = _maxRiskMultiplier;
emit SetMaxCapAndMaxRiskMultiplier(_maxCap, _maxRiskMultiplier);
}
/// @notice sets the default cap and default risk multiplier
/// @param _defaultCap default cap
/// @param _defaultRiskMultiplier default risk multiplier
function setDefaultCapAndDefaultRiskMultiplier(uint _defaultCap, uint _defaultRiskMultiplier) external onlyOwner {
if (_defaultCap > maxCap || _defaultRiskMultiplier > maxRiskMultiplier) revert InvalidInput();
defaultCap = _defaultCap;
defaultRiskMultiplier = _defaultRiskMultiplier;
emit SetDefaultCapAndDefaultRiskMultiplier(_defaultCap, _defaultRiskMultiplier);
}
/// @notice sets the cap per sport (batch)
/// @param _sportIds sport IDs to set cap for
/// @param _capsPerSport the cap amounts
function setCapsPerSport(
uint[] memory _sportIds,
uint[] memory _capsPerSport
) external onlyWhitelistedAddresses(msg.sender) {
for (uint i; i < _sportIds.length; ++i) {
_setCapPerSport(_sportIds[i], _capsPerSport[i]);
}
}
/// @notice sets the cap per all child markets of specific sport (batch)
/// @param _sportIds sport IDs to set cap for
/// @param _capsPerSportChild the cap amounts
function setCapsPerSportChild(
uint[] memory _sportIds,
uint[] memory _capsPerSportChild
) external onlyWhitelistedAddresses(msg.sender) {
for (uint i; i < _sportIds.length; ++i) {
_setCapPerSportChild(_sportIds[i], _capsPerSportChild[i]);
}
}
/// @notice sets the cap per sport and type (batch)
/// @param _sportIds sport IDs to set cap for
/// @param _typeIds type IDs to set cap for
/// @param _capsPerType the cap amounts
function setCapsPerSportAndType(
uint[] memory _sportIds,
uint[] memory _typeIds,
uint[] memory _capsPerType
) external onlyWhitelistedAddresses(msg.sender) {
for (uint i; i < _sportIds.length; ++i) {
_setCapPerSportAndType(_sportIds[i], _typeIds[i], _capsPerType[i]);
}
}
/// @notice sets the caps per specific markets
/// @param _gameIds game IDs to set cap for
/// @param _typeIds type IDs to set cap for
/// @param _playerIds player IDs to set cap for
/// @param _lines lines to set cap for
/// @param _capsPerMarket the cap amounts
function setCapsPerMarket(
bytes32[] memory _gameIds,
uint16[] memory _typeIds,
uint24[] memory _playerIds,
int24[] memory _lines,
uint[] memory _capsPerMarket
) external onlyWhitelistedAddresses(msg.sender) {
for (uint i; i < _gameIds.length; ++i) {
if (_capsPerMarket[i] > maxCap) revert InvalidCap();
capPerMarket[_gameIds[i]][_typeIds[i]][_playerIds[i]][_lines[i]] = _capsPerMarket[i];
emit SetCapPerMarket(_gameIds[i], _typeIds[i], _playerIds[i], _lines[i], _capsPerMarket[i]);
}
}
/// @notice sets the cap per sport, cap per sport child and cap per sport and type (batch)
/// @param _sportIds sport IDs to set cap for
/// @param _capsPerSport the cap amounts used for the sport IDs
/// @param _sportIdsForChild sport IDs to set child cap for
/// @param _capsPerSportChild the cap amounts used for the sport child markets
/// @param _sportIdsForType sport IDs to set type cap for
/// @param _typeIds type IDs to set cap for
/// @param _capsPerSportAndType the cap amounts used for the sport IDs and type IDs
function setCaps(
uint[] memory _sportIds,
uint[] memory _capsPerSport,
uint[] memory _sportIdsForChild,
uint[] memory _capsPerSportChild,
uint[] memory _sportIdsForType,
uint[] memory _typeIds,
uint[] memory _capsPerSportAndType
) external onlyWhitelistedAddresses(msg.sender) {
for (uint i; i < _sportIds.length; ++i) {
_setCapPerSport(_sportIds[i], _capsPerSport[i]);
}
for (uint i; i < _sportIdsForChild.length; ++i) {
_setCapPerSportChild(_sportIdsForChild[i], _capsPerSportChild[i]);
}
for (uint i; i < _sportIdsForType.length; ++i) {
_setCapPerSportAndType(_sportIdsForType[i], _typeIds[i], _capsPerSportAndType[i]);
}
}
/// @notice sets the risk multiplier per sport (batch)
/// @param _sportIds sport IDs to set risk multiplier for
/// @param _riskMultipliersPerSport the risk multiplier amounts
function setRiskMultipliersPerSport(
uint[] memory _sportIds,
uint[] memory _riskMultipliersPerSport
) external onlyWhitelistedAddresses(msg.sender) {
for (uint i; i < _sportIds.length; ++i) {
if (_riskMultipliersPerSport[i] > maxRiskMultiplier) revert MultiplierTooHigh();
riskMultiplierPerSport[_sportIds[i]] = _riskMultipliersPerSport[i];
emit SetRiskMultiplierPerSport(_sportIds[i], _riskMultipliersPerSport[i]);
}
}
/// @notice sets the risk multiplier per spec. games
/// @param _gameIds game IDs to set risk multiplier for
/// @param _riskMultipliersPerGame the risk multiplier amounts used for the specific games
function setRiskMultipliersPerGame(
bytes32[] memory _gameIds,
uint[] memory _riskMultipliersPerGame
) external onlyWhitelistedAddresses(msg.sender) {
for (uint i; i < _gameIds.length; ++i) {
if (_riskMultipliersPerGame[i] > maxRiskMultiplier) revert MultiplierTooHigh();
riskMultiplierPerGame[_gameIds[i]] = _riskMultipliersPerGame[i];
emit SetRiskMultiplierPerGame(_gameIds[i], _riskMultipliersPerGame[i]);
}
}
/// @notice sets the dynamic liquidity params
/// @param _sportId the ID used for sport
/// @param _dynamicLiquidityCutoffTime when to start increasing the liquidity linearly, if 0 assume 100% liquidity all the time since game creation
/// @param _dynamicLiquidityCutoffDivider e.g. if 2 it means liquidity up until cut off time is 50%, then increases linearly. if 0 use default
function setDynamicLiquidityParamsPerSport(
uint _sportId,
uint _dynamicLiquidityCutoffTime,
uint _dynamicLiquidityCutoffDivider
) external onlyWhitelistedAddresses(msg.sender) {
dynamicLiquidityCutoffTimePerSport[_sportId] = _dynamicLiquidityCutoffTime;
dynamicLiquidityCutoffDividerPerSport[_sportId] = _dynamicLiquidityCutoffDivider;
emit SetDynamicLiquidityParams(_sportId, _dynamicLiquidityCutoffTime, _dynamicLiquidityCutoffDivider);
}
/// @notice Sets the contract addresses for manager, result manager, and sports AMM
/// @param _manager The address of the SportsAMMV2Manager contract
/// @param _resultManager The address of the SportsAMMV2ResultManager contract
/// @param _sportsAMM The address of the SportsAMMV2 contract
function setAddresses(address _manager, address _resultManager, address _sportsAMM) external onlyOwner {
if (_manager == address(0) || _resultManager == address(0) || _sportsAMM == address(0)) revert InvalidAddress();
manager = ISportsAMMV2Manager(_manager);
resultManager = ISportsAMMV2ResultManager(_resultManager);
sportsAMM = ISportsAMMV2(_sportsAMM);
emit SetAddresses(_manager, _resultManager, _sportsAMM);
}
/// @notice Setting whether live trading per sport is enabled
/// @param _sportId to set live trading for
/// @param _typeId to set live trading for
/// @param _enabled self explanatory
function setLiveTradingPerSportAndTypeEnabled(uint _sportId, uint _typeId, bool _enabled) external onlyOwner {
_setLiveTradingPerSportAndTypeEnabled(_sportId, _typeId, _enabled);
}
/// @notice Setting whether live trading per sports is enabled
/// @param _sportIds to set live trading for
/// @param _typeIds to set live trading for
/// @param _enabled self explanatory
function setBatchLiveTradingPerSportAndTypeEnabled(
uint[] calldata _sportIds,
uint[] calldata _typeIds,
bool _enabled
) external onlyOwner {
if (_sportIds.length == 0 || _typeIds.length == 0) revert EmptyArrays();
for (uint index = 0; index < _sportIds.length; index++) {
uint _sportId = _sportIds[index];
for (uint indexType = 0; indexType < _typeIds.length; indexType++) {
uint _typeId = _typeIds[indexType];
_setLiveTradingPerSportAndTypeEnabled(_sportId, _typeId, _enabled);
}
}
}
function _setLiveTradingPerSportAndTypeEnabled(uint _sportId, uint _typeId, bool _enabled) internal {
liveTradingPerSportAndTypeEnabled[_sportId][_typeId] = _enabled;
emit SetLiveTradingPerSportAndTypeEnabled(_sportId, _typeId, _enabled);
}
/// @notice sets different ticket parameters
/// @param _minBuyInAmount minimum ticket buy-in amount
/// @param _maxTicketSize maximum ticket size
/// @param _maxSupportedAmount maximum supported payout amount
/// @param _maxSupportedOdds maximum supported ticket odds
function setTicketParams(
uint _minBuyInAmount,
uint _maxTicketSize,
uint _maxSupportedAmount,
uint _maxSupportedOdds,
uint _maxAllowedSystemCombinations
) external onlyOwner {
minBuyInAmount = _minBuyInAmount;
maxTicketSize = _maxTicketSize;
maxSupportedAmount = _maxSupportedAmount;
maxSupportedOdds = _maxSupportedOdds;
maxAllowedSystemCombinations = _maxAllowedSystemCombinations;
emit TicketParamsUpdated(
_minBuyInAmount,
_maxTicketSize,
_maxSupportedAmount,
_maxSupportedOdds,
_maxAllowedSystemCombinations
);
}
/// @notice sets different times/periods
/// @param _minimalTimeLeftToMaturity the period of time in seconds before a game is matured and begins to be restricted for AMM trading
/// @param _expiryDuration the period of time in seconds after mauturity when ticket expires
function setTimes(uint _minimalTimeLeftToMaturity, uint _expiryDuration) external onlyOwner {
minimalTimeLeftToMaturity = _minimalTimeLeftToMaturity;
expiryDuration = _expiryDuration;
emit TimesUpdated(_minimalTimeLeftToMaturity, _expiryDuration);
}
/// @notice sets divider to reduce live cap for sport by
/// @param _divider to reduce live cap for sport by
function setLiveCapDivider(uint _sportId, uint _divider) external onlyWhitelistedAddresses(msg.sender) {
if (_divider == 0 || _divider > 10) revert DividerOutOfRange();
liveCapDividerPerSport[_sportId] = _divider;
emit SetLiveCapDivider(_sportId, _divider);
}
/// @notice sets divider to reduce live cap for sport by
/// @param _divider to reduce live cap for sport by
function setDefaultLiveCapDivider(uint _divider) external onlyWhitelistedAddresses(msg.sender) {
if (_divider == 0 || _divider > 10) revert DividerOutOfRange();
defaultLiveCapDivider = _divider;
emit SetDefaultLiveCapDivider(_divider);
}
/// @notice sets divider to reduce prematch sgp cap for
/// @param _divider to reduce prematch sgp cap for
function setSGPCapDivider(uint _divider) external onlyWhitelistedAddresses(msg.sender) {
if (_divider == 0 || _divider > 10) revert DividerOutOfRange();
sgpCapDivider = _divider;
emit SetSGPCapDivider(_divider);
}
/// @notice sets whether a sportsId is future
/// @param _sportId to set whether is a future
/// @param _isFuture boolean representing whether the given _sportId should be treated as a future
function setIsSportIdFuture(uint16 _sportId, bool _isFuture) external onlyWhitelistedAddresses(msg.sender) {
isSportIdFuture[_sportId] = _isFuture;
emit SetIsSportIdFuture(_sportId, _isFuture);
}
/// @notice sets whether a sportsId has SGP enabled
/// @param _sportIds to set whether SGP enabled
/// @param _isEnabled boolean representing whether the given _sportId should have SGPs enabled
function setSGPEnabledOnSportIds(uint16[] calldata _sportIds, bool _isEnabled) external onlyOwner {
for (uint index = 0; index < _sportIds.length; index++) {
uint16 _sportId = _sportIds[index];
sgpOnSportIdEnabled[_sportId] = _isEnabled;
emit SetSGPEnabledOnSport(_sportId, _isEnabled);
}
}
/* ========== INTERNAL SETTERS ========== */
function _setCapPerSport(uint _sportId, uint _capPerSport) internal {
if (_capPerSport > maxCap) revert InvalidCap();
capPerSport[_sportId] = _capPerSport;
emit SetCapPerSport(_sportId, _capPerSport);
}
function _setCapPerSportChild(uint _sportId, uint _capPerSportChild) internal {
uint currentCapPerSport = capPerSport[_sportId] > 0 ? capPerSport[_sportId] : defaultCap;
if (_capPerSportChild > currentCapPerSport) revert InvalidCap();
capPerSportChild[_sportId] = _capPerSportChild;
emit SetCapPerSportChild(_sportId, _capPerSportChild);
}
function _setCapPerSportAndType(uint _sportId, uint _typeId, uint _capPerType) internal {
uint currentCapPerSport = capPerSport[_sportId] > 0 ? capPerSport[_sportId] : defaultCap;
if (_capPerType > currentCapPerSport) revert InvalidCap();
capPerSportAndType[_sportId][_typeId] = _capPerType;
emit SetCapPerSportAndType(_sportId, _typeId, _capPerType);
}
/**
* @notice Computes a unique hash for a Same Game Parlay (SGP) using only relevant fields.
* @dev Extracts `gameId`, `typeId`, and `playerId` from the `TradeData` struct and hashes them.
* @param trades The array of `TradeData` structs representing the parlay selections.
* @return bytes32 A unique hash representing the SGP combination.
*/
function getSGPHash(ISportsAMMV2.TradeData[] memory trades) public pure returns (bytes32) {
// Sort trades based on (typeId, playerId and lineId)
_sortSGPLegs(trades);
bytes32[] memory gameIds = new bytes32[](trades.length);
uint16[] memory typeIds = new uint16[](trades.length);
uint24[] memory playerIds = new uint24[](trades.length);
for (uint i; i < trades.length; ++i) {
gameIds[i] = trades[i].gameId;
typeIds[i] = trades[i].typeId;
playerIds[i] = trades[i].playerId;
}
return keccak256(abi.encode(gameIds, typeIds, playerIds));
}
function _sortSGPLegs(ISportsAMMV2.TradeData[] memory trades) internal pure {
uint256 length = trades.length;
for (uint256 i = 0; i < length - 1; ++i) {
for (uint256 j = i + 1; j < length; j++) {
if (_compareSGPLegs(trades[i], trades[j]) > 0) {
// Swap trades[i] and trades[j]
(trades[i], trades[j]) = (trades[j], trades[i]);
}
}
}
}
function _compareSGPLegs(ISportsAMMV2.TradeData memory a, ISportsAMMV2.TradeData memory b) internal pure returns (int) {
if (a.typeId < b.typeId) return -1;
if (a.typeId > b.typeId) return 1;
if (a.playerId < b.playerId) return -1;
if (a.playerId > b.playerId) return 1;
if (a.line < b.line) return -1;
if (a.line > b.line) return 1;
return 0;
}
/* ========== MODIFIERS ========== */
modifier onlyWhitelistedAddresses(address sender) {
require(
sender == owner || manager.isWhitelistedAddress(sender, ISportsAMMV2Manager.Role.RISK_MANAGING),
"InvalidSender"
);
_;
}
modifier onlySportsAMM(address sender) {
require(sender == address(sportsAMM), "OnlyAMMAllowed");
_;
}
/* ========== EVENTS ========== */
event SetMaxCapAndMaxRiskMultiplier(uint maxCap, uint maxRiskMultiplier);
event SetDefaultCapAndDefaultRiskMultiplier(uint defaultCap, uint defaultRiskMultiplier);
event SetCapPerSport(uint sportId, uint cap);
event SetCapPerSportChild(uint sportId, uint cap);
event SetCapPerSportAndType(uint sportId, uint typeId, uint cap);
event SetCapPerMarket(bytes32 gameId, uint16 typeId, uint24 playerId, int24 line, uint cap);
event SetRiskMultiplierPerSport(uint sportId, uint riskMultiplier);
event SetRiskMultiplierPerGame(bytes32 gameId, uint riskMultiplier);
event SetDynamicLiquidityParams(uint sportId, uint dynamicLiquidityCutoffTime, uint dynamicLiquidityCutoffDivider);
event SetAddresses(address _manager, address _resultManager, address _sportsAMM);
event SetLiveTradingPerSportAndTypeEnabled(uint _sportId, uint _typeId, bool _enabled);
event SetCombiningPerSportEnabled(uint _sportID, bool _enabled);
event TicketParamsUpdated(
uint minBuyInAmount,
uint maxTicketSize,
uint maxSupportedAmount,
uint maxSupportedOdds,
uint maxAllowedSystemCombinations
);
event TimesUpdated(uint minimalTimeLeftToMaturity, uint expiryDuration);
event SetLiveCapDivider(uint _sportId, uint _divider);
event SetDefaultLiveCapDivider(uint _divider);
event SetSGPCapDivider(uint _divider);
event SetIsSportIdFuture(uint16 _sportId, bool _isFuture);
event SetSGPEnabledOnSport(uint16 _sportId, bool _isEnabled);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}// 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) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.20;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the Merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates Merkle trees that are safe
* against this attack out of the box.
*/
library MerkleProof {
/**
*@dev The multiproof provided is not valid.
*/
error MerkleProofInvalidMultiproof();
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*/
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Sorts the pair (a, b) and hashes the result.
*/
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
/**
* @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
*/
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IProxyBetting.sol";
interface IFreeBetsHolder is IProxyBetting {
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);
}// 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;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Clone of syntetix contract without constructor
contract ProxyOwned {
address public owner;
address public nominatedOwner;
bool private _initialized;
bool private _transferredAtInit;
function setOwner(address _owner) public {
require(_owner != address(0), "Owner address cannot be 0");
require(!_initialized, "Already initialized, use nominateNewOwner");
_initialized = true;
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
function transferOwnershipAtInit(address proxyAddress) external onlyOwner {
require(proxyAddress != address(0), "Invalid address");
require(!_transferredAtInit, "Already transferred");
owner = proxyAddress;
_transferredAtInit = true;
emit OwnerChanged(owner, proxyAddress);
}
modifier onlyOwner() {
_onlyOwner();
_;
}
function _onlyOwner() private view {
require(msg.sender == owner, "Only the contract owner may perform this action");
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Inheritance
import "./ProxyOwned.sol";
// Clone of syntetix contract without constructor
contract ProxyPausable is ProxyOwned {
uint public lastPauseTime;
bool public paused;
/**
* @notice Change the paused state of the contract
* @dev Only the contract owner may call this.
*/
function setPaused(bool _paused) external onlyOwner {
// Ensure we're actually changing the state before we do anything
if (_paused == paused) {
return;
}
// Set our paused state.
paused = _paused;
// If applicable, set the last pause time.
if (paused) {
lastPauseTime = block.timestamp;
}
// Let everyone know that our pause state has changed.
emit PauseChanged(paused);
}
event PauseChanged(bool isPaused);
modifier notPaused() {
require(!paused, "This action cannot be performed while the contract is paused");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier
* available, which can be aplied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*/
contract ProxyReentrancyGuard {
/// @dev counter to allow mutex lock with only one SSTORE operation
uint256 private _guardCounter;
bool private _initialized;
function initNonReentrant() public {
require(!_initialized, "Already initialized");
_initialized = true;
_guardCounter = 1;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_guardCounter += 1;
uint256 localCounter = _guardCounter;
_;
require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
}
}{
"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":[],"name":"BadRangeForK","type":"error"},{"inputs":[],"name":"CantParlayFutures","type":"error"},{"inputs":[],"name":"DividerOutOfRange","type":"error"},{"inputs":[],"name":"EmptyArrays","type":"error"},{"inputs":[],"name":"ExceededGameRisk","type":"error"},{"inputs":[],"name":"ExceededMarketPositionRisk","type":"error"},{"inputs":[],"name":"ExceededMaxAmount","type":"error"},{"inputs":[],"name":"ExceededMaxCombinations","type":"error"},{"inputs":[],"name":"ExceededMaxOdds","type":"error"},{"inputs":[],"name":"ExceededMaxSize","type":"error"},{"inputs":[],"name":"ExceededSGPRisk","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidCap","type":"error"},{"inputs":[],"name":"InvalidCombination","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidOdds","type":"error"},{"inputs":[],"name":"InvalidPosition","type":"error"},{"inputs":[],"name":"LowBuyIn","type":"error"},{"inputs":[],"name":"MarketNotTrading","type":"error"},{"inputs":[],"name":"MismatchedInputs","type":"error"},{"inputs":[],"name":"MultiplierTooHigh","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"SlippageTooHigh","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PauseChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_manager","type":"address"},{"indexed":false,"internalType":"address","name":"_resultManager","type":"address"},{"indexed":false,"internalType":"address","name":"_sportsAMM","type":"address"}],"name":"SetAddresses","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"gameId","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"typeId","type":"uint16"},{"indexed":false,"internalType":"uint24","name":"playerId","type":"uint24"},{"indexed":false,"internalType":"int24","name":"line","type":"int24"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"SetCapPerMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sportId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"SetCapPerSport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sportId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"typeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"SetCapPerSportAndType","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sportId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"SetCapPerSportChild","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sportID","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_enabled","type":"bool"}],"name":"SetCombiningPerSportEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"defaultCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"defaultRiskMultiplier","type":"uint256"}],"name":"SetDefaultCapAndDefaultRiskMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_divider","type":"uint256"}],"name":"SetDefaultLiveCapDivider","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sportId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dynamicLiquidityCutoffTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dynamicLiquidityCutoffDivider","type":"uint256"}],"name":"SetDynamicLiquidityParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_sportId","type":"uint16"},{"indexed":false,"internalType":"bool","name":"_isFuture","type":"bool"}],"name":"SetIsSportIdFuture","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sportId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_divider","type":"uint256"}],"name":"SetLiveCapDivider","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sportId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_typeId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_enabled","type":"bool"}],"name":"SetLiveTradingPerSportAndTypeEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxRiskMultiplier","type":"uint256"}],"name":"SetMaxCapAndMaxRiskMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"gameId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"riskMultiplier","type":"uint256"}],"name":"SetRiskMultiplierPerGame","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sportId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"riskMultiplier","type":"uint256"}],"name":"SetRiskMultiplierPerSport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_divider","type":"uint256"}],"name":"SetSGPCapDivider","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_sportId","type":"uint16"},{"indexed":false,"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"SetSGPEnabledOnSport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minBuyInAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxTicketSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxSupportedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxSupportedOdds","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxAllowedSystemCombinations","type":"uint256"}],"name":"TicketParamsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minimalTimeLeftToMaturity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiryDuration","type":"uint256"}],"name":"TimesUpdated","type":"event"},{"inputs":[],"name":"DEFAULT_DYNAMIC_LIQUIDITY_CUTOFF_DIVIDER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint256[]","name":"odds","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint8","name":"position","type":"uint8"},{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[][]","name":"combinedPositions","type":"tuple[][]"}],"internalType":"struct ISportsAMMV2.TradeData[]","name":"_marketTradeData","type":"tuple[]"},{"internalType":"bytes32[]","name":"_rootPerGame","type":"bytes32[]"}],"name":"batchVerifyMerkleTree","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"},{"internalType":"uint16","name":"_sportId","type":"uint16"},{"internalType":"uint16","name":"_typeId","type":"uint16"},{"internalType":"uint24","name":"_playerId","type":"uint24"},{"internalType":"int24","name":"_line","type":"int24"},{"internalType":"uint256","name":"_maturity","type":"uint256"},{"internalType":"bool","name":"_isLive","type":"bool"}],"name":"calculateCapToBeUsed","outputs":[{"internalType":"uint256","name":"cap","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"},{"internalType":"uint16","name":"_sportId","type":"uint16"},{"internalType":"uint256","name":"_maturity","type":"uint256"}],"name":"calculateTotalRiskOnGame","outputs":[{"internalType":"uint256","name":"totalRisk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"int256","name":"","type":"int256"}],"name":"capPerMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"capPerSport","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"capPerSportAndType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"capPerSportChild","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint256[]","name":"odds","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint8","name":"position","type":"uint8"},{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[][]","name":"combinedPositions","type":"tuple[][]"}],"internalType":"struct ISportsAMMV2.TradeData[]","name":"_tradeData","type":"tuple[]"},{"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"internalType":"uint256","name":"_payout","type":"uint256"},{"internalType":"bool","name":"_isLive","type":"bool"},{"internalType":"uint8","name":"_systemBetDenominator","type":"uint8"},{"internalType":"bool","name":"_isSGP","type":"bool"}],"name":"checkAndUpdateRisks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"internalType":"uint256","name":"_totalQuote","type":"uint256"},{"internalType":"uint256","name":"_payout","type":"uint256"},{"internalType":"uint256","name":"_expectedPayout","type":"uint256"},{"internalType":"uint256","name":"_additionalSlippage","type":"uint256"},{"internalType":"uint256","name":"_ticketSize","type":"uint256"}],"name":"checkLimits","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint256[]","name":"odds","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint8","name":"position","type":"uint8"},{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[][]","name":"combinedPositions","type":"tuple[][]"}],"internalType":"struct ISportsAMMV2.TradeData[]","name":"_tradeData","type":"tuple[]"},{"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"internalType":"bool","name":"_isLive","type":"bool"},{"internalType":"uint8","name":"_systemBetDenominator","type":"uint8"}],"name":"checkRisks","outputs":[{"internalType":"enum ISportsAMMV2RiskManager.RiskStatus","name":"riskStatus","type":"uint8"},{"internalType":"bool[]","name":"isMarketOutOfLiquidity","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"combiningPerSportEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultLiveCapDivider","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultRiskMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dynamicLiquidityCutoffDividerPerSport","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dynamicLiquidityCutoffTimePerSport","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expiryDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"n","type":"uint8"},{"internalType":"uint8","name":"k","type":"uint8"}],"name":"generateCombinations","outputs":[{"internalType":"uint8[][]","name":"","type":"uint8[][]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint256[]","name":"odds","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint8","name":"position","type":"uint8"},{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[][]","name":"combinedPositions","type":"tuple[][]"}],"internalType":"struct ISportsAMMV2.TradeData[]","name":"_tradeData","type":"tuple[]"},{"internalType":"uint8","name":"_systemBetDenominator","type":"uint8"},{"internalType":"uint256","name":"_buyInAmount","type":"uint256"},{"internalType":"uint256","name":"_addedPayoutPercentage","type":"uint256"}],"name":"getMaxSystemBetPayout","outputs":[{"internalType":"uint256","name":"systemBetPayout","type":"uint256"},{"internalType":"uint256","name":"systemBetQuote","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_sportIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_typeIds","type":"uint256[]"}],"name":"getRiskData","outputs":[{"components":[{"internalType":"uint256","name":"sportId","type":"uint256"},{"components":[{"internalType":"uint256","name":"capPerSport","type":"uint256"},{"internalType":"uint256","name":"capPerChild","type":"uint256"},{"components":[{"internalType":"uint256","name":"typeId","type":"uint256"},{"internalType":"uint256","name":"cap","type":"uint256"}],"internalType":"struct ISportsAMMV2RiskManager.TypeCap[]","name":"capPerType","type":"tuple[]"}],"internalType":"struct ISportsAMMV2RiskManager.CapData","name":"capData","type":"tuple"},{"internalType":"uint256","name":"riskMultiplierPerSport","type":"uint256"},{"components":[{"internalType":"uint256","name":"cutoffTimePerSport","type":"uint256"},{"internalType":"uint256","name":"cutoffDividerPerSport","type":"uint256"}],"internalType":"struct ISportsAMMV2RiskManager.DynamicLiquidityData","name":"dynamicLiquidityData","type":"tuple"}],"internalType":"struct ISportsAMMV2RiskManager.RiskData[]","name":"riskData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint256[]","name":"odds","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint8","name":"position","type":"uint8"},{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[][]","name":"combinedPositions","type":"tuple[][]"}],"internalType":"struct ISportsAMMV2.TradeData[]","name":"trades","type":"tuple[]"}],"name":"getSGPCombinationRisk","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint256[]","name":"odds","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint8","name":"position","type":"uint8"},{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[][]","name":"combinedPositions","type":"tuple[][]"}],"internalType":"struct ISportsAMMV2.TradeData[]","name":"trades","type":"tuple[]"}],"name":"getSGPHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"initNonReentrant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract ISportsAMMV2Manager","name":"_manager","type":"address"},{"internalType":"contract ISportsAMMV2ResultManager","name":"_resultManager","type":"address"},{"internalType":"uint256","name":"_defaultCap","type":"uint256"},{"internalType":"uint256","name":"_defaultRiskMultiplier","type":"uint256"},{"internalType":"uint256","name":"_maxCap","type":"uint256"},{"internalType":"uint256","name":"_maxRiskMultiplier","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"isSportIdFuture","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"liveCapDividerPerSport","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"liveTradingPerSportAndTypeEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"contract ISportsAMMV2Manager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAllowedSystemCombinations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRiskMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupportedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupportedOdds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTicketSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minBuyInAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimalTimeLeftToMaturity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resultManager","outputs":[{"internalType":"contract ISportsAMMV2ResultManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"riskMultiplierPerGame","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"riskMultiplierPerSport","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"riskPerMarketTypeAndPosition","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"address","name":"_resultManager","type":"address"},{"internalType":"address","name":"_sportsAMM","type":"address"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_sportIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_typeIds","type":"uint256[]"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setBatchLiveTradingPerSportAndTypeEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_sportIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_capsPerSport","type":"uint256[]"},{"internalType":"uint256[]","name":"_sportIdsForChild","type":"uint256[]"},{"internalType":"uint256[]","name":"_capsPerSportChild","type":"uint256[]"},{"internalType":"uint256[]","name":"_sportIdsForType","type":"uint256[]"},{"internalType":"uint256[]","name":"_typeIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_capsPerSportAndType","type":"uint256[]"}],"name":"setCaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_gameIds","type":"bytes32[]"},{"internalType":"uint16[]","name":"_typeIds","type":"uint16[]"},{"internalType":"uint24[]","name":"_playerIds","type":"uint24[]"},{"internalType":"int24[]","name":"_lines","type":"int24[]"},{"internalType":"uint256[]","name":"_capsPerMarket","type":"uint256[]"}],"name":"setCapsPerMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_sportIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_capsPerSport","type":"uint256[]"}],"name":"setCapsPerSport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_sportIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_typeIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_capsPerType","type":"uint256[]"}],"name":"setCapsPerSportAndType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_sportIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_capsPerSportChild","type":"uint256[]"}],"name":"setCapsPerSportChild","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sportID","type":"uint256"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setCombiningPerSportEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_defaultCap","type":"uint256"},{"internalType":"uint256","name":"_defaultRiskMultiplier","type":"uint256"}],"name":"setDefaultCapAndDefaultRiskMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_divider","type":"uint256"}],"name":"setDefaultLiveCapDivider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sportId","type":"uint256"},{"internalType":"uint256","name":"_dynamicLiquidityCutoffTime","type":"uint256"},{"internalType":"uint256","name":"_dynamicLiquidityCutoffDivider","type":"uint256"}],"name":"setDynamicLiquidityParamsPerSport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_sportId","type":"uint16"},{"internalType":"bool","name":"_isFuture","type":"bool"}],"name":"setIsSportIdFuture","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sportId","type":"uint256"},{"internalType":"uint256","name":"_divider","type":"uint256"}],"name":"setLiveCapDivider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sportId","type":"uint256"},{"internalType":"uint256","name":"_typeId","type":"uint256"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setLiveTradingPerSportAndTypeEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxCap","type":"uint256"},{"internalType":"uint256","name":"_maxRiskMultiplier","type":"uint256"}],"name":"setMaxCapAndMaxRiskMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_gameIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"_riskMultipliersPerGame","type":"uint256[]"}],"name":"setRiskMultipliersPerGame","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_sportIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_riskMultipliersPerSport","type":"uint256[]"}],"name":"setRiskMultipliersPerSport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_divider","type":"uint256"}],"name":"setSGPCapDivider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"_sportIds","type":"uint16[]"},{"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"setSGPEnabledOnSportIds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minBuyInAmount","type":"uint256"},{"internalType":"uint256","name":"_maxTicketSize","type":"uint256"},{"internalType":"uint256","name":"_maxSupportedAmount","type":"uint256"},{"internalType":"uint256","name":"_maxSupportedOdds","type":"uint256"},{"internalType":"uint256","name":"_maxAllowedSystemCombinations","type":"uint256"}],"name":"setTicketParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimalTimeLeftToMaturity","type":"uint256"},{"internalType":"uint256","name":"_expiryDuration","type":"uint256"}],"name":"setTimes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sgpCapDivider","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"sgpOnSportIdEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"sgpRiskPerCombination","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"sgpSpentOnGame","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"spentOnGame","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sportsAMM","outputs":[{"internalType":"contract ISportsAMMV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"uint16","name":"sportId","type":"uint16"},{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"},{"internalType":"uint24","name":"playerId","type":"uint24"},{"internalType":"uint256[]","name":"odds","type":"uint256[]"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint8","name":"position","type":"uint8"},{"components":[{"internalType":"uint16","name":"typeId","type":"uint16"},{"internalType":"uint8","name":"position","type":"uint8"},{"internalType":"int24","name":"line","type":"int24"}],"internalType":"struct ISportsAMMV2.CombinedPosition[][]","name":"combinedPositions","type":"tuple[][]"}],"internalType":"struct ISportsAMMV2.TradeData","name":"_marketTradeData","type":"tuple"},{"internalType":"bytes32","name":"_rootPerGame","type":"bytes32"}],"name":"verifyMerkleTree","outputs":[],"stateMutability":"pure","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50615ba080620000216000396000f3fe608060405234801561001057600080fd5b506004361061044a5760003560e01c80637daed3291161023c578063c3b83f5f11610146578063df8974d0116100c3578063ea8b414011610087578063ea8b414014610aa8578063eafea26514610ac8578063ebc7977214610adb578063f9c2262214610ae3578063ff527ee314610af657600080fd5b8063df8974d014610a5a578063e202221314610a63578063e365da7814610a6c578063e625afc614610a8c578063e88698bf14610a9f57600080fd5b8063ca9ef2e61161010a578063ca9ef2e6146109ac578063ce440b93146109e6578063d5bdface14610a14578063dc55793614610a27578063dddf183514610a3a57600080fd5b8063c3b83f5f14610957578063c5d89be81461096a578063c6334f9f1461097d578063c758d1f514610986578063c99252881461099957600080fd5b8063a5f32b1e116101d4578063b3ee142411610198578063b3ee1424146108f4578063b7d33278146108fd578063c064649e14610910578063c2a16a9814610923578063c360aded1461093657600080fd5b8063a5f32b1e1461089f578063a90888fc146108b2578063a9772e78146108c5578063a9dfd887146108d8578063aa0f0bb0146108eb57600080fd5b80637daed329146107dc5780638bb78dbd146107ef5780638da5cb5b1461080f5780638ff9d5cf1461082257806391b4ded91461083557806391db39db1461083e57806393de77921461086157806399182a8214610883578063a33a154e1461089657600080fd5b8063404f5788116103585780635c975abb116102d557806362185d9f1161029957806362185d9f1461079257806367c24124146107a5578063689df56e146107b857806379ba5097146107c15780637a0918cf146107c957600080fd5b80635c975abb1461071f5780635cab25d91461072c5780635d6a738c1461073f5780635e0d66b01461075f578063603157861461077257600080fd5b80634dfbc89c1161031c5780634dfbc89c146106d45780635037dc99146106dd57806353a47bb7146106e657806354c05451146106f957806359dc82571461070c57600080fd5b8063404f57881461064757806341dcd5fe14610672578063422f96bf1461067b578063481c6a7514610684578063489685b4146106b457600080fd5b806322434836116103e65780632b7288ae116103aa5780632b7288ae146105b857806331483e0f146105cb5780633305a15d14610605578063363bf964146106255780633f282a8d1461063857600080fd5b8063224348361461055657806323548b8b146105695780632367b6ae146105725780632a8321b2146105855780632b4656c8146105a557600080fd5b8063035478d21461044f57806305954ad4146104875780630a2cc72c146104b55780630d1a2f89146104ca57806313af4035146104ea5780631401f934146104fd5780631627540c1461051d57806316c38b3c146105305780631ad483b514610543575b600080fd5b61047261045d3660046146b0565b60226020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6104a76104953660046146cb565b60176020526000908152604090205481565b60405190815260200161047e565b6104c86104c336600461473d565b610b1e565b005b6104a76104d83660046146cb565b600f6020526000908152604090205481565b6104c86104f83660046147a8565b610bd0565b61051061050b3660046147d6565b610cec565b60405161047e9190614809565b6104c861052b3660046147a8565b61108f565b6104c861053e366004614896565b6110e5565b6104c86105513660046148b3565b611157565b6104c86105643660046148df565b611265565b6104a760105481565b6104c8610580366004614c70565b6112b5565b6104a76105933660046146cb565b60256020526000908152604090205481565b6104c86105b3366004614cb4565b6112c3565b6104c86105c6366004614d22565b611432565b6104a76105d9366004614da9565b600c60209081526000948552604080862082529385528385208152918452828420909152825290205481565b6104a76106133660046146cb565b60236020526000908152604090205481565b6104c8610633366004614ddb565b611555565b6104a7671bc16d674ec8000081565b6104a76106553660046148df565b600b60209081526000928352604080842090915290825290205481565b6104a760195481565b6104a7601a5481565b60055461069c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161047e565b6106c76106c2366004614e1b565b61163e565b60405161047e9190614e7e565b6104a760115481565b6104a760245481565b60015461069c906001600160a01b031681565b6104c8610707366004614ff4565b611876565b6104a761071a36600461507a565b611bfd565b6003546104729060ff1681565b6104c861073a3660046150f6565b611c1c565b6104a761074d3660046146cb565b60096020526000908152604090205481565b6104c861076d366004614e1b565b611c34565b6104a76107803660046146cb565b60126020526000908152604090205481565b6104c86107a0366004614e1b565b611d36565b6104c86107b33660046146cb565b611ef6565b6104a760085481565b6104c8612000565b6104c86107d7366004615124565b6120d8565b6104c86107ea3660046148df565b6121d7565b6104a76107fd3660046146cb565b600a6020526000908152604090205481565b60005461069c906001600160a01b031681565b60065461069c906001600160a01b031681565b6104a760025481565b61047261084c3660046146cb565b60156020526000908152604090205460ff1681565b61047261086f3660046146b0565b602080526000908152604090205460ff1681565b6104a761089136600461515b565b61224e565b6104a7601f5481565b6104c86108ad366004615190565b612264565b6104a76108c0366004615213565b612320565b6104c86108d336600461536d565b612518565b6104c86108e636600461543e565b6127dd565b6104a7600d5481565b6104a7601d5481565b6104c861090b366004615558565b612968565b6104c861091e3660046148df565b6129c2565b6104c861093136600461557d565b612adf565b6109496109443660046155c0565b612bc2565b60405161047e92919061563f565b6104c86109653660046147a8565b612e28565b6104c861097836600461569f565b612f18565b6104a760185481565b6104c86109943660046146cb565b612f92565b60075461069c906001600160a01b031681565b6104a76109ba366004614da9565b601660209081526000948552604080862082529385528385208152918452828420909152825290205481565b6104726109f43660046148df565b601460209081526000928352604080842090915290825290205460ff1681565b6104c8610a223660046148df565b61309c565b6104c8610a35366004614e1b565b613115565b6104a7610a483660046146cb565b601e6020526000908152604090205481565b6104a7601c5481565b6104a760215481565b6104a7610a7a3660046146cb565b60136020526000908152604090205481565b6104c8610a9a366004614e1b565b6132d5565b6104a7601b5481565b6104a7610ab63660046146cb565b600e6020526000908152604090205481565b6104a7610ad6366004615213565b6133ca565b6104c86133ec565b6104c8610af13660046156d5565b61344a565b610b09610b04366004615710565b6134c1565b6040805192835260208301919091520161047e565b610b266136f5565b60005b82811015610bca576000848483818110610b4557610b4561576c565b9050602002016020810190610b5a91906146b0565b61ffff8116600081815260226020908152604091829020805460ff19168815159081179091558251938452908301529192507f6df8945bb4c412ec4a960d2d0c8d268565213a3ef867bd9c00ed2c104932513f910160405180910390a15080610bc281615798565b915050610b29565b50505050565b6001600160a01b038116610c275760405162461bcd60e51b815260206004820152601960248201527804f776e657220616464726573732063616e6e6f74206265203603c1b60448201526064015b60405180910390fd5b600154600160a01b900460ff1615610c935760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b6064820152608401610c1e565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b0383166001600160a01b0319909116178155604051600080516020615b4b83398151915291610ce19184906157b1565b60405180910390a150565b606060018260ff16111580610d0757508260ff168260ff1610155b15610d2557604051632a6c01d760e21b815260040160405180910390fd5b600160005b8360ff168160ff161015610d7957610d438160016157cb565b60ff16610d5082876157e4565b610d5d9060ff16846157fd565b610d679190615814565b9150610d7281615836565b9050610d2a565b506000816001600160401b03811115610d9457610d94614901565b604051908082528060200260200182016040528015610dc757816020015b6060815260200190600190039081610db25790505b50905060008460ff166001600160401b03811115610de757610de7614901565b604051908082528060200260200182016040528015610e10578160200160208202803683370190505b50905060005b8560ff168160ff161015610e5c5780828260ff1681518110610e3a57610e3a61576c565b60ff90921660209283029190910190910152610e5581615836565b9050610e16565b5060005b60008660ff166001600160401b03811115610e7d57610e7d614901565b604051908082528060200260200182016040528015610ea6578160200160208202803683370190505b50905060005b8760ff168160ff161015610f0e57838160ff1681518110610ecf57610ecf61576c565b6020026020010151828260ff1681518110610eec57610eec61576c565b60ff90921660209283029190910190910152610f0781615836565b9050610eac565b5080848381518110610f2257610f2261576c565b60200260200101819052508180610f3890615798565b925060019050875b60ff81161561106d57610f546001826157e4565b610f5e908a6157e4565b610f68908b6157e4565b60ff1685610f776001846157e4565b60ff1681518110610f8a57610f8a61576c565b602002602001015160ff16101561105b5784610fa76001836157e4565b60ff1681518110610fba57610fba61576c565b602002602001018051809190610fcf90615836565b60ff16905250805b8960ff168160ff1610156110515785610ff16001836157e4565b60ff16815181106110045761100461576c565b6020026020010151600161101891906157cb565b868260ff168151811061102d5761102d61576c565b60ff909216602092830291909101909101528061104981615836565b915050610fd7565b506000915061106d565b8061106581615855565b915050610f40565b50801561107b575050611082565b5050610e60565b5090925050505b92915050565b6110976136f5565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290602001610ce1565b6110ed6136f5565b60035460ff16151581151514611154576003805460ff191682151590811790915560ff161561111b57426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec590602001610ce1565b50565b60005433906001600160a01b03168114806111e5575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c395906111a4908490600190600401615872565b602060405180830381865afa1580156111c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e5919061589f565b6112015760405162461bcd60e51b8152600401610c1e906158bc565b6000848152601260209081526040808320869055601382529182902084905581518681529081018590529081018390527f73231c1da1a7341edd4af21892fc5e1c1f340ae5726ee3e20714c146c968558a906060015b60405180910390a150505050565b61126d6136f5565b601c829055601d81905560408051838152602081018390527f8f8d0d2155084c34c7e189b664aa128aebfd57e564d2d01c82a148d3da3a3bbc91015b60405180910390a15050565b6112bf8282613769565b5050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03166000811580156113085750825b90506000826001600160401b031660011480156113245750303b155b905081158015611332575080155b156113505760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561137a57845460ff60401b1916600160401b1785555b6113838c610bd0565b61138b6133ec565b60058054610100600160a81b0319166101006001600160a01b038e81169190910291909117909155600680546001600160a01b031916918c169190911790556008899055600d88905560108790556011869055831561142457845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b60005433906001600160a01b03168114806114c0575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c3959061147f908490600190600401615872565b602060405180830381865afa15801561149c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c0919061589f565b6114dc5760405162461bcd60e51b8152600401610c1e906158bc565b60005b845181101561154e5761153e8582815181106114fd576114fd61576c565b60200260200101518583815181106115175761151761576c565b60200260200101518584815181106115315761153161576c565b60200260200101516137c7565b61154781615798565b90506114df565b5050505050565b61155d6136f5565b6001600160a01b038316158061157a57506001600160a01b038216155b8061158c57506001600160a01b038116155b156115aa5760405163e6c4247b60e01b815260040160405180910390fd5b60058054610100600160a81b0319166101006001600160a01b0386811691820292909217909255600680546001600160a01b03199081168684169081179092556007805490911692851692831790556040805193845260208401919091528201527fbbfb274df95bebde0669697bf0d15986b4ad73e11c495ae4e2d08d1bc5c90bad906060015b60405180910390a1505050565b606082516001600160401b0381111561165957611659614901565b60405190808252806020026020018201604052801561169257816020015b61167f614635565b8152602001906001900390816116775790505b50905060005b835181101561186f5760008482815181106116b5576116b561576c565b60200260200101519050600084516001600160401b038111156116da576116da614901565b60405190808252806020026020018201604052801561171f57816020015b60408051808201909152600080825260208201528152602001906001900390816116f85790505b50905060005b85518110156117b65760008682815181106117425761174261576c565b602002602001015190506040518060400160405280828152602001600b60008781526020019081526020016000206000848152602001908152602001600020548152508383815181106117975761179761576c565b60200260200101819052505080806117ae90615798565b915050611725565b506040805160608082018352600085815260096020908152848220548452868252600a8152848220548185015283850186905284518086018652878352601282528583205481528783526013825285832054818301528551608081018752888152808301869052888452600e90925291859020549481019490945290830181905286519192909187908790811061184f5761184f61576c565b6020026020010181905250505050508061186890615798565b9050611698565b5092915050565b60075433906001600160a01b031681146118c35760405162461bcd60e51b815260206004820152600e60248201526d13db9b1e505353505b1b1bddd95960921b6044820152606401610c1e565b865160005b81811015611b3d5760008982815181106118e4576118e461576c565b6020908102919091018101518082015161ffff16600090815291805260409091205490915060ff168015611919575060018a51115b156119375760405163f37139c760e01b815260040160405180910390fd5b60e0810151610120820151815160ff8216106119665760405163673f032f60e11b815260040160405180910390fd5b61196f8361386d565b61198c57604051633a67d48160e01b815260040160405180910390fd5b6000828260ff16815181106119a3576119a361576c565b60200260200101516000146119f257828260ff16815181106119c7576119c761576c565b60200260200101518c670de0b6b3a76400006119e391906157fd565b6119ed9190615814565b6119f5565b60005b90508b811115611b28576000611a0b8d836158e3565b905060018a60ff161115611a9857611a2b670de0b6b3a7640000886157fd565b60ff8b16611a41670de0b6b3a7640000846157fd565b611a4b91906157fd565b611a559190615814565b9050611a69670de0b6b3a7640000886157fd565b8a60ff16670de0b6b3a76400008f611a8191906157fd565b611a8b91906157fd565b611a959190615814565b9c505b611aa385828d613974565b15611ac157604051635ddb506960e01b815260040160405180910390fd5b611acb85826139f7565b15611ae957604051632d173bb760e11b815260040160405180910390fd5b88158015611afd5750611afd8e8688613a40565b15611b1b5760405163991d7d0b60e01b815260040160405180910390fd5b611b2685828f613b28565b505b5050505080611b3690615798565b90506118c8565b508215611bf3576000611b5088886158e3565b9050611b5c8982613c4e565b15611b7a576040516313fb3c2560e21b815260040160405180910390fd5b80602360008b600081518110611b9257611b9261576c565b60200260200101516000015181526020019081526020016000206000828254611bbb91906158f6565b9091555081905060256000611bcf8c612320565b81526020019081526020016000206000828254611bec91906158f6565b9091555050505b5050505050505050565b6000611c0e88888888888888613d6c565b90505b979650505050505050565b611c246136f5565b611c2f838383614043565b505050565b60005433906001600160a01b0316811480611cc2575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590611c81908490600190600401615872565b602060405180830381865afa158015611c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc2919061589f565b611cde5760405162461bcd60e51b8152600401610c1e906158bc565b60005b8351811015610bca57611d26848281518110611cff57611cff61576c565b6020026020010151848381518110611d1957611d1961576c565b60200260200101516140a8565b611d2f81615798565b9050611ce1565b60005433906001600160a01b0316811480611dc4575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590611d83908490600190600401615872565b602060405180830381865afa158015611da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc4919061589f565b611de05760405162461bcd60e51b8152600401610c1e906158bc565b60005b8351811015610bca57601154838281518110611e0157611e0161576c565b60200260200101511115611e2857604051638f651fb760e01b815260040160405180910390fd5b828181518110611e3a57611e3a61576c565b6020026020010151600f6000868481518110611e5857611e5861576c565b60200260200101518152602001908152602001600020819055507fad3938ddda68b0c35a94769b9bfe09359d462174ac669a50c54f6913ffee2387848281518110611ea557611ea561576c565b6020026020010151848381518110611ebf57611ebf61576c565b6020026020010151604051611ede929190918252602082015260400190565b60405180910390a1611eef81615798565b9050611de3565b60005433906001600160a01b0316811480611f84575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590611f43908490600190600401615872565b602060405180830381865afa158015611f60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f84919061589f565b611fa05760405162461bcd60e51b8152600401610c1e906158bc565b811580611fad5750600a82115b15611fcb576040516315fe1d1760e31b815260040160405180910390fd5b60248290556040518281527f0c239364e4f5adc356c13510be0c9eb7d5cf361baf8315222cd91233a10c599d906020016112a9565b6001546001600160a01b031633146120785760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610c1e565b600054600154604051600080516020615b4b833981519152926120a9926001600160a01b03918216929116906157b1565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60005433906001600160a01b0316811480612166575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590612125908490600190600401615872565b602060405180830381865afa158015612142573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612166919061589f565b6121825760405162461bcd60e51b8152600401610c1e906158bc565b61ffff831660008181526020808052604091829020805460ff19168615159081179091558251938452908301527fb51232e4b8914c35311ac17f4d60b83e968f42365fe9f84d7e79f678971f88bf9101611631565b6121df6136f5565b6010548211806121f0575060115481115b1561220e5760405163b4fa3fb360e01b815260040160405180910390fd5b6008829055600d81905560408051838152602081018390527f66f5882a9629034cfbaab9f0e58425ef198945ed475f313968d861fc699c03c091016112a9565b600061225b848484614113565b50949350505050565b61226c6136f5565b831580612277575081155b156122955760405163a600c81d60e01b815260040160405180910390fd5b60005b848110156123185760008686838181106122b4576122b461576c565b90506020020135905060005b848110156123035760008686838181106122dc576122dc61576c565b9050602002013590506122f0838287614043565b50806122fb81615798565b9150506122c0565b5050808061231090615798565b915050612298565b505050505050565b600061232b82614148565b600082516001600160401b0381111561234657612346614901565b60405190808252806020026020018201604052801561236f578160200160208202803683370190505b509050600083516001600160401b0381111561238d5761238d614901565b6040519080825280602002602001820160405280156123b6578160200160208202803683370190505b509050600084516001600160401b038111156123d4576123d4614901565b6040519080825280602002602001820160405280156123fd578160200160208202803683370190505b50905060005b85518110156124e25785818151811061241e5761241e61576c565b60200260200101516000015184828151811061243c5761243c61576c565b60200260200101818152505085818151811061245a5761245a61576c565b6020026020010151604001518382815181106124785761247861576c565b602002602001019061ffff16908161ffff16815250508581815181106124a0576124a061576c565b602002602001015160c001518282815181106124be576124be61576c565b62ffffff909216602092830291909101909101526124db81615798565b9050612403565b508282826040516020016124f893929190615949565b604051602081830303815290604052805190602001209350505050919050565b60005433906001600160a01b03168114806125a6575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590612565908490600190600401615872565b602060405180830381865afa158015612582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a6919061589f565b6125c25760405162461bcd60e51b8152600401610c1e906158bc565b60005b86518110156127d4576010548382815181106125e3576125e361576c565b6020026020010151111561260a5760405163195bab4d60e31b815260040160405180910390fd5b82818151811061261c5761261c61576c565b6020026020010151600c600089848151811061263a5761263a61576c565b6020026020010151815260200190815260200160002060008884815181106126645761266461576c565b602002602001015161ffff16815260200190815260200160002060008784815181106126925761269261576c565b602002602001015162ffffff16815260200190815260200160002060008684815181106126c1576126c161576c565b602002602001015160020b8152602001908152602001600020819055507fc14b7699de20e98a6336e1020b227f531f06ec5cc9d0f7ba40e51827524fb64a8782815181106127115761271161576c565b602002602001015187838151811061272b5761272b61576c565b60200260200101518784815181106127455761274561576c565b602002602001015187858151811061275f5761275f61576c565b60200260200101518786815181106127795761277961576c565b60200260200101516040516127bc95949392919094855261ffff93909316602085015262ffffff91909116604084015260020b6060830152608082015260a00190565b60405180910390a16127cd81615798565b90506125c5565b50505050505050565b60005433906001600160a01b031681148061286b575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c3959061282a908490600190600401615872565b602060405180830381865afa158015612847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286b919061589f565b6128875760405162461bcd60e51b8152600401610c1e906158bc565b60005b88518110156128d2576128c28982815181106128a8576128a861576c565b6020026020010151898381518110611d1957611d1961576c565b6128cb81615798565b905061288a565b5060005b865181101561292b5761291b8782815181106128f4576128f461576c565b602002602001015187838151811061290e5761290e61576c565b602002602001015161424d565b61292481615798565b90506128d6565b5060005b845181101561295d5761294d8582815181106114fd576114fd61576c565b61295681615798565b905061292f565b505050505050505050565b6129706136f5565b600082815260156020908152604091829020805460ff19168415159081179091558251858152918201527fd6607d95dba4bba9cc6488f5d59c8c13fd3393bb32e524cbfebe05e87796e77491016112a9565b60005433906001600160a01b0316811480612a50575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590612a0f908490600190600401615872565b602060405180830381865afa158015612a2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a50919061589f565b612a6c5760405162461bcd60e51b8152600401610c1e906158bc565b811580612a795750600a82115b15612a97576040516315fe1d1760e31b815260040160405180910390fd5b6000838152601e602090815260409182902084905581518581529081018490527fc8ec738370e588095f95e158fd2cd81a0a2ce198cf844dfba650f0719abd4a949101611631565b601854861015612b0257604051633c6ed54960e11b815260040160405180910390fd5b601b54851015612b2557604051630e10601360e31b815260040160405180910390fd5b601a54612b3287866158e3565b1115612b515760405163245eadfb60e11b815260040160405180910390fd5b612b6382670de0b6b3a76400006158f6565b84612b7685670de0b6b3a76400006157fd565b612b809190615814565b1115612b9f5760405163428637bb60e11b815260040160405180910390fd5b601954811115612318576040516350180cdd60e11b815260040160405180910390fd5b8351600090606090806001600160401b03811115612be257612be2614901565b604051908082528060200260200182016040528015612c0b578160200160208202803683370190505b5091506000600160ff861611815b83811015612e1b5760008a8281518110612c3557612c3561576c565b6020908102919091018101518082015161ffff16600090815291805260409091205490915060ff168015612c695750600185115b93508060e0015181610120015160ff1681518110612c8957612c8961576c565b602002602001015160001480612ccc5750670de0b6b3a76400008160e0015182610120015160ff1681518110612cc157612cc161576c565b602002602001015110155b15612cea5760405163fdfffca760e01b815260040160405180910390fd5b60008160e0015182610120015160ff1681518110612d0a57612d0a61576c565b60200260200101518b670de0b6b3a7640000612d2691906157fd565b612d309190615814565b90506000612d3e8c836158e3565b90508415612d8557612d58670de0b6b3a7640000886157fd565b60ff8b16612d6e670de0b6b3a7640000846157fd565b612d7891906157fd565b612d829190615814565b90505b8580612d975750612d978d8486613a40565b15612da55760029850612e07565b612db083828d613974565b80612dc05750612dc083826139f7565b15612e07576001888581518110612dd957612dd961576c565b911515602092830291909101909101526000896002811115612dfd57612dfd615629565b03612e0757600198505b50505080612e1490615798565b9050612c19565b5050505094509492505050565b612e306136f5565b6001600160a01b038116612e785760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610c1e565b600154600160a81b900460ff1615612ec85760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b6044820152606401610c1e565b600080546001600160a01b0383166001600160a01b031990911681179091556001805460ff60a81b1916600160a81b179055604051600080516020615b4b83398151915291610ce19184906157b1565b8051825114612f3a57604051630469224f60e41b815260040160405180910390fd5b60005b8251811015611c2f57612f82838281518110612f5b57612f5b61576c565b6020026020010151838381518110612f7557612f7561576c565b6020026020010151613769565b612f8b81615798565b9050612f3d565b60005433906001600160a01b0316811480613020575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590612fdf908490600190600401615872565b602060405180830381865afa158015612ffc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613020919061589f565b61303c5760405162461bcd60e51b8152600401610c1e906158bc565b8115806130495750600a82115b15613067576040516315fe1d1760e31b815260040160405180910390fd5b601f8290556040518281527f71ada83bfd8e30b300b57f2f9d90cc70c7d3b027cd3e38967d588ec4378ecf62906020016112a9565b6130a46136f5565b600854821115806130b75750600d548111155b156130d55760405163b4fa3fb360e01b815260040160405180910390fd5b6010829055601181905560408051838152602081018390527f3ef96d50e94656fa01fa9c9a131bc026d07ed3bb6c53daff5695c3a4a2bad54691016112a9565b60005433906001600160a01b03168114806131a3575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590613162908490600190600401615872565b602060405180830381865afa15801561317f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a3919061589f565b6131bf5760405162461bcd60e51b8152600401610c1e906158bc565b60005b8351811015610bca576011548382815181106131e0576131e061576c565b6020026020010151111561320757604051638f651fb760e01b815260040160405180910390fd5b8281815181106132195761321961576c565b6020026020010151600e60008684815181106132375761323761576c565b60200260200101518152602001908152602001600020819055507fbc374ebda39a7586f4916c1911f82c2b045a44439acc485b4097428bf24ab9f98482815181106132845761328461576c565b602002602001015184838151811061329e5761329e61576c565b60200260200101516040516132bd929190918252602082015260400190565b60405180910390a16132ce81615798565b90506131c2565b60005433906001600160a01b0316811480613363575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590613322908490600190600401615872565b602060405180830381865afa15801561333f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613363919061589f565b61337f5760405162461bcd60e51b8152600401610c1e906158bc565b60005b8351811015610bca576133ba8482815181106133a0576133a061576c565b602002602001015184838151811061290e5761290e61576c565b6133c381615798565b9050613382565b6000806133d683612320565b6000908152602560205260409020549392505050565b60055460ff16156134355760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610c1e565b6005805460ff19166001908117909155600455565b6134526136f5565b60188590556019849055601a839055601b8290556021819055604080518681526020810186905290810184905260608101839052608081018290527f6cde94c5ae9fdbda396942be459bab30f8a54e9fc195bca3ab452ab19d4e04069060a00160405180910390a15050505050565b60008060006134d1875187610cec565b8051602154919250908111156134fa57604051633c357c8360e11b815260040160405180910390fd5b6000670de0b6b3a764000082613510828a6157fd565b61351a9190615814565b6135249190615814565b905060005b828110156136c95760008482815181106135455761354561576c565b60200260200101519050600080600090505b82518160ff161015613680576000838260ff168151811061357a5761357a61576c565b6020026020010151905060008e8260ff168151811061359b5761359b61576c565b602002602001015160e001518f8360ff16815181106135bc576135bc61576c565b6020026020010151610120015160ff16815181106135dc576135dc61576c565b60200260200101519050670de0b6b3a7640000818d6135fb91906157fd565b6136059190615814565b6136178d670de0b6b3a76400006158f6565b61362191906158e3565b613633670de0b6b3a7640000836157fd565b61363d9190615814565b9050831561366757670de0b6b3a764000061365882866157fd565b6136629190615814565b613669565b805b93505050808061367890615836565b915050613557565b5080156136b65760008161369c670de0b6b3a7640000876157fd565b6136a69190615814565b90506136b2818a6158f6565b9850505b5050806136c290615798565b9050613529565b50846136dd88670de0b6b3a76400006157fd565b6136e79190615814565b935050505094509492505050565b6000546001600160a01b031633146137675760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610c1e565b565b6000613774836142e3565b90506137868361010001518383614498565b611c2f5760405162461bcd60e51b8152602060048201526012602482015271141c9bdbd9881a5cc81b9bdd081d985b1a5960721b6044820152606401610c1e565b6000838152600960205260408120546137e2576008546137f2565b6000848152600960205260409020545b9050808211156138155760405163195bab4d60e31b815260040160405180910390fd5b6000848152600b6020908152604080832086845282529182902084905581518681529081018590529081018390527f38bba85d238b3778cdb675a039211d90996b1dc4b6c6301971bdbd43fbfe886490606001611257565b600080826060015190506000600660009054906101000a90046001600160a01b03166001600160a01b031663397f7823856000015186604001518760c001518860a001518961014001518a610120015160ff16815181106138d0576138d061576c565b60200260200101516040518663ffffffff1660e01b81526004016138f89594939291906159cf565b602060405180830381865afa158015613915573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613939919061589f565b9050836080015160ff166000148015613950575080155b1561396d5742821061396d57601c5461396942846158e3565b1192505b5050919050565b8251604084015160c0850151602086015160a087015160608801516000959493926139a5928692869186918b613d6c565b600084815260166020908152604080832061ffff87168452825280832062ffffff8616845282528083206101208c015160ff1684529091529020546139eb908890615a5e565b13979650505050505050565b600080836000015190506000613a168286602001518760600151614113565b506000838152601760205260409020549091508190613a369086906158f6565b1195945050505050565b600080613a4e8360016158f6565b90505b8451811015613b20576000858281518110613a6e57613a6e61576c565b6020026020010151905080600001518560000151148015613a9e5750806020015161ffff16856020015161ffff16145b15613b0f5760208086015161ffff1660009081526015909152604090205460ff161580613adc57508060c0015162ffffff168560c0015162ffffff16145b80613aee575060c085015162ffffff16155b80613b00575060c081015162ffffff16155b15613b0f576001925050613b20565b50613b1981615798565b9050613a51565b509392505050565b8251604084015160c085015161012086015160e0870151516020811160005b82811015613c2f57600087815260166020908152604080832061ffff8a168452825280832062ffffff89168452825280832084845290915290205460ff85168203613bce57613b968a82615a5e565b600089815260166020908152604080832061ffff8c168452825280832062ffffff8b1684528252808320868452909152902055613c1e565b821580613bdb5750600081135b15613c1e57613bea8982615a86565b600089815260166020908152604080832061ffff8c168452825280832062ffffff8b16845282528083208684529091529020555b50613c2881615798565b9050613b47565b50600086815260176020526040812080548a9290611bec9084906158f6565b600080600060245411613c62576002613c66565b6024545b9050600080613cd086600081518110613c8157613c8161576c565b60200260200101516000015187600081518110613ca057613ca061576c565b60200260200101516020015188600081518110613cbf57613cbf61576c565b602002602001015160600151614113565b90925090506000613ce18484615814565b86602360008a600081518110613cf957613cf961576c565b602002602001015160000151815260200190815260200160002054613d1e91906158f6565b1190506000613d2d8584615814565b8760256000613d3b8c612320565b815260200190815260200160002054613d5491906158f6565b1190508180613d605750805b98975050505050505050565b600042831115611c11576000888152600c6020908152604080832061ffff8a168452825280832062ffffff891684528252808320600288900b8452909152902054613de1576000888152600c6020908152604080832061ffff8a16845282528083208380528252808320909152902054613e19565b6000888152600c6020908152604080832061ffff8a168452825280832062ffffff891684528252808320600288900b84529091529020545b905080600003613f0d5761ffff871660009081526009602052604090205480613e4457600854613e46565b805b915081905061ffff871615613f0b5761ffff8089166000908152600b60209081526040808320938b168352928152828220548c8352600c825283832083805282528383208252838320909152919020548015613ece5781613ea8600283615814565b1080613eb2575081155b613ebc5781613ec7565b613ec7600282615814565b9350613f08565b81935083600003613f085761ffff8a166000908152600a602052604090205480613f0257613efd600285615814565b613f04565b805b9450505b50505b505b8115613f665761ffff87166000908152601e6020526040902054613f44576000601f5411613f3c576001613f59565b601f54613f59565b61ffff87166000908152601e60205260409020545b613f639082615814565b90505b61ffff87166000908152601260205260409020548015614037576000613f8c42866158e3565b61ffff8a1660009081526013602052604081205491925090613fb657671bc16d674ec80000613fcb565b61ffff8a166000908152601360205260409020545b613fdd670de0b6b3a7640000866157fd565b613fe79190615814565b9050828210613ff857809350614034565b600061400482866158e3565b9050838161401285836158e3565b61401c91906157fd565b6140269190615814565b61403090836158f6565b9450505b50505b50979650505050505050565b6000838152601460209081526040808320858452825291829020805460ff19168415159081179091558251868152918201859052918101919091527ffdd6a752e1596b39b7dc599993db99ce8fcf9f740e9beb9fcd057228e19fc8db90606001611631565b6010548111156140cb5760405163195bab4d60e31b815260040160405180910390fd5b60008281526009602090815260409182902083905581518481529081018390527fdd336d23e5a148c17f76389d3ac4d0ab595ec1bc30e226f1d6ee3cd7714dd6f891016112a9565b60008061412885856000806000886000613d6c565b905061413485856144ae565b61413e90826157fd565b9150935093915050565b805160005b6141586001836158e3565b811015611c2f57600061416c8260016158f6565b90505b8281101561423c5760006141b585848151811061418e5761418e61576c565b60200260200101518684815181106141a8576141a861576c565b60200260200101516144f0565b131561422a578381815181106141cd576141cd61576c565b60200260200101518483815181106141e7576141e761576c565b60200260200101518584815181106142015761420161576c565b6020026020010186848151811061421a5761421a61576c565b6020026020010182905282905250505b8061423481615798565b91505061416f565b5061424681615798565b905061414d565b60008281526009602052604081205461426857600854614278565b6000838152600960205260409020545b90508082111561429b5760405163195bab4d60e31b815260040160405180910390fd5b6000838152600a602090815260409182902084905581518581529081018490527ffbd9918f75c3522536de3aee36688a9c85119cfd97fab820e6c2a4bf5b08f4699101611631565b6000808260000151836020015161ffff16846040015161ffff168560600151866080015160ff168760a0015160020b8860c0015162ffffff168960e00151604051602001614338989796959493929190615aa6565b604051602081830303815290604052905060005b836101400151518110156144895760005b84610140015182815181106143745761437461576c565b6020026020010151518110156144785782856101400151838151811061439c5761439c61576c565b602002602001015182815181106143b5576143b561576c565b60200260200101516000015161ffff1686610140015184815181106143dc576143dc61576c565b602002602001015183815181106143f5576143f561576c565b60200260200101516020015160ff16876101400151858151811061441b5761441b61576c565b602002602001015184815181106144345761443461576c565b60200260200101516040015160020b6040516020016144569493929190615b0b565b60405160208183030381529060405292508061447190615798565b905061435d565b5061448281615798565b905061434c565b50805160209091012092915050565b6000826144a585846145be565b14949350505050565b6000828152600f6020526040812054908190036110895761ffff82166000908152600e6020526040902054806144e657600d546144e8565b805b949350505050565b6000816040015161ffff16836040015161ffff1610156145135750600019611089565b816040015161ffff16836040015161ffff16111561453357506001611089565b8160c0015162ffffff168360c0015162ffffff1610156145565750600019611089565b8160c0015162ffffff168360c0015162ffffff16111561457857506001611089565b8160a0015160020b8360a0015160020b12156145975750600019611089565b8160a0015160020b8360a0015160020b13156145b557506001611089565b50600092915050565b600081815b8451811015613b20576145ef828683815181106145e2576145e261576c565b6020026020010151614603565b9150806145fb81615798565b9150506145c3565b600081831061461f57600082815260208490526040902061462e565b60008381526020839052604090205b9392505050565b60405180608001604052806000815260200161466b60405180606001604052806000815260200160008152602001606081525090565b815260200160008152602001614694604051806040016040528060008152602001600081525090565b905290565b803561ffff811681146146ab57600080fd5b919050565b6000602082840312156146c257600080fd5b61462e82614699565b6000602082840312156146dd57600080fd5b5035919050565b60008083601f8401126146f657600080fd5b5081356001600160401b0381111561470d57600080fd5b6020830191508360208260051b850101111561472857600080fd5b9250929050565b801515811461115457600080fd5b60008060006040848603121561475257600080fd5b83356001600160401b0381111561476857600080fd5b614774868287016146e4565b90945092505060208401356147888161472f565b809150509250925092565b6001600160a01b038116811461115457600080fd5b6000602082840312156147ba57600080fd5b81356144e681614793565b803560ff811681146146ab57600080fd5b600080604083850312156147e957600080fd5b6147f2836147c5565b9150614800602084016147c5565b90509250929050565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b8381101561488857888603603f19018552825180518088529088019088880190845b8181101561487257835160ff168352928a0192918a0191600101614853565b5090975050509386019391860191600101614831565b509398975050505050505050565b6000602082840312156148a857600080fd5b81356144e68161472f565b6000806000606084860312156148c857600080fd5b505081359360208301359350604090920135919050565b600080604083850312156148f257600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561493957614939614901565b60405290565b60405161016081016001600160401b038111828210171561493957614939614901565b604051601f8201601f191681016001600160401b038111828210171561498a5761498a614901565b604052919050565b8035600281900b81146146ab57600080fd5b803562ffffff811681146146ab57600080fd5b60006001600160401b038211156149d0576149d0614901565b5060051b60200190565b600082601f8301126149eb57600080fd5b81356020614a006149fb836149b7565b614962565b82815260059290921b84018101918181019086841115614a1f57600080fd5b8286015b84811015614a3a5780358352918301918301614a23565b509695505050505050565b600082601f830112614a5657600080fd5b81356020614a666149fb836149b7565b82815260059290921b84018101918181019086841115614a8557600080fd5b8286015b84811015614a3a5780356001600160401b03811115614aa85760008081fd5b8701603f81018913614aba5760008081fd5b848101356040614acc6149fb836149b7565b8281526060928302840182019288820191908d851115614aec5760008081fd5b948301945b84861015614b495780868f031215614b095760008081fd5b614b11614917565b614b1a87614699565b8152614b278b88016147c5565b8b820152614b36858801614992565b8186015283529485019491890191614af1565b50875250505092840192508301614a89565b60006101608284031215614b6e57600080fd5b614b7661493f565b905081358152614b8860208301614699565b6020820152614b9960408301614699565b604082015260608201356060820152614bb4608083016147c5565b6080820152614bc560a08301614992565b60a0820152614bd660c083016149a4565b60c082015260e08201356001600160401b0380821115614bf557600080fd5b614c01858386016149da565b60e084015261010091508184013581811115614c1c57600080fd5b614c28868287016149da565b83850152506101209150614c3d8285016147c5565b8284015261014091508184013581811115614c5757600080fd5b614c6386828701614a45565b8385015250505092915050565b60008060408385031215614c8357600080fd5b82356001600160401b03811115614c9957600080fd5b614ca585828601614b5b565b95602094909401359450505050565b600080600080600080600060e0888a031215614ccf57600080fd5b8735614cda81614793565b96506020880135614cea81614793565b95506040880135614cfa81614793565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b600080600060608486031215614d3757600080fd5b83356001600160401b0380821115614d4e57600080fd5b614d5a878388016149da565b94506020860135915080821115614d7057600080fd5b614d7c878388016149da565b93506040860135915080821115614d9257600080fd5b50614d9f868287016149da565b9150509250925092565b60008060008060808587031215614dbf57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600060608486031215614df057600080fd5b8335614dfb81614793565b92506020840135614e0b81614793565b9150604084013561478881614793565b60008060408385031215614e2e57600080fd5b82356001600160401b0380821115614e4557600080fd5b614e51868387016149da565b93506020850135915080821115614e6757600080fd5b50614e74858286016149da565b9150509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015614f6657898403603f190186528251805185528881015160a08a8701819052815190870152808a015160c0870152880151606060e0870181905281516101008801819052918b019185906101208901905b80831015614f2c57614f1882865180518252602090810151910152565b938d019360019290920191908c0190614efb565b50848c0151898d01529382015193614f50838a018680518252602090810151910152565b998c019997505050938901935050600101614ea6565b50919998505050505050505050565b600082601f830112614f8657600080fd5b81356020614f966149fb836149b7565b82815260059290921b84018101918181019086841115614fb557600080fd5b8286015b84811015614a3a5780356001600160401b03811115614fd85760008081fd5b614fe68986838b0101614b5b565b845250918301918301614fb9565b60008060008060008060c0878903121561500d57600080fd5b86356001600160401b0381111561502357600080fd5b61502f89828a01614f75565b9650506020870135945060408701359350606087013561504e8161472f565b925061505c608088016147c5565b915060a087013561506c8161472f565b809150509295509295509295565b600080600080600080600060e0888a03121561509557600080fd5b873596506150a560208901614699565b95506150b360408901614699565b94506150c1606089016149a4565b93506150cf60808901614992565b925060a0880135915060c08801356150e68161472f565b8091505092959891949750929550565b60008060006060848603121561510b57600080fd5b833592506020840135915060408401356147888161472f565b6000806040838503121561513757600080fd5b61514083614699565b915060208301356151508161472f565b809150509250929050565b60008060006060848603121561517057600080fd5b8335925061518060208501614699565b9150604084013590509250925092565b6000806000806000606086880312156151a857600080fd5b85356001600160401b03808211156151bf57600080fd5b6151cb89838a016146e4565b909750955060208801359150808211156151e457600080fd5b506151f1888289016146e4565b90945092505060408601356152058161472f565b809150509295509295909350565b60006020828403121561522557600080fd5b81356001600160401b0381111561523b57600080fd5b6144e884828501614f75565b600082601f83011261525857600080fd5b813560206152686149fb836149b7565b82815260059290921b8401810191818101908684111561528757600080fd5b8286015b84811015614a3a5761529c81614699565b835291830191830161528b565b600082601f8301126152ba57600080fd5b813560206152ca6149fb836149b7565b82815260059290921b840181019181810190868411156152e957600080fd5b8286015b84811015614a3a576152fe816149a4565b83529183019183016152ed565b600082601f83011261531c57600080fd5b8135602061532c6149fb836149b7565b82815260059290921b8401810191818101908684111561534b57600080fd5b8286015b84811015614a3a5761536081614992565b835291830191830161534f565b600080600080600060a0868803121561538557600080fd5b85356001600160401b038082111561539c57600080fd5b6153a889838a016149da565b965060208801359150808211156153be57600080fd5b6153ca89838a01615247565b955060408801359150808211156153e057600080fd5b6153ec89838a016152a9565b9450606088013591508082111561540257600080fd5b61540e89838a0161530b565b9350608088013591508082111561542457600080fd5b50615431888289016149da565b9150509295509295909350565b600080600080600080600060e0888a03121561545957600080fd5b87356001600160401b038082111561547057600080fd5b61547c8b838c016149da565b985060208a013591508082111561549257600080fd5b61549e8b838c016149da565b975060408a01359150808211156154b457600080fd5b6154c08b838c016149da565b965060608a01359150808211156154d657600080fd5b6154e28b838c016149da565b955060808a01359150808211156154f857600080fd5b6155048b838c016149da565b945060a08a013591508082111561551a57600080fd5b6155268b838c016149da565b935060c08a013591508082111561553c57600080fd5b506155498a828b016149da565b91505092959891949750929550565b6000806040838503121561556b57600080fd5b8235915060208301356151508161472f565b60008060008060008060c0878903121561559657600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b600080600080608085870312156155d657600080fd5b84356001600160401b038111156155ec57600080fd5b6155f887828801614f75565b9450506020850135925060408501356156108161472f565b915061561e606086016147c5565b905092959194509250565b634e487b7160e01b600052602160045260246000fd5b6000604082016003851061565557615655615629565b8483526020604081850152818551808452606086019150828701935060005b81811015615692578451151583529383019391830191600101615674565b5090979650505050505050565b600080604083850312156156b257600080fd5b82356001600160401b03808211156156c957600080fd5b614e5186838701614f75565b600080600080600060a086880312156156ed57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000806000806080858703121561572657600080fd5b84356001600160401b0381111561573c57600080fd5b61574887828801614f75565b945050615757602086016147c5565b93969395505050506040820135916060013590565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016157aa576157aa615782565b5060010190565b6001600160a01b0392831681529116602082015260400190565b60ff818116838216019081111561108957611089615782565b60ff828116828216039081111561108957611089615782565b808202811582820484141761108957611089615782565b60008261583157634e487b7160e01b600052601260045260246000fd5b500490565b600060ff821660ff810361584c5761584c615782565b60010192915050565b600060ff82168061586857615868615782565b6000190192915050565b6001600160a01b0383168152604081016004831061589257615892615629565b8260208301529392505050565b6000602082840312156158b157600080fd5b81516144e68161472f565b6020808252600d908201526c24b73b30b634b229b2b73232b960991b604082015260600190565b8181038181111561108957611089615782565b8082018082111561108957611089615782565b600081518084526020808501945080840160005b8381101561593e57815162ffffff168752958201959082019060010161591d565b509495945050505050565b606080825284519082018190526000906020906080840190828801845b8281101561598257815184529284019290840190600101615966565b5050508381038285015285518082528683019183019060005b818110156159bb57835161ffff168352928401929184019160010161599b565b50508481036040860152613d608187615909565b600060a08201878352602061ffff80891682860152604062ffffff8916818701526060600289810b8289015260a0608089015285895180885260c08a019150868b01975060005b81811015615a4a5788518051881684528881015160ff1689850152860151840b868401529787019791840191600101615a16565b50909e9d5050505050505050505050505050565b8082018281126000831280158216821582161715615a7e57615a7e615782565b505092915050565b818103600083128015838313168383128216171561186f5761186f615782565b8881526000602089818401528860408401528760608401528660808401528560a08401528460c084015260e08301845182860160005b82811015615af857815184529284019290840190600101615adc565b50919d9c50505050505050505050505050565b6000855160005b81811015615b2c5760208189018101518583015201615b12565b5091909101938452506020830191909152604082015260600191905056feb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159ca264697066735822122014fa3da3a64e2d6c1d5d59ba4400822e9058148a4e6d318bfa8bf7bcededc1e164736f6c63430008140033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061044a5760003560e01c80637daed3291161023c578063c3b83f5f11610146578063df8974d0116100c3578063ea8b414011610087578063ea8b414014610aa8578063eafea26514610ac8578063ebc7977214610adb578063f9c2262214610ae3578063ff527ee314610af657600080fd5b8063df8974d014610a5a578063e202221314610a63578063e365da7814610a6c578063e625afc614610a8c578063e88698bf14610a9f57600080fd5b8063ca9ef2e61161010a578063ca9ef2e6146109ac578063ce440b93146109e6578063d5bdface14610a14578063dc55793614610a27578063dddf183514610a3a57600080fd5b8063c3b83f5f14610957578063c5d89be81461096a578063c6334f9f1461097d578063c758d1f514610986578063c99252881461099957600080fd5b8063a5f32b1e116101d4578063b3ee142411610198578063b3ee1424146108f4578063b7d33278146108fd578063c064649e14610910578063c2a16a9814610923578063c360aded1461093657600080fd5b8063a5f32b1e1461089f578063a90888fc146108b2578063a9772e78146108c5578063a9dfd887146108d8578063aa0f0bb0146108eb57600080fd5b80637daed329146107dc5780638bb78dbd146107ef5780638da5cb5b1461080f5780638ff9d5cf1461082257806391b4ded91461083557806391db39db1461083e57806393de77921461086157806399182a8214610883578063a33a154e1461089657600080fd5b8063404f5788116103585780635c975abb116102d557806362185d9f1161029957806362185d9f1461079257806367c24124146107a5578063689df56e146107b857806379ba5097146107c15780637a0918cf146107c957600080fd5b80635c975abb1461071f5780635cab25d91461072c5780635d6a738c1461073f5780635e0d66b01461075f578063603157861461077257600080fd5b80634dfbc89c1161031c5780634dfbc89c146106d45780635037dc99146106dd57806353a47bb7146106e657806354c05451146106f957806359dc82571461070c57600080fd5b8063404f57881461064757806341dcd5fe14610672578063422f96bf1461067b578063481c6a7514610684578063489685b4146106b457600080fd5b806322434836116103e65780632b7288ae116103aa5780632b7288ae146105b857806331483e0f146105cb5780633305a15d14610605578063363bf964146106255780633f282a8d1461063857600080fd5b8063224348361461055657806323548b8b146105695780632367b6ae146105725780632a8321b2146105855780632b4656c8146105a557600080fd5b8063035478d21461044f57806305954ad4146104875780630a2cc72c146104b55780630d1a2f89146104ca57806313af4035146104ea5780631401f934146104fd5780631627540c1461051d57806316c38b3c146105305780631ad483b514610543575b600080fd5b61047261045d3660046146b0565b60226020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6104a76104953660046146cb565b60176020526000908152604090205481565b60405190815260200161047e565b6104c86104c336600461473d565b610b1e565b005b6104a76104d83660046146cb565b600f6020526000908152604090205481565b6104c86104f83660046147a8565b610bd0565b61051061050b3660046147d6565b610cec565b60405161047e9190614809565b6104c861052b3660046147a8565b61108f565b6104c861053e366004614896565b6110e5565b6104c86105513660046148b3565b611157565b6104c86105643660046148df565b611265565b6104a760105481565b6104c8610580366004614c70565b6112b5565b6104a76105933660046146cb565b60256020526000908152604090205481565b6104c86105b3366004614cb4565b6112c3565b6104c86105c6366004614d22565b611432565b6104a76105d9366004614da9565b600c60209081526000948552604080862082529385528385208152918452828420909152825290205481565b6104a76106133660046146cb565b60236020526000908152604090205481565b6104c8610633366004614ddb565b611555565b6104a7671bc16d674ec8000081565b6104a76106553660046148df565b600b60209081526000928352604080842090915290825290205481565b6104a760195481565b6104a7601a5481565b60055461069c9061010090046001600160a01b031681565b6040516001600160a01b03909116815260200161047e565b6106c76106c2366004614e1b565b61163e565b60405161047e9190614e7e565b6104a760115481565b6104a760245481565b60015461069c906001600160a01b031681565b6104c8610707366004614ff4565b611876565b6104a761071a36600461507a565b611bfd565b6003546104729060ff1681565b6104c861073a3660046150f6565b611c1c565b6104a761074d3660046146cb565b60096020526000908152604090205481565b6104c861076d366004614e1b565b611c34565b6104a76107803660046146cb565b60126020526000908152604090205481565b6104c86107a0366004614e1b565b611d36565b6104c86107b33660046146cb565b611ef6565b6104a760085481565b6104c8612000565b6104c86107d7366004615124565b6120d8565b6104c86107ea3660046148df565b6121d7565b6104a76107fd3660046146cb565b600a6020526000908152604090205481565b60005461069c906001600160a01b031681565b60065461069c906001600160a01b031681565b6104a760025481565b61047261084c3660046146cb565b60156020526000908152604090205460ff1681565b61047261086f3660046146b0565b602080526000908152604090205460ff1681565b6104a761089136600461515b565b61224e565b6104a7601f5481565b6104c86108ad366004615190565b612264565b6104a76108c0366004615213565b612320565b6104c86108d336600461536d565b612518565b6104c86108e636600461543e565b6127dd565b6104a7600d5481565b6104a7601d5481565b6104c861090b366004615558565b612968565b6104c861091e3660046148df565b6129c2565b6104c861093136600461557d565b612adf565b6109496109443660046155c0565b612bc2565b60405161047e92919061563f565b6104c86109653660046147a8565b612e28565b6104c861097836600461569f565b612f18565b6104a760185481565b6104c86109943660046146cb565b612f92565b60075461069c906001600160a01b031681565b6104a76109ba366004614da9565b601660209081526000948552604080862082529385528385208152918452828420909152825290205481565b6104726109f43660046148df565b601460209081526000928352604080842090915290825290205460ff1681565b6104c8610a223660046148df565b61309c565b6104c8610a35366004614e1b565b613115565b6104a7610a483660046146cb565b601e6020526000908152604090205481565b6104a7601c5481565b6104a760215481565b6104a7610a7a3660046146cb565b60136020526000908152604090205481565b6104c8610a9a366004614e1b565b6132d5565b6104a7601b5481565b6104a7610ab63660046146cb565b600e6020526000908152604090205481565b6104a7610ad6366004615213565b6133ca565b6104c86133ec565b6104c8610af13660046156d5565b61344a565b610b09610b04366004615710565b6134c1565b6040805192835260208301919091520161047e565b610b266136f5565b60005b82811015610bca576000848483818110610b4557610b4561576c565b9050602002016020810190610b5a91906146b0565b61ffff8116600081815260226020908152604091829020805460ff19168815159081179091558251938452908301529192507f6df8945bb4c412ec4a960d2d0c8d268565213a3ef867bd9c00ed2c104932513f910160405180910390a15080610bc281615798565b915050610b29565b50505050565b6001600160a01b038116610c275760405162461bcd60e51b815260206004820152601960248201527804f776e657220616464726573732063616e6e6f74206265203603c1b60448201526064015b60405180910390fd5b600154600160a01b900460ff1615610c935760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b6064820152608401610c1e565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b0383166001600160a01b0319909116178155604051600080516020615b4b83398151915291610ce19184906157b1565b60405180910390a150565b606060018260ff16111580610d0757508260ff168260ff1610155b15610d2557604051632a6c01d760e21b815260040160405180910390fd5b600160005b8360ff168160ff161015610d7957610d438160016157cb565b60ff16610d5082876157e4565b610d5d9060ff16846157fd565b610d679190615814565b9150610d7281615836565b9050610d2a565b506000816001600160401b03811115610d9457610d94614901565b604051908082528060200260200182016040528015610dc757816020015b6060815260200190600190039081610db25790505b50905060008460ff166001600160401b03811115610de757610de7614901565b604051908082528060200260200182016040528015610e10578160200160208202803683370190505b50905060005b8560ff168160ff161015610e5c5780828260ff1681518110610e3a57610e3a61576c565b60ff90921660209283029190910190910152610e5581615836565b9050610e16565b5060005b60008660ff166001600160401b03811115610e7d57610e7d614901565b604051908082528060200260200182016040528015610ea6578160200160208202803683370190505b50905060005b8760ff168160ff161015610f0e57838160ff1681518110610ecf57610ecf61576c565b6020026020010151828260ff1681518110610eec57610eec61576c565b60ff90921660209283029190910190910152610f0781615836565b9050610eac565b5080848381518110610f2257610f2261576c565b60200260200101819052508180610f3890615798565b925060019050875b60ff81161561106d57610f546001826157e4565b610f5e908a6157e4565b610f68908b6157e4565b60ff1685610f776001846157e4565b60ff1681518110610f8a57610f8a61576c565b602002602001015160ff16101561105b5784610fa76001836157e4565b60ff1681518110610fba57610fba61576c565b602002602001018051809190610fcf90615836565b60ff16905250805b8960ff168160ff1610156110515785610ff16001836157e4565b60ff16815181106110045761100461576c565b6020026020010151600161101891906157cb565b868260ff168151811061102d5761102d61576c565b60ff909216602092830291909101909101528061104981615836565b915050610fd7565b506000915061106d565b8061106581615855565b915050610f40565b50801561107b575050611082565b5050610e60565b5090925050505b92915050565b6110976136f5565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290602001610ce1565b6110ed6136f5565b60035460ff16151581151514611154576003805460ff191682151590811790915560ff161561111b57426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec590602001610ce1565b50565b60005433906001600160a01b03168114806111e5575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c395906111a4908490600190600401615872565b602060405180830381865afa1580156111c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e5919061589f565b6112015760405162461bcd60e51b8152600401610c1e906158bc565b6000848152601260209081526040808320869055601382529182902084905581518681529081018590529081018390527f73231c1da1a7341edd4af21892fc5e1c1f340ae5726ee3e20714c146c968558a906060015b60405180910390a150505050565b61126d6136f5565b601c829055601d81905560408051838152602081018390527f8f8d0d2155084c34c7e189b664aa128aebfd57e564d2d01c82a148d3da3a3bbc91015b60405180910390a15050565b6112bf8282613769565b5050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03166000811580156113085750825b90506000826001600160401b031660011480156113245750303b155b905081158015611332575080155b156113505760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561137a57845460ff60401b1916600160401b1785555b6113838c610bd0565b61138b6133ec565b60058054610100600160a81b0319166101006001600160a01b038e81169190910291909117909155600680546001600160a01b031916918c169190911790556008899055600d88905560108790556011869055831561142457845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b60005433906001600160a01b03168114806114c0575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c3959061147f908490600190600401615872565b602060405180830381865afa15801561149c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c0919061589f565b6114dc5760405162461bcd60e51b8152600401610c1e906158bc565b60005b845181101561154e5761153e8582815181106114fd576114fd61576c565b60200260200101518583815181106115175761151761576c565b60200260200101518584815181106115315761153161576c565b60200260200101516137c7565b61154781615798565b90506114df565b5050505050565b61155d6136f5565b6001600160a01b038316158061157a57506001600160a01b038216155b8061158c57506001600160a01b038116155b156115aa5760405163e6c4247b60e01b815260040160405180910390fd5b60058054610100600160a81b0319166101006001600160a01b0386811691820292909217909255600680546001600160a01b03199081168684169081179092556007805490911692851692831790556040805193845260208401919091528201527fbbfb274df95bebde0669697bf0d15986b4ad73e11c495ae4e2d08d1bc5c90bad906060015b60405180910390a1505050565b606082516001600160401b0381111561165957611659614901565b60405190808252806020026020018201604052801561169257816020015b61167f614635565b8152602001906001900390816116775790505b50905060005b835181101561186f5760008482815181106116b5576116b561576c565b60200260200101519050600084516001600160401b038111156116da576116da614901565b60405190808252806020026020018201604052801561171f57816020015b60408051808201909152600080825260208201528152602001906001900390816116f85790505b50905060005b85518110156117b65760008682815181106117425761174261576c565b602002602001015190506040518060400160405280828152602001600b60008781526020019081526020016000206000848152602001908152602001600020548152508383815181106117975761179761576c565b60200260200101819052505080806117ae90615798565b915050611725565b506040805160608082018352600085815260096020908152848220548452868252600a8152848220548185015283850186905284518086018652878352601282528583205481528783526013825285832054818301528551608081018752888152808301869052888452600e90925291859020549481019490945290830181905286519192909187908790811061184f5761184f61576c565b6020026020010181905250505050508061186890615798565b9050611698565b5092915050565b60075433906001600160a01b031681146118c35760405162461bcd60e51b815260206004820152600e60248201526d13db9b1e505353505b1b1bddd95960921b6044820152606401610c1e565b865160005b81811015611b3d5760008982815181106118e4576118e461576c565b6020908102919091018101518082015161ffff16600090815291805260409091205490915060ff168015611919575060018a51115b156119375760405163f37139c760e01b815260040160405180910390fd5b60e0810151610120820151815160ff8216106119665760405163673f032f60e11b815260040160405180910390fd5b61196f8361386d565b61198c57604051633a67d48160e01b815260040160405180910390fd5b6000828260ff16815181106119a3576119a361576c565b60200260200101516000146119f257828260ff16815181106119c7576119c761576c565b60200260200101518c670de0b6b3a76400006119e391906157fd565b6119ed9190615814565b6119f5565b60005b90508b811115611b28576000611a0b8d836158e3565b905060018a60ff161115611a9857611a2b670de0b6b3a7640000886157fd565b60ff8b16611a41670de0b6b3a7640000846157fd565b611a4b91906157fd565b611a559190615814565b9050611a69670de0b6b3a7640000886157fd565b8a60ff16670de0b6b3a76400008f611a8191906157fd565b611a8b91906157fd565b611a959190615814565b9c505b611aa385828d613974565b15611ac157604051635ddb506960e01b815260040160405180910390fd5b611acb85826139f7565b15611ae957604051632d173bb760e11b815260040160405180910390fd5b88158015611afd5750611afd8e8688613a40565b15611b1b5760405163991d7d0b60e01b815260040160405180910390fd5b611b2685828f613b28565b505b5050505080611b3690615798565b90506118c8565b508215611bf3576000611b5088886158e3565b9050611b5c8982613c4e565b15611b7a576040516313fb3c2560e21b815260040160405180910390fd5b80602360008b600081518110611b9257611b9261576c565b60200260200101516000015181526020019081526020016000206000828254611bbb91906158f6565b9091555081905060256000611bcf8c612320565b81526020019081526020016000206000828254611bec91906158f6565b9091555050505b5050505050505050565b6000611c0e88888888888888613d6c565b90505b979650505050505050565b611c246136f5565b611c2f838383614043565b505050565b60005433906001600160a01b0316811480611cc2575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590611c81908490600190600401615872565b602060405180830381865afa158015611c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc2919061589f565b611cde5760405162461bcd60e51b8152600401610c1e906158bc565b60005b8351811015610bca57611d26848281518110611cff57611cff61576c565b6020026020010151848381518110611d1957611d1961576c565b60200260200101516140a8565b611d2f81615798565b9050611ce1565b60005433906001600160a01b0316811480611dc4575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590611d83908490600190600401615872565b602060405180830381865afa158015611da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc4919061589f565b611de05760405162461bcd60e51b8152600401610c1e906158bc565b60005b8351811015610bca57601154838281518110611e0157611e0161576c565b60200260200101511115611e2857604051638f651fb760e01b815260040160405180910390fd5b828181518110611e3a57611e3a61576c565b6020026020010151600f6000868481518110611e5857611e5861576c565b60200260200101518152602001908152602001600020819055507fad3938ddda68b0c35a94769b9bfe09359d462174ac669a50c54f6913ffee2387848281518110611ea557611ea561576c565b6020026020010151848381518110611ebf57611ebf61576c565b6020026020010151604051611ede929190918252602082015260400190565b60405180910390a1611eef81615798565b9050611de3565b60005433906001600160a01b0316811480611f84575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590611f43908490600190600401615872565b602060405180830381865afa158015611f60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f84919061589f565b611fa05760405162461bcd60e51b8152600401610c1e906158bc565b811580611fad5750600a82115b15611fcb576040516315fe1d1760e31b815260040160405180910390fd5b60248290556040518281527f0c239364e4f5adc356c13510be0c9eb7d5cf361baf8315222cd91233a10c599d906020016112a9565b6001546001600160a01b031633146120785760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610c1e565b600054600154604051600080516020615b4b833981519152926120a9926001600160a01b03918216929116906157b1565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60005433906001600160a01b0316811480612166575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590612125908490600190600401615872565b602060405180830381865afa158015612142573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612166919061589f565b6121825760405162461bcd60e51b8152600401610c1e906158bc565b61ffff831660008181526020808052604091829020805460ff19168615159081179091558251938452908301527fb51232e4b8914c35311ac17f4d60b83e968f42365fe9f84d7e79f678971f88bf9101611631565b6121df6136f5565b6010548211806121f0575060115481115b1561220e5760405163b4fa3fb360e01b815260040160405180910390fd5b6008829055600d81905560408051838152602081018390527f66f5882a9629034cfbaab9f0e58425ef198945ed475f313968d861fc699c03c091016112a9565b600061225b848484614113565b50949350505050565b61226c6136f5565b831580612277575081155b156122955760405163a600c81d60e01b815260040160405180910390fd5b60005b848110156123185760008686838181106122b4576122b461576c565b90506020020135905060005b848110156123035760008686838181106122dc576122dc61576c565b9050602002013590506122f0838287614043565b50806122fb81615798565b9150506122c0565b5050808061231090615798565b915050612298565b505050505050565b600061232b82614148565b600082516001600160401b0381111561234657612346614901565b60405190808252806020026020018201604052801561236f578160200160208202803683370190505b509050600083516001600160401b0381111561238d5761238d614901565b6040519080825280602002602001820160405280156123b6578160200160208202803683370190505b509050600084516001600160401b038111156123d4576123d4614901565b6040519080825280602002602001820160405280156123fd578160200160208202803683370190505b50905060005b85518110156124e25785818151811061241e5761241e61576c565b60200260200101516000015184828151811061243c5761243c61576c565b60200260200101818152505085818151811061245a5761245a61576c565b6020026020010151604001518382815181106124785761247861576c565b602002602001019061ffff16908161ffff16815250508581815181106124a0576124a061576c565b602002602001015160c001518282815181106124be576124be61576c565b62ffffff909216602092830291909101909101526124db81615798565b9050612403565b508282826040516020016124f893929190615949565b604051602081830303815290604052805190602001209350505050919050565b60005433906001600160a01b03168114806125a6575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590612565908490600190600401615872565b602060405180830381865afa158015612582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a6919061589f565b6125c25760405162461bcd60e51b8152600401610c1e906158bc565b60005b86518110156127d4576010548382815181106125e3576125e361576c565b6020026020010151111561260a5760405163195bab4d60e31b815260040160405180910390fd5b82818151811061261c5761261c61576c565b6020026020010151600c600089848151811061263a5761263a61576c565b6020026020010151815260200190815260200160002060008884815181106126645761266461576c565b602002602001015161ffff16815260200190815260200160002060008784815181106126925761269261576c565b602002602001015162ffffff16815260200190815260200160002060008684815181106126c1576126c161576c565b602002602001015160020b8152602001908152602001600020819055507fc14b7699de20e98a6336e1020b227f531f06ec5cc9d0f7ba40e51827524fb64a8782815181106127115761271161576c565b602002602001015187838151811061272b5761272b61576c565b60200260200101518784815181106127455761274561576c565b602002602001015187858151811061275f5761275f61576c565b60200260200101518786815181106127795761277961576c565b60200260200101516040516127bc95949392919094855261ffff93909316602085015262ffffff91909116604084015260020b6060830152608082015260a00190565b60405180910390a16127cd81615798565b90506125c5565b50505050505050565b60005433906001600160a01b031681148061286b575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c3959061282a908490600190600401615872565b602060405180830381865afa158015612847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286b919061589f565b6128875760405162461bcd60e51b8152600401610c1e906158bc565b60005b88518110156128d2576128c28982815181106128a8576128a861576c565b6020026020010151898381518110611d1957611d1961576c565b6128cb81615798565b905061288a565b5060005b865181101561292b5761291b8782815181106128f4576128f461576c565b602002602001015187838151811061290e5761290e61576c565b602002602001015161424d565b61292481615798565b90506128d6565b5060005b845181101561295d5761294d8582815181106114fd576114fd61576c565b61295681615798565b905061292f565b505050505050505050565b6129706136f5565b600082815260156020908152604091829020805460ff19168415159081179091558251858152918201527fd6607d95dba4bba9cc6488f5d59c8c13fd3393bb32e524cbfebe05e87796e77491016112a9565b60005433906001600160a01b0316811480612a50575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590612a0f908490600190600401615872565b602060405180830381865afa158015612a2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a50919061589f565b612a6c5760405162461bcd60e51b8152600401610c1e906158bc565b811580612a795750600a82115b15612a97576040516315fe1d1760e31b815260040160405180910390fd5b6000838152601e602090815260409182902084905581518581529081018490527fc8ec738370e588095f95e158fd2cd81a0a2ce198cf844dfba650f0719abd4a949101611631565b601854861015612b0257604051633c6ed54960e11b815260040160405180910390fd5b601b54851015612b2557604051630e10601360e31b815260040160405180910390fd5b601a54612b3287866158e3565b1115612b515760405163245eadfb60e11b815260040160405180910390fd5b612b6382670de0b6b3a76400006158f6565b84612b7685670de0b6b3a76400006157fd565b612b809190615814565b1115612b9f5760405163428637bb60e11b815260040160405180910390fd5b601954811115612318576040516350180cdd60e11b815260040160405180910390fd5b8351600090606090806001600160401b03811115612be257612be2614901565b604051908082528060200260200182016040528015612c0b578160200160208202803683370190505b5091506000600160ff861611815b83811015612e1b5760008a8281518110612c3557612c3561576c565b6020908102919091018101518082015161ffff16600090815291805260409091205490915060ff168015612c695750600185115b93508060e0015181610120015160ff1681518110612c8957612c8961576c565b602002602001015160001480612ccc5750670de0b6b3a76400008160e0015182610120015160ff1681518110612cc157612cc161576c565b602002602001015110155b15612cea5760405163fdfffca760e01b815260040160405180910390fd5b60008160e0015182610120015160ff1681518110612d0a57612d0a61576c565b60200260200101518b670de0b6b3a7640000612d2691906157fd565b612d309190615814565b90506000612d3e8c836158e3565b90508415612d8557612d58670de0b6b3a7640000886157fd565b60ff8b16612d6e670de0b6b3a7640000846157fd565b612d7891906157fd565b612d829190615814565b90505b8580612d975750612d978d8486613a40565b15612da55760029850612e07565b612db083828d613974565b80612dc05750612dc083826139f7565b15612e07576001888581518110612dd957612dd961576c565b911515602092830291909101909101526000896002811115612dfd57612dfd615629565b03612e0757600198505b50505080612e1490615798565b9050612c19565b5050505094509492505050565b612e306136f5565b6001600160a01b038116612e785760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610c1e565b600154600160a81b900460ff1615612ec85760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b6044820152606401610c1e565b600080546001600160a01b0383166001600160a01b031990911681179091556001805460ff60a81b1916600160a81b179055604051600080516020615b4b83398151915291610ce19184906157b1565b8051825114612f3a57604051630469224f60e41b815260040160405180910390fd5b60005b8251811015611c2f57612f82838281518110612f5b57612f5b61576c565b6020026020010151838381518110612f7557612f7561576c565b6020026020010151613769565b612f8b81615798565b9050612f3d565b60005433906001600160a01b0316811480613020575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590612fdf908490600190600401615872565b602060405180830381865afa158015612ffc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613020919061589f565b61303c5760405162461bcd60e51b8152600401610c1e906158bc565b8115806130495750600a82115b15613067576040516315fe1d1760e31b815260040160405180910390fd5b601f8290556040518281527f71ada83bfd8e30b300b57f2f9d90cc70c7d3b027cd3e38967d588ec4378ecf62906020016112a9565b6130a46136f5565b600854821115806130b75750600d548111155b156130d55760405163b4fa3fb360e01b815260040160405180910390fd5b6010829055601181905560408051838152602081018390527f3ef96d50e94656fa01fa9c9a131bc026d07ed3bb6c53daff5695c3a4a2bad54691016112a9565b60005433906001600160a01b03168114806131a3575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590613162908490600190600401615872565b602060405180830381865afa15801561317f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a3919061589f565b6131bf5760405162461bcd60e51b8152600401610c1e906158bc565b60005b8351811015610bca576011548382815181106131e0576131e061576c565b6020026020010151111561320757604051638f651fb760e01b815260040160405180910390fd5b8281815181106132195761321961576c565b6020026020010151600e60008684815181106132375761323761576c565b60200260200101518152602001908152602001600020819055507fbc374ebda39a7586f4916c1911f82c2b045a44439acc485b4097428bf24ab9f98482815181106132845761328461576c565b602002602001015184838151811061329e5761329e61576c565b60200260200101516040516132bd929190918252602082015260400190565b60405180910390a16132ce81615798565b90506131c2565b60005433906001600160a01b0316811480613363575060055460405163e760c39560e01b81526101009091046001600160a01b03169063e760c39590613322908490600190600401615872565b602060405180830381865afa15801561333f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613363919061589f565b61337f5760405162461bcd60e51b8152600401610c1e906158bc565b60005b8351811015610bca576133ba8482815181106133a0576133a061576c565b602002602001015184838151811061290e5761290e61576c565b6133c381615798565b9050613382565b6000806133d683612320565b6000908152602560205260409020549392505050565b60055460ff16156134355760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610c1e565b6005805460ff19166001908117909155600455565b6134526136f5565b60188590556019849055601a839055601b8290556021819055604080518681526020810186905290810184905260608101839052608081018290527f6cde94c5ae9fdbda396942be459bab30f8a54e9fc195bca3ab452ab19d4e04069060a00160405180910390a15050505050565b60008060006134d1875187610cec565b8051602154919250908111156134fa57604051633c357c8360e11b815260040160405180910390fd5b6000670de0b6b3a764000082613510828a6157fd565b61351a9190615814565b6135249190615814565b905060005b828110156136c95760008482815181106135455761354561576c565b60200260200101519050600080600090505b82518160ff161015613680576000838260ff168151811061357a5761357a61576c565b6020026020010151905060008e8260ff168151811061359b5761359b61576c565b602002602001015160e001518f8360ff16815181106135bc576135bc61576c565b6020026020010151610120015160ff16815181106135dc576135dc61576c565b60200260200101519050670de0b6b3a7640000818d6135fb91906157fd565b6136059190615814565b6136178d670de0b6b3a76400006158f6565b61362191906158e3565b613633670de0b6b3a7640000836157fd565b61363d9190615814565b9050831561366757670de0b6b3a764000061365882866157fd565b6136629190615814565b613669565b805b93505050808061367890615836565b915050613557565b5080156136b65760008161369c670de0b6b3a7640000876157fd565b6136a69190615814565b90506136b2818a6158f6565b9850505b5050806136c290615798565b9050613529565b50846136dd88670de0b6b3a76400006157fd565b6136e79190615814565b935050505094509492505050565b6000546001600160a01b031633146137675760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610c1e565b565b6000613774836142e3565b90506137868361010001518383614498565b611c2f5760405162461bcd60e51b8152602060048201526012602482015271141c9bdbd9881a5cc81b9bdd081d985b1a5960721b6044820152606401610c1e565b6000838152600960205260408120546137e2576008546137f2565b6000848152600960205260409020545b9050808211156138155760405163195bab4d60e31b815260040160405180910390fd5b6000848152600b6020908152604080832086845282529182902084905581518681529081018590529081018390527f38bba85d238b3778cdb675a039211d90996b1dc4b6c6301971bdbd43fbfe886490606001611257565b600080826060015190506000600660009054906101000a90046001600160a01b03166001600160a01b031663397f7823856000015186604001518760c001518860a001518961014001518a610120015160ff16815181106138d0576138d061576c565b60200260200101516040518663ffffffff1660e01b81526004016138f89594939291906159cf565b602060405180830381865afa158015613915573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613939919061589f565b9050836080015160ff166000148015613950575080155b1561396d5742821061396d57601c5461396942846158e3565b1192505b5050919050565b8251604084015160c0850151602086015160a087015160608801516000959493926139a5928692869186918b613d6c565b600084815260166020908152604080832061ffff87168452825280832062ffffff8616845282528083206101208c015160ff1684529091529020546139eb908890615a5e565b13979650505050505050565b600080836000015190506000613a168286602001518760600151614113565b506000838152601760205260409020549091508190613a369086906158f6565b1195945050505050565b600080613a4e8360016158f6565b90505b8451811015613b20576000858281518110613a6e57613a6e61576c565b6020026020010151905080600001518560000151148015613a9e5750806020015161ffff16856020015161ffff16145b15613b0f5760208086015161ffff1660009081526015909152604090205460ff161580613adc57508060c0015162ffffff168560c0015162ffffff16145b80613aee575060c085015162ffffff16155b80613b00575060c081015162ffffff16155b15613b0f576001925050613b20565b50613b1981615798565b9050613a51565b509392505050565b8251604084015160c085015161012086015160e0870151516020811160005b82811015613c2f57600087815260166020908152604080832061ffff8a168452825280832062ffffff89168452825280832084845290915290205460ff85168203613bce57613b968a82615a5e565b600089815260166020908152604080832061ffff8c168452825280832062ffffff8b1684528252808320868452909152902055613c1e565b821580613bdb5750600081135b15613c1e57613bea8982615a86565b600089815260166020908152604080832061ffff8c168452825280832062ffffff8b16845282528083208684529091529020555b50613c2881615798565b9050613b47565b50600086815260176020526040812080548a9290611bec9084906158f6565b600080600060245411613c62576002613c66565b6024545b9050600080613cd086600081518110613c8157613c8161576c565b60200260200101516000015187600081518110613ca057613ca061576c565b60200260200101516020015188600081518110613cbf57613cbf61576c565b602002602001015160600151614113565b90925090506000613ce18484615814565b86602360008a600081518110613cf957613cf961576c565b602002602001015160000151815260200190815260200160002054613d1e91906158f6565b1190506000613d2d8584615814565b8760256000613d3b8c612320565b815260200190815260200160002054613d5491906158f6565b1190508180613d605750805b98975050505050505050565b600042831115611c11576000888152600c6020908152604080832061ffff8a168452825280832062ffffff891684528252808320600288900b8452909152902054613de1576000888152600c6020908152604080832061ffff8a16845282528083208380528252808320909152902054613e19565b6000888152600c6020908152604080832061ffff8a168452825280832062ffffff891684528252808320600288900b84529091529020545b905080600003613f0d5761ffff871660009081526009602052604090205480613e4457600854613e46565b805b915081905061ffff871615613f0b5761ffff8089166000908152600b60209081526040808320938b168352928152828220548c8352600c825283832083805282528383208252838320909152919020548015613ece5781613ea8600283615814565b1080613eb2575081155b613ebc5781613ec7565b613ec7600282615814565b9350613f08565b81935083600003613f085761ffff8a166000908152600a602052604090205480613f0257613efd600285615814565b613f04565b805b9450505b50505b505b8115613f665761ffff87166000908152601e6020526040902054613f44576000601f5411613f3c576001613f59565b601f54613f59565b61ffff87166000908152601e60205260409020545b613f639082615814565b90505b61ffff87166000908152601260205260409020548015614037576000613f8c42866158e3565b61ffff8a1660009081526013602052604081205491925090613fb657671bc16d674ec80000613fcb565b61ffff8a166000908152601360205260409020545b613fdd670de0b6b3a7640000866157fd565b613fe79190615814565b9050828210613ff857809350614034565b600061400482866158e3565b9050838161401285836158e3565b61401c91906157fd565b6140269190615814565b61403090836158f6565b9450505b50505b50979650505050505050565b6000838152601460209081526040808320858452825291829020805460ff19168415159081179091558251868152918201859052918101919091527ffdd6a752e1596b39b7dc599993db99ce8fcf9f740e9beb9fcd057228e19fc8db90606001611631565b6010548111156140cb5760405163195bab4d60e31b815260040160405180910390fd5b60008281526009602090815260409182902083905581518481529081018390527fdd336d23e5a148c17f76389d3ac4d0ab595ec1bc30e226f1d6ee3cd7714dd6f891016112a9565b60008061412885856000806000886000613d6c565b905061413485856144ae565b61413e90826157fd565b9150935093915050565b805160005b6141586001836158e3565b811015611c2f57600061416c8260016158f6565b90505b8281101561423c5760006141b585848151811061418e5761418e61576c565b60200260200101518684815181106141a8576141a861576c565b60200260200101516144f0565b131561422a578381815181106141cd576141cd61576c565b60200260200101518483815181106141e7576141e761576c565b60200260200101518584815181106142015761420161576c565b6020026020010186848151811061421a5761421a61576c565b6020026020010182905282905250505b8061423481615798565b91505061416f565b5061424681615798565b905061414d565b60008281526009602052604081205461426857600854614278565b6000838152600960205260409020545b90508082111561429b5760405163195bab4d60e31b815260040160405180910390fd5b6000838152600a602090815260409182902084905581518581529081018490527ffbd9918f75c3522536de3aee36688a9c85119cfd97fab820e6c2a4bf5b08f4699101611631565b6000808260000151836020015161ffff16846040015161ffff168560600151866080015160ff168760a0015160020b8860c0015162ffffff168960e00151604051602001614338989796959493929190615aa6565b604051602081830303815290604052905060005b836101400151518110156144895760005b84610140015182815181106143745761437461576c565b6020026020010151518110156144785782856101400151838151811061439c5761439c61576c565b602002602001015182815181106143b5576143b561576c565b60200260200101516000015161ffff1686610140015184815181106143dc576143dc61576c565b602002602001015183815181106143f5576143f561576c565b60200260200101516020015160ff16876101400151858151811061441b5761441b61576c565b602002602001015184815181106144345761443461576c565b60200260200101516040015160020b6040516020016144569493929190615b0b565b60405160208183030381529060405292508061447190615798565b905061435d565b5061448281615798565b905061434c565b50805160209091012092915050565b6000826144a585846145be565b14949350505050565b6000828152600f6020526040812054908190036110895761ffff82166000908152600e6020526040902054806144e657600d546144e8565b805b949350505050565b6000816040015161ffff16836040015161ffff1610156145135750600019611089565b816040015161ffff16836040015161ffff16111561453357506001611089565b8160c0015162ffffff168360c0015162ffffff1610156145565750600019611089565b8160c0015162ffffff168360c0015162ffffff16111561457857506001611089565b8160a0015160020b8360a0015160020b12156145975750600019611089565b8160a0015160020b8360a0015160020b13156145b557506001611089565b50600092915050565b600081815b8451811015613b20576145ef828683815181106145e2576145e261576c565b6020026020010151614603565b9150806145fb81615798565b9150506145c3565b600081831061461f57600082815260208490526040902061462e565b60008381526020839052604090205b9392505050565b60405180608001604052806000815260200161466b60405180606001604052806000815260200160008152602001606081525090565b815260200160008152602001614694604051806040016040528060008152602001600081525090565b905290565b803561ffff811681146146ab57600080fd5b919050565b6000602082840312156146c257600080fd5b61462e82614699565b6000602082840312156146dd57600080fd5b5035919050565b60008083601f8401126146f657600080fd5b5081356001600160401b0381111561470d57600080fd5b6020830191508360208260051b850101111561472857600080fd5b9250929050565b801515811461115457600080fd5b60008060006040848603121561475257600080fd5b83356001600160401b0381111561476857600080fd5b614774868287016146e4565b90945092505060208401356147888161472f565b809150509250925092565b6001600160a01b038116811461115457600080fd5b6000602082840312156147ba57600080fd5b81356144e681614793565b803560ff811681146146ab57600080fd5b600080604083850312156147e957600080fd5b6147f2836147c5565b9150614800602084016147c5565b90509250929050565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b8381101561488857888603603f19018552825180518088529088019088880190845b8181101561487257835160ff168352928a0192918a0191600101614853565b5090975050509386019391860191600101614831565b509398975050505050505050565b6000602082840312156148a857600080fd5b81356144e68161472f565b6000806000606084860312156148c857600080fd5b505081359360208301359350604090920135919050565b600080604083850312156148f257600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561493957614939614901565b60405290565b60405161016081016001600160401b038111828210171561493957614939614901565b604051601f8201601f191681016001600160401b038111828210171561498a5761498a614901565b604052919050565b8035600281900b81146146ab57600080fd5b803562ffffff811681146146ab57600080fd5b60006001600160401b038211156149d0576149d0614901565b5060051b60200190565b600082601f8301126149eb57600080fd5b81356020614a006149fb836149b7565b614962565b82815260059290921b84018101918181019086841115614a1f57600080fd5b8286015b84811015614a3a5780358352918301918301614a23565b509695505050505050565b600082601f830112614a5657600080fd5b81356020614a666149fb836149b7565b82815260059290921b84018101918181019086841115614a8557600080fd5b8286015b84811015614a3a5780356001600160401b03811115614aa85760008081fd5b8701603f81018913614aba5760008081fd5b848101356040614acc6149fb836149b7565b8281526060928302840182019288820191908d851115614aec5760008081fd5b948301945b84861015614b495780868f031215614b095760008081fd5b614b11614917565b614b1a87614699565b8152614b278b88016147c5565b8b820152614b36858801614992565b8186015283529485019491890191614af1565b50875250505092840192508301614a89565b60006101608284031215614b6e57600080fd5b614b7661493f565b905081358152614b8860208301614699565b6020820152614b9960408301614699565b604082015260608201356060820152614bb4608083016147c5565b6080820152614bc560a08301614992565b60a0820152614bd660c083016149a4565b60c082015260e08201356001600160401b0380821115614bf557600080fd5b614c01858386016149da565b60e084015261010091508184013581811115614c1c57600080fd5b614c28868287016149da565b83850152506101209150614c3d8285016147c5565b8284015261014091508184013581811115614c5757600080fd5b614c6386828701614a45565b8385015250505092915050565b60008060408385031215614c8357600080fd5b82356001600160401b03811115614c9957600080fd5b614ca585828601614b5b565b95602094909401359450505050565b600080600080600080600060e0888a031215614ccf57600080fd5b8735614cda81614793565b96506020880135614cea81614793565b95506040880135614cfa81614793565b969995985095966060810135965060808101359560a0820135955060c0909101359350915050565b600080600060608486031215614d3757600080fd5b83356001600160401b0380821115614d4e57600080fd5b614d5a878388016149da565b94506020860135915080821115614d7057600080fd5b614d7c878388016149da565b93506040860135915080821115614d9257600080fd5b50614d9f868287016149da565b9150509250925092565b60008060008060808587031215614dbf57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600060608486031215614df057600080fd5b8335614dfb81614793565b92506020840135614e0b81614793565b9150604084013561478881614793565b60008060408385031215614e2e57600080fd5b82356001600160401b0380821115614e4557600080fd5b614e51868387016149da565b93506020850135915080821115614e6757600080fd5b50614e74858286016149da565b9150509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015614f6657898403603f190186528251805185528881015160a08a8701819052815190870152808a015160c0870152880151606060e0870181905281516101008801819052918b019185906101208901905b80831015614f2c57614f1882865180518252602090810151910152565b938d019360019290920191908c0190614efb565b50848c0151898d01529382015193614f50838a018680518252602090810151910152565b998c019997505050938901935050600101614ea6565b50919998505050505050505050565b600082601f830112614f8657600080fd5b81356020614f966149fb836149b7565b82815260059290921b84018101918181019086841115614fb557600080fd5b8286015b84811015614a3a5780356001600160401b03811115614fd85760008081fd5b614fe68986838b0101614b5b565b845250918301918301614fb9565b60008060008060008060c0878903121561500d57600080fd5b86356001600160401b0381111561502357600080fd5b61502f89828a01614f75565b9650506020870135945060408701359350606087013561504e8161472f565b925061505c608088016147c5565b915060a087013561506c8161472f565b809150509295509295509295565b600080600080600080600060e0888a03121561509557600080fd5b873596506150a560208901614699565b95506150b360408901614699565b94506150c1606089016149a4565b93506150cf60808901614992565b925060a0880135915060c08801356150e68161472f565b8091505092959891949750929550565b60008060006060848603121561510b57600080fd5b833592506020840135915060408401356147888161472f565b6000806040838503121561513757600080fd5b61514083614699565b915060208301356151508161472f565b809150509250929050565b60008060006060848603121561517057600080fd5b8335925061518060208501614699565b9150604084013590509250925092565b6000806000806000606086880312156151a857600080fd5b85356001600160401b03808211156151bf57600080fd5b6151cb89838a016146e4565b909750955060208801359150808211156151e457600080fd5b506151f1888289016146e4565b90945092505060408601356152058161472f565b809150509295509295909350565b60006020828403121561522557600080fd5b81356001600160401b0381111561523b57600080fd5b6144e884828501614f75565b600082601f83011261525857600080fd5b813560206152686149fb836149b7565b82815260059290921b8401810191818101908684111561528757600080fd5b8286015b84811015614a3a5761529c81614699565b835291830191830161528b565b600082601f8301126152ba57600080fd5b813560206152ca6149fb836149b7565b82815260059290921b840181019181810190868411156152e957600080fd5b8286015b84811015614a3a576152fe816149a4565b83529183019183016152ed565b600082601f83011261531c57600080fd5b8135602061532c6149fb836149b7565b82815260059290921b8401810191818101908684111561534b57600080fd5b8286015b84811015614a3a5761536081614992565b835291830191830161534f565b600080600080600060a0868803121561538557600080fd5b85356001600160401b038082111561539c57600080fd5b6153a889838a016149da565b965060208801359150808211156153be57600080fd5b6153ca89838a01615247565b955060408801359150808211156153e057600080fd5b6153ec89838a016152a9565b9450606088013591508082111561540257600080fd5b61540e89838a0161530b565b9350608088013591508082111561542457600080fd5b50615431888289016149da565b9150509295509295909350565b600080600080600080600060e0888a03121561545957600080fd5b87356001600160401b038082111561547057600080fd5b61547c8b838c016149da565b985060208a013591508082111561549257600080fd5b61549e8b838c016149da565b975060408a01359150808211156154b457600080fd5b6154c08b838c016149da565b965060608a01359150808211156154d657600080fd5b6154e28b838c016149da565b955060808a01359150808211156154f857600080fd5b6155048b838c016149da565b945060a08a013591508082111561551a57600080fd5b6155268b838c016149da565b935060c08a013591508082111561553c57600080fd5b506155498a828b016149da565b91505092959891949750929550565b6000806040838503121561556b57600080fd5b8235915060208301356151508161472f565b60008060008060008060c0878903121561559657600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b600080600080608085870312156155d657600080fd5b84356001600160401b038111156155ec57600080fd5b6155f887828801614f75565b9450506020850135925060408501356156108161472f565b915061561e606086016147c5565b905092959194509250565b634e487b7160e01b600052602160045260246000fd5b6000604082016003851061565557615655615629565b8483526020604081850152818551808452606086019150828701935060005b81811015615692578451151583529383019391830191600101615674565b5090979650505050505050565b600080604083850312156156b257600080fd5b82356001600160401b03808211156156c957600080fd5b614e5186838701614f75565b600080600080600060a086880312156156ed57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000806000806080858703121561572657600080fd5b84356001600160401b0381111561573c57600080fd5b61574887828801614f75565b945050615757602086016147c5565b93969395505050506040820135916060013590565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016157aa576157aa615782565b5060010190565b6001600160a01b0392831681529116602082015260400190565b60ff818116838216019081111561108957611089615782565b60ff828116828216039081111561108957611089615782565b808202811582820484141761108957611089615782565b60008261583157634e487b7160e01b600052601260045260246000fd5b500490565b600060ff821660ff810361584c5761584c615782565b60010192915050565b600060ff82168061586857615868615782565b6000190192915050565b6001600160a01b0383168152604081016004831061589257615892615629565b8260208301529392505050565b6000602082840312156158b157600080fd5b81516144e68161472f565b6020808252600d908201526c24b73b30b634b229b2b73232b960991b604082015260600190565b8181038181111561108957611089615782565b8082018082111561108957611089615782565b600081518084526020808501945080840160005b8381101561593e57815162ffffff168752958201959082019060010161591d565b509495945050505050565b606080825284519082018190526000906020906080840190828801845b8281101561598257815184529284019290840190600101615966565b5050508381038285015285518082528683019183019060005b818110156159bb57835161ffff168352928401929184019160010161599b565b50508481036040860152613d608187615909565b600060a08201878352602061ffff80891682860152604062ffffff8916818701526060600289810b8289015260a0608089015285895180885260c08a019150868b01975060005b81811015615a4a5788518051881684528881015160ff1689850152860151840b868401529787019791840191600101615a16565b50909e9d5050505050505050505050505050565b8082018281126000831280158216821582161715615a7e57615a7e615782565b505092915050565b818103600083128015838313168383128216171561186f5761186f615782565b8881526000602089818401528860408401528760608401528660808401528560a08401528460c084015260e08301845182860160005b82811015615af857815184529284019290840190600101615adc565b50919d9c50505050505050505050505050565b6000855160005b81811015615b2c5760208189018101518583015201615b12565b5091909101938452506020830191909152604082015260600191905056feb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159ca264697066735822122014fa3da3a64e2d6c1d5d59ba4400822e9058148a4e6d318bfa8bf7bcededc1e164736f6c63430008140033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.