Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ParlayPolicy
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Inheritance import "../../interfaces/IParlayMarketsAMM.sol"; import "../../interfaces/ISportPositionalMarket.sol"; import "../../utils/proxy/solidity-0.8.0/ProxyOwned.sol"; import "../../utils/proxy/solidity-0.8.0/ProxyPausable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "../../interfaces/ISportsAMMTiny.sol"; import "../../interfaces/IParlayPolicy.sol"; import "../../interfaces/ITherundownConsumer.sol"; import "../../interfaces/IGamesPlayerProps.sol"; import "../../interfaces/IGamesOddsObtainer.sol"; import "../../interfaces/ISportPositionalMarket.sol"; contract ParlayPolicy is Initializable, ProxyOwned, ProxyPausable { IParlayMarketsAMM public parlayMarketsAMM; ISportsAMMTiny public sportsAMM; address public consumer; mapping(uint => bool) public eligibleSportForSamePropsCombination; function initialize(address _owner, address _parlayMarketsAMM) external initializer { setOwner(_owner); parlayMarketsAMM = IParlayMarketsAMM(_parlayMarketsAMM); sportsAMM = ISportsAMMTiny(parlayMarketsAMM.sportsAmm()); consumer = sportsAMM.theRundownConsumer(); } function areEligiblePropsMarkets( address _childMarket1, address _childMarket2, uint _tag1 ) external view returns (bool isEligible) { IGamesPlayerProps gamePlayerProps = IGamesPlayerProps(ITherundownConsumer(consumer).playerProps()); if ( eligibleSportForSamePropsCombination[_tag1] && gamePlayerProps.optionIdPerChildMarket(_childMarket1) > 0 && gamePlayerProps.optionIdPerChildMarket(_childMarket1) == gamePlayerProps.optionIdPerChildMarket(_childMarket2) ) { isEligible = true; } } function getSgpFeePerCombination(IParlayPolicy.SGPData memory params) external view returns (uint sgpFee) { sgpFee = parlayMarketsAMM.getSgpFeePerCombination( params.tag1, params.tag2_1, params.tag2_2, params.position1, params.position2 ); } function getMarketDefaultOdds(address _sportMarket, uint _position) external view returns (uint odd) { odd = sportsAMM.getMarketDefaultOdds(_sportMarket, false)[_position]; } function getChildMarketTotalLine(address _sportMarket) external view returns (uint childTotalsLine) { if (ISportPositionalMarket(_sportMarket).isChild()) { childTotalsLine = ISportPositionalMarket(_sportMarket).parentMarket().optionsCount(); if (childTotalsLine > 2) { childTotalsLine = uint( IGamesOddsObtainer(ITherundownConsumer(consumer).oddsObtainer()).childMarketTotal(_sportMarket) ); } } } function setEligibleSportForSamePropsCombination(uint _tag1, bool _eligible) external onlyOwner { eligibleSportForSamePropsCombination[_tag1] = _eligible; emit SetEligibleSportForSamePropsCombination(_tag1, _eligible); } function setParlayMarketsAMM(address _parlayMarketsAMM) external onlyOwner { parlayMarketsAMM = IParlayMarketsAMM(_parlayMarketsAMM); sportsAMM = ISportsAMMTiny(parlayMarketsAMM.sportsAmm()); consumer = sportsAMM.theRundownConsumer(); emit SetParlayMarketsAMM(_parlayMarketsAMM); } modifier onlyParlayAMM() { _onlyParlayAMM(); _; } function _onlyParlayAMM() internal view { require(msg.sender == address(parlayMarketsAMM), "Not ParlayAMM"); } event SetParlayMarketsAMM(address _parlayMarketsAMM); event SetEligibleSportForSamePropsCombination(uint _tag1, bool _eligible); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "../SportMarkets/Parlay/ParlayVerifier.sol"; interface IParlayMarketsAMM { /* ========== VIEWS / VARIABLES ========== */ function parlaySize() external view returns (uint); function sUSD() external view returns (IERC20Upgradeable); function sportsAmm() external view returns (address); function parlayPolicy() external view returns (address); function parlayAmmFee() external view returns (uint); function maxAllowedRiskPerCombination() external view returns (uint); function maxSupportedOdds() external view returns (uint); function getSgpFeePerCombination( uint tag1, uint tag2_1, uint tag2_2, uint position1, uint position2 ) external view returns (uint sgpFee); function riskPerCombination( address _sportMarkets1, uint _position1, address _sportMarkets2, uint _position2, address _sportMarkets3, uint _position3, address _sportMarkets4, uint _position4 ) external view returns (uint); function riskPerGameCombination( address _sportMarkets1, address _sportMarkets2, address _sportMarkets3, address _sportMarkets4, address _sportMarkets5, address _sportMarkets6, address _sportMarkets7, address _sportMarkets8 ) external view returns (uint); function riskPerPackedGamesCombination(bytes32 gamesPacked) external view returns (uint); function isActiveParlay(address _parlayMarket) external view returns (bool isActiveParlayMarket); function exerciseParlay(address _parlayMarket) external; function triggerResolvedEvent(address _account, bool _userWon) external; function resolveParlay() external; function buyFromParlay( address[] calldata _sportMarkets, uint[] calldata _positions, uint _sUSDPaid, uint _additionalSlippage, uint _expectedPayout, address _differentRecepient ) external; function buyQuoteFromParlay( address[] calldata _sportMarkets, uint[] calldata _positions, uint _sUSDPaid ) external view returns ( uint sUSDAfterFees, uint totalBuyAmount, uint totalQuote, uint initialQuote, uint skewImpact, uint[] memory finalQuotes, uint[] memory amountsToBuy ); function canCreateParlayMarket( address[] calldata _sportMarkets, uint[] calldata _positions, uint _sUSDToPay ) external view returns (bool canBeCreated); function numActiveParlayMarkets() external view returns (uint); function activeParlayMarkets(uint index, uint pageSize) external view returns (address[] memory); function parlayVerifier() external view returns (ParlayVerifier); function minUSDAmount() external view returns (uint); function maxSupportedAmount() external view returns (uint); function safeBoxImpact() external view returns (uint); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; import "../interfaces/IPositionalMarketManager.sol"; import "../interfaces/IPosition.sol"; import "../interfaces/IPriceFeed.sol"; interface ISportPositionalMarket { /* ========== TYPES ========== */ enum Phase { Trading, Maturity, Expiry } enum Side { Cancelled, Home, Away, Draw } /* ========== VIEWS / VARIABLES ========== */ function getOptions() external view returns ( IPosition home, IPosition away, IPosition draw ); function times() external view returns (uint maturity, uint destruction); function initialMint() external view returns (uint); function getGameDetails() external view returns (bytes32 gameId, string memory gameLabel); function getGameId() external view returns (bytes32); function deposited() external view returns (uint); function optionsCount() external view returns (uint); function creator() external view returns (address); function resolved() external view returns (bool); function cancelled() external view returns (bool); function paused() external view returns (bool); function phase() external view returns (Phase); function canResolve() external view returns (bool); function result() external view returns (Side); function isChild() external view returns (bool); function tags(uint idx) external view returns (uint); function getTags() external view returns (uint tag1, uint tag2); function getTagsLength() external view returns (uint tagsLength); function getParentMarketPositions() external view returns (IPosition position1, IPosition position2); function getStampedOdds() external view returns ( uint, uint, uint ); function balancesOf(address account) external view returns ( uint home, uint away, uint draw ); function totalSupplies() external view returns ( uint home, uint away, uint draw ); function isDoubleChance() external view returns (bool); function parentMarket() external view returns (ISportPositionalMarket); /* ========== MUTATIVE FUNCTIONS ========== */ function setPaused(bool _paused) external; function updateDates(uint256 _maturity, uint256 _expiry) external; function mint(uint value) external; function exerciseOptions() external; function restoreInvalidOdds( uint _homeOdds, uint _awayOdds, uint _drawOdds ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 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.0; // 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 // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @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 a proxied contract can't have 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. * * 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 initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ISportsAMMTiny { /* ========== VIEWS / VARIABLES ========== */ enum Position { Home, Away, Draw } function theRundownConsumer() external view returns (address); function getMarketDefaultOdds(address _market, bool isSell) external view returns (uint[] memory); function isMarketInAMMTrading(address _market) external view returns (bool); function parlayAMM() external view returns (address); function manager() external view returns (address); function getLiquidityPool() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IParlayPolicy { struct SGPData { uint tag1; uint tag2_1; uint tag2_2; uint position1; uint position2; } /* ========== VIEWS / VARIABLES ========== */ function consumer() external view returns (address); function getSgpFeePerCombination(SGPData memory params) external view returns (uint sgpFee); function getMarketDefaultOdds(address _sportMarket, uint _position) external view returns (uint odd); function areEligiblePropsMarkets( address _childMarket1, address _childMarket2, uint _tag1 ) external view returns (bool samePlayerDifferentProp); function getChildMarketTotalLine(address _sportMarket) external view returns (uint childTotalsLine); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ITherundownConsumer { struct GameCreate { bytes32 gameId; uint256 startTime; int24 homeOdds; int24 awayOdds; int24 drawOdds; string homeTeam; string awayTeam; } // view functions function supportedSport(uint _sportId) external view returns (bool); function gameOnADate(bytes32 _gameId) external view returns (uint); function isGameResolvedOrCanceled(bytes32 _gameId) external view returns (bool); function getNormalizedOddsForMarket(address _market) external view returns (uint[] memory); function getGamesPerDatePerSport(uint _sportId, uint _date) external view returns (bytes32[] memory); function getGamePropsForOdds(address _market) external view returns ( uint, uint, bytes32 ); function gameIdPerMarket(address _market) external view returns (bytes32); function getGameCreatedById(bytes32 _gameId) external view returns (GameCreate memory); function isChildMarket(address _market) external view returns (bool); function gameFulfilledCreated(bytes32 _gameId) external view returns (bool); function playerProps() external view returns (address); function oddsObtainer() external view returns (address); // write functions function fulfillGamesCreated( bytes32 _requestId, bytes[] memory _games, uint _sportsId, uint _date ) external; function fulfillGamesResolved( bytes32 _requestId, bytes[] memory _games, uint _sportsId ) external; function fulfillGamesOdds(bytes32 _requestId, bytes[] memory _games) external; function setPausedByCanceledStatus(address _market, bool _flag) external; function setGameIdPerChildMarket(bytes32 _gameId, address _child) external; function pauseOrUnpauseMarket(address _market, bool _pause) external; function pauseOrUnpauseMarketForPlayerProps( address _market, bool _pause, bool _invalidOdds, bool _circuitBreakerMain ) external; function setChildMarkets( bytes32 _gameId, address _main, address _child, bool _isSpread, int16 _spreadHome, uint24 _totalOver ) external; function resolveMarketManually( address _market, uint _outcome, uint8 _homeScore, uint8 _awayScore, bool _usebackupOdds ) external; function getOddsForGame(bytes32 _gameId) external view returns ( int24, int24, int24 ); function sportsIdPerGame(bytes32 _gameId) external view returns (uint); function getGameStartTime(bytes32 _gameId) external view returns (uint256); function getLastUpdatedFromGameResolve(bytes32 _gameId) external view returns (uint40); function marketPerGameId(bytes32 _gameId) external view returns (address); function marketResolved(address _market) external view returns (bool); function marketCanceled(address _market) external view returns (bool); function invalidOdds(address _market) external view returns (bool); function isPausedByCanceledStatus(address _market) external view returns (bool); function isSportOnADate(uint _date, uint _sportId) external view returns (bool); function isSportTwoPositionsSport(uint _sportsId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IGamesPlayerProps { struct PlayerProps { bytes32 gameId; bytes32 playerId; uint8 option; string playerName; uint16 line; int24 overOdds; int24 underOdds; } struct PlayerPropsResolver { bytes32 gameId; bytes32 playerId; uint8 option; uint16 score; uint8 statusId; } function obtainPlayerProps(PlayerProps memory _player, uint _sportId) external; function resolvePlayerProps(PlayerPropsResolver memory _result) external; function cancelMarketFromManager(address _market) external; function pauseAllPlayerPropsMarketForMain( address _main, bool _flag, bool _invalidOddsOnMain, bool _circuitBreakerMain ) external; function createFulfilledForPlayerProps( bytes32 gameId, bytes32 playerId, uint8 option ) external view returns (bool); function cancelPlayerPropsMarketForMain(address _main) external; function getNormalizedOddsForMarket(address _market) external view returns (uint[] memory); function mainMarketChildMarketIndex(address _main, uint _index) external view returns (address); function numberOfChildMarkets(address _main) external view returns (uint); function doesSportSupportPlayerProps(uint _sportId) external view returns (bool); function pausedByInvalidOddsOnMain(address _main) external view returns (bool); function pausedByCircuitBreakerOnMain(address _main) external view returns (bool); function playerIdPerChildMarket(address _market) external view returns (bytes32); function optionIdPerChildMarket(address _market) external view returns (uint8); function getAllOptionsWithPlayersForGameId(bytes32 _gameId) external view returns ( bytes32[] memory _playerIds, uint8[] memory _options, bool[] memory _isResolved, address[][] memory _childMarketsPerOption ); function getPlayerPropsDataForMarket(address _market) external view returns ( address, bytes32, bytes32, uint8 ); function getPlayerPropForOption( bytes32 gameId, bytes32 playerId, uint8 option ) external view returns ( uint16, int24, int24, bool ); function fulfillPlayerPropsCLResolved(bytes[] memory _playerProps) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IGamesOddsObtainer { struct GameOdds { bytes32 gameId; int24 homeOdds; int24 awayOdds; int24 drawOdds; int16 spreadHome; int24 spreadHomeOdds; int16 spreadAway; int24 spreadAwayOdds; uint24 totalOver; int24 totalOverOdds; uint24 totalUnder; int24 totalUnderOdds; } // view function getActiveChildMarketsFromParent(address _parent) external view returns (address, address); function getSpreadTotalsChildMarketsFromParent(address _parent) external view returns ( uint numOfSpreadMarkets, address[] memory spreadMarkets, uint numOfTotalsMarkets, address[] memory totalMarkets ); function areOddsValid(bytes32 _gameId, bool _useBackup) external view returns (bool); function invalidOdds(address _market) external view returns (bool); function getNormalizedOdds(bytes32 _gameId) external view returns (uint[] memory); function getNormalizedOddsForMarket(address _market) external view returns (uint[] memory); function getOddsForGames(bytes32[] memory _gameIds) external view returns (int24[] memory odds); function mainMarketChildMarketIndex(address _main, uint _index) external view returns (address); function numberOfChildMarkets(address _main) external view returns (uint); function mainMarketSpreadChildMarket(address _main, int16 _spread) external view returns (address); function mainMarketTotalChildMarket(address _main, uint24 _total) external view returns (address); function childMarketMainMarket(address _market) external view returns (address); function childMarketTotal(address _market) external view returns (uint24); function currentActiveTotalChildMarket(address _main) external view returns (address); function currentActiveSpreadChildMarket(address _main) external view returns (address); function isSpreadChildMarket(address _child) external view returns (bool); function childMarketCreated(address _child) external view returns (bool); function getOddsForGame(bytes32 _gameId) external view returns ( int24, int24, int24, int24, int24, int24, int24 ); function getLinesForGame(bytes32 _gameId) external view returns ( int16, int16, uint24, uint24 ); // executable function obtainOdds( bytes32 requestId, GameOdds memory _game, uint _sportId ) external; function setFirstOdds( bytes32 _gameId, int24 _homeOdds, int24 _awayOdds, int24 _drawOdds ) external; function setFirstNormalizedOdds(bytes32 _gameId, address _market) external; function setBackupOddsAsMainOddsForGame(bytes32 _gameId) external; function pauseUnpauseChildMarkets(address _main, bool _flag) external; function pauseUnpauseCurrentActiveChildMarket( bytes32 _gameId, address _main, bool _flag ) external; function resolveChildMarkets( address _market, uint _outcome, uint8 _homeScore, uint8 _awayScore ) external; function setChildMarketGameId(bytes32 gameId, address market) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // interfaces import "../../interfaces/IParlayMarketsAMM.sol"; import "../../interfaces/ISportsAMM.sol"; // import "../../interfaces/IParlayMarketData.sol"; import "../../interfaces/ISportPositionalMarket.sol"; import "../../interfaces/IParlayPolicy.sol"; contract ParlayVerifier { uint private constant ONE = 1e18; uint private constant ONE_PERCENT = 1e16; uint private constant TAG_F1 = 9445; uint private constant TAG_MOTOGP = 9497; uint private constant TAG_GOLF = 100121; uint private constant TAG_NUMBER_SPREAD = 10001; uint private constant TAG_NUMBER_TOTAL = 10002; uint private constant DOUBLE_CHANCE_TAG = 10003; uint private constant PLAYER_PROPS_TAG = 10010; struct InitialQuoteParameters { address[] sportMarkets; uint[] positions; uint totalSUSDToPay; uint parlaySize; uint defaultONE; uint[] sgpFees; ISportsAMM sportsAMM; address parlayAMM; } struct FinalQuoteParameters { address[] sportMarkets; uint[] positions; uint[] buyQuoteAmounts; ISportsAMM sportsAmm; uint sUSDAfterFees; uint defaultONE; uint[] sgpFees; } struct VerifyMarket { address[] sportMarkets; uint[] positions; ISportsAMM sportsAMM; address parlayAMM; } struct CachedMarket { bytes32 gameId; uint gameCounter; } struct CheckSGP { address[] sportMarkets; uint[] positions; uint[] tag1; uint[] tag2; IParlayPolicy parlayPolicy; } /// @notice Verifying if given parlay is able to be created given the policies in state /// @param params VerifyMarket parameters /// @return eligible if the parlay can be created /// @return odds the odds for each position /// @return sgpFees the fees applied per position in case of SameGameParlay function _verifyMarkets(VerifyMarket memory params) internal view returns ( bool eligible, uint[] memory odds, uint[] memory sgpFees ) { eligible = true; uint[] memory tags1; uint[] memory tags2; IParlayPolicy parlayPolicy = IParlayPolicy(IParlayMarketsAMM(params.parlayAMM).parlayPolicy()); (tags1, tags2) = _obtainAllTags(params.sportMarkets); (odds, sgpFees) = _checkSGPAndGetOdds(CheckSGP(params.sportMarkets, params.positions, tags1, tags2, parlayPolicy)); } /// @notice Obtain all the tags for each position and calculate unique ones /// @param sportMarkets the sport markets for the parlay /// @return tag1 all the tags 1 per market /// @return tag2 all the tags 2 per market function _obtainAllTags(address[] memory sportMarkets) internal view returns (uint[] memory tag1, uint[] memory tag2) { tag1 = new uint[](sportMarkets.length); tag2 = new uint[](sportMarkets.length); address sportMarket; for (uint i = 0; i < sportMarkets.length; i++) { // 1. Get all tags for a sport market (tag1, tag2) sportMarket = sportMarkets[i]; tag1[i] = ISportPositionalMarket(sportMarket).tags(0); tag2[i] = ISportPositionalMarket(sportMarket).getTagsLength() > 1 ? ISportPositionalMarket(sportMarket).tags(1) : 0; for (uint j = 0; j < i; j++) { if (sportMarkets[i] == sportMarkets[j]) { revert("SameTeamOnParlay"); } } } } /// @notice Check the names, check if any markets are SGPs, obtain odds and apply fees if needed /// @param params all the parameters to calculate the fees and odds per position /// @return odds all the odds per position /// @return sgpFees all the fees per position function _checkSGPAndGetOdds(CheckSGP memory params) internal view returns (uint[] memory odds, uint[] memory sgpFees) { odds = new uint[](params.sportMarkets.length); sgpFees = new uint[](odds.length); bool[] memory alreadyInSGP = new bool[](sgpFees.length); for (uint i = 0; i < params.sportMarkets.length; i++) { for (uint j = 0; j < i; j++) { if (params.sportMarkets[j] != params.sportMarkets[i]) { if (!alreadyInSGP[j] && params.tag1[j] == params.tag1[i] && (params.tag2[i] > 0 || params.tag2[j] > 0)) { address parentI = address(ISportPositionalMarket(params.sportMarkets[i]).parentMarket()); address parentJ = address(ISportPositionalMarket(params.sportMarkets[j]).parentMarket()); if ( (params.tag2[j] > 0 && parentJ == params.sportMarkets[i]) || (params.tag2[i] > 0 && parentI == params.sportMarkets[j]) || // the following line is for totals + spreads or totals + playerProps (params.tag2[i] > 0 && params.tag2[j] > 0 && parentI == parentJ) ) { uint sgpFee = params.parlayPolicy.getSgpFeePerCombination( IParlayPolicy.SGPData( params.tag1[i], params.tag2[i], params.tag2[j], params.positions[i], params.positions[j] ) ); if (params.tag2[j] == PLAYER_PROPS_TAG && params.tag2[i] == PLAYER_PROPS_TAG) { // check if the markets are elibible props markets if ( !params.parlayPolicy.areEligiblePropsMarkets( params.sportMarkets[i], params.sportMarkets[j], params.tag1[i] ) ) { revert("InvalidPlayerProps"); } } else if (sgpFee == 0) { revert("SameTeamOnParlay"); } else { alreadyInSGP[i] = true; alreadyInSGP[j] = true; if (params.tag2[j] > 0) { (odds[i], odds[j], sgpFees[i], sgpFees[j]) = _getSGPSingleOdds( params.parlayPolicy.getMarketDefaultOdds( params.sportMarkets[i], params.positions[i] ), params.parlayPolicy.getMarketDefaultOdds( params.sportMarkets[j], params.positions[j] ), params.positions[j], sgpFee, params.parlayPolicy.getChildMarketTotalLine(params.sportMarkets[j]) ); } else { (odds[j], odds[i], sgpFees[j], sgpFees[i]) = _getSGPSingleOdds( params.parlayPolicy.getMarketDefaultOdds( params.sportMarkets[j], params.positions[j] ), params.parlayPolicy.getMarketDefaultOdds( params.sportMarkets[i], params.positions[i] ), params.positions[i], sgpFee, params.parlayPolicy.getChildMarketTotalLine(params.sportMarkets[i]) ); } } } } } else { revert("SameTeamOnParlay"); } } if (odds[i] == 0) { odds[i] = params.parlayPolicy.getMarketDefaultOdds(params.sportMarkets[i], params.positions[i]); } } } function getSPGOdds( uint odds1, uint odds2, uint position2, uint sgpFee, uint totalsLine ) external pure returns ( uint resultOdds1, uint resultOdds2, uint sgpFee1, uint sgpFee2 ) { (resultOdds1, resultOdds2, sgpFee1, sgpFee2) = _getSGPSingleOdds(odds1, odds2, position2, sgpFee, totalsLine); } /// @notice Calculate the sgpFees for the positions of two sport markets, given their odds and default sgpfee /// @param odds1 the odd of position 1 (usually the moneyline odd) /// @param odds2 the odd of position 2 (usually the totals/spreads odd) /// @param sgpFee the default sgp fee /// @return resultOdds1 the odd1 /// @return resultOdds2 the odd2 /// @return sgpFee1 the fee for position 1 or odd1 /// @return sgpFee2 the fee for position 2 or odd2 function _getSGPSingleOdds( uint odds1, uint odds2, uint position2, uint sgpFee, uint totalsLine ) internal pure returns ( uint resultOdds1, uint resultOdds2, uint sgpFee1, uint sgpFee2 ) { resultOdds1 = odds1; resultOdds2 = odds2; if (odds1 > 0 && odds2 > 0) { if (totalsLine == 2) { sgpFee2 = sgpFee; } else if (totalsLine == 250) { if (position2 == 0) { if (odds1 < (6 * ONE_PERCENT) && odds2 < (70 * ONE_PERCENT)) { sgpFee2 = sgpFee - (ONE - sgpFee); } else if (odds1 >= (99 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) - 1 * ONE_PERCENT); } else if (odds1 >= (96 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE; } else if (odds1 >= (93 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 75 * ONE_PERCENT) / ONE; } else if (odds1 >= (90 * ONE_PERCENT) && odds2 >= (65 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE; } else if (odds1 >= (83 * ONE_PERCENT) && odds2 >= (98 * ONE_PERCENT)) { sgpFee2 = sgpFee + (5 * ONE_PERCENT); } else if (odds1 >= (83 * ONE_PERCENT) && odds2 >= (52 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds1 >= (80 * ONE_PERCENT) && odds2 >= (74 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 20 * ONE_PERCENT) / ONE; } else if (odds1 >= (80 * ONE_PERCENT) && odds2 >= (70 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else if (odds1 >= (80 * ONE_PERCENT) && odds2 >= (60 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds1 >= (80 * ONE_PERCENT) && odds2 >= (50 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE; } else if (odds2 >= (60 * ONE_PERCENT) && odds1 <= (10 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds2 >= (55 * ONE_PERCENT) && odds1 <= (19 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE; } else if (odds2 >= (55 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 40 * ONE_PERCENT) / ONE; } else if (odds2 >= (54 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE; } else if (odds2 >= (52 * ONE_PERCENT)) { if (odds1 <= (10 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else if (odds1 <= (23 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 45 * ONE_PERCENT) / ONE; } else if (odds1 <= (46 * ONE_PERCENT)) { sgpFee2 = sgpFee + (((5 * ONE_PERCENT) * (ONE - odds1)) / ONE); } else { sgpFee2 = sgpFee; } } else if (odds2 >= (51 * ONE_PERCENT) && odds1 <= (20 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE; } else if (odds2 >= (51 * ONE_PERCENT) && odds1 <= (25 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((sgpFee * 10 * ONE_PERCENT) / ONE); } else if (odds2 >= (50 * ONE_PERCENT)) { if (odds1 < (10 * ONE_PERCENT)) { sgpFee2 = ONE + odds1; } else if (odds1 <= (21 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE; } else if (odds1 <= (23 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds1 <= (56 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE; } else { uint oddsDiff = odds2 > odds1 ? odds2 - odds1 : odds1 - odds2; if (oddsDiff > 0) { oddsDiff = (oddsDiff - (5 * ONE_PERCENT) / (90 * ONE_PERCENT)); oddsDiff = ((ONE - sgpFee) * oddsDiff) / ONE; sgpFee2 = (sgpFee * (ONE + oddsDiff)) / ONE; } else { sgpFee2 = sgpFee; } } } else if (odds2 >= (49 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE; } else if (odds2 >= (48 * ONE_PERCENT) && odds1 <= (20 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds2 >= (48 * ONE_PERCENT) && odds1 <= (40 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 20 * ONE_PERCENT) / ONE; } else if (odds2 >= (48 * ONE_PERCENT) && odds1 <= (50 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 40 * ONE_PERCENT) / ONE; } else if (odds2 >= (48 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds2 >= (46 * ONE_PERCENT) && odds1 <= (43 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else if (odds2 >= (46 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds2 >= (43 * ONE_PERCENT)) { if (odds1 <= (24 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (46 * ONE_PERCENT)) { sgpFee2 = sgpFee > 5 * ONE_PERCENT ? sgpFee - (2 * ONE_PERCENT) : sgpFee; } else { uint oddsDiff = odds2 > odds1 ? odds2 - odds1 : odds1 - odds2; if (oddsDiff > 0) { oddsDiff = (oddsDiff - (5 * ONE_PERCENT) / (90 * ONE_PERCENT)); oddsDiff = ((ONE - sgpFee + (ONE - sgpFee) / 2) * oddsDiff) / ONE; sgpFee2 = (sgpFee * (ONE + oddsDiff)) / ONE; } else { sgpFee2 = sgpFee; } } } else if (odds2 >= (39 * ONE_PERCENT) && odds1 >= (43 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE; } else if (odds2 >= (35 * ONE_PERCENT)) { if (odds1 <= (46 * ONE_PERCENT)) { sgpFee2 = sgpFee - (((ONE - sgpFee) * (ONE - odds1)) / ONE); } else { sgpFee2 = sgpFee > 5 * ONE_PERCENT ? sgpFee - (2 * ONE_PERCENT) : sgpFee; } } else if (odds2 < (35 * ONE_PERCENT)) { if (odds1 <= (46 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 90 * ONE_PERCENT) / ONE; } else { sgpFee2 = sgpFee > 5 * ONE_PERCENT ? sgpFee - (2 * ONE_PERCENT) : sgpFee; } } } else { if (odds2 >= (56 * ONE_PERCENT)) { if (odds2 > (68 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else if (odds1 >= 76 * ONE_PERCENT) { sgpFee2 = (ONE + (15 * ONE_PERCENT) + (odds1 * 15 * ONE_PERCENT) / ONE); } else if (odds1 >= 60 * ONE_PERCENT) { sgpFee2 = ONE + (ONE - sgpFee); } else if (odds2 >= (58 * ONE_PERCENT) && odds1 <= (18 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE; } else if (odds2 >= (58 * ONE_PERCENT) && odds1 <= (32 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE; } else if (odds2 >= (55 * ONE_PERCENT) && odds1 >= (58 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds2 >= (55 * ONE_PERCENT) && odds1 <= (18 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds1 <= 35 * ONE_PERCENT && odds1 >= 30 * ONE_PERCENT) { sgpFee2 = sgpFee; } else if (odds1 <= 15 * ONE_PERCENT) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else { sgpFee2 = (ONE + (15 * ONE_PERCENT) + (odds1 * 10 * ONE_PERCENT) / ONE); } } else if (odds2 <= (32 * ONE_PERCENT) && odds1 >= (65 * ONE_PERCENT)) { sgpFee2 = sgpFee - (ONE - sgpFee); } else if (odds2 <= (32 * ONE_PERCENT) && odds1 >= (85 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE; } else if (odds2 <= (35 * ONE_PERCENT) && odds1 <= (125 * 1e15)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 10 * ONE_PERCENT) / ONE; } else if (odds2 <= (35 * ONE_PERCENT) && odds1 > (125 * 1e15) && odds1 <= (13 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds2 <= (35 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 20 * ONE_PERCENT) / ONE; } else if (odds2 <= (35 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (37 * ONE_PERCENT) && odds1 <= (10 * ONE_PERCENT)) { sgpFee2 = sgpFee - (ONE - sgpFee); } else if (odds2 <= (37 * ONE_PERCENT) && odds1 <= (16 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 60 * ONE_PERCENT) / ONE; } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (80 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee + 5 * ONE_PERCENT); } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (70 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee + 10 * ONE_PERCENT); } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (66 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee + 25 * ONE_PERCENT); } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (50 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee + 5 * ONE_PERCENT); } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (25 * ONE_PERCENT)) { sgpFee2 = ONE + (2 * (ONE - sgpFee)); } else if (odds2 <= (38 * ONE_PERCENT) && odds1 >= (23 * ONE_PERCENT)) { sgpFee2 = sgpFee - ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (38 * ONE_PERCENT) && odds1 < (23 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 40 * ONE_PERCENT) / ONE; } else if (odds2 <= (39 * ONE_PERCENT) && odds1 < (20 * ONE_PERCENT)) { sgpFee2 = sgpFee - (sgpFee * 20 * ONE_PERCENT) / ONE; } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (9 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE; } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (11 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (13 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (14 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE; } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (30 * ONE_PERCENT)) { sgpFee2 = ONE + (sgpFee * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (40 * ONE_PERCENT) && odds1 <= (54 * ONE_PERCENT)) { sgpFee2 = ONE + (sgpFee * 20 * ONE_PERCENT) / ONE; } else if (odds2 <= (40 * ONE_PERCENT) && odds1 > (54 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee); } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (11 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (12 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 75 * ONE_PERCENT) / ONE; } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (14 * ONE_PERCENT)) { sgpFee2 = sgpFee + (sgpFee * 20 * ONE_PERCENT) / ONE; } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) { sgpFee2 = sgpFee - (sgpFee * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (43 * ONE_PERCENT) && odds1 <= (51 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee); } else if (odds2 <= (44 * ONE_PERCENT) && odds1 >= (55 * ONE_PERCENT)) { sgpFee2 = ONE + (sgpFee * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (44 * ONE_PERCENT) && odds1 <= (55 * ONE_PERCENT)) { sgpFee2 = ONE + (sgpFee * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (45 * ONE_PERCENT) && odds1 >= (70 * ONE_PERCENT)) { sgpFee2 = ONE + (2 * (ONE - sgpFee)) - ((ONE - sgpFee) * 40 * ONE_PERCENT) / ONE; } else if (odds2 <= (45 * ONE_PERCENT) && odds1 >= (44 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE; } else if (odds2 <= (45 * ONE_PERCENT) && odds1 >= (40 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 10 * ONE_PERCENT) / ONE; } else if (odds2 <= (45 * ONE_PERCENT) && odds1 >= (20 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE; } else if (odds2 <= (45 * ONE_PERCENT) && odds1 < (20 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (47 * ONE_PERCENT) && odds1 <= (17 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 70 * ONE_PERCENT) / ONE; } else if (odds2 <= (47 * ONE_PERCENT) && odds1 <= (23 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 8 * ONE_PERCENT) / ONE; } else if (odds2 <= (48 * ONE_PERCENT) && odds1 <= (11 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE; } else if (odds2 <= (48 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) { sgpFee2 = sgpFee + (sgpFee * 20 * ONE_PERCENT) / ONE; } else if (odds2 <= (49 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (49 * ONE_PERCENT) && odds1 <= (25 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 80 * ONE_PERCENT) / ONE; } else if (odds2 <= (49 * ONE_PERCENT) && odds1 <= (33 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds2 <= (50 * ONE_PERCENT) && odds1 <= (10 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else if (odds2 <= (50 * ONE_PERCENT) && odds1 <= (17 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 35 * ONE_PERCENT) / ONE; } else if (odds2 <= (50 * ONE_PERCENT) && odds1 <= (20 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee); } else if (odds2 <= (50 * ONE_PERCENT) && odds1 <= (25 * ONE_PERCENT)) { sgpFee2 = sgpFee - (ONE - sgpFee) - (ONE - sgpFee); } else if (odds2 <= (51 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) { sgpFee2 = sgpFee; } else if (odds2 <= (52 * ONE_PERCENT) && odds1 <= (10 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 35 * ONE_PERCENT) / ONE; } else if (odds2 <= (52 * ONE_PERCENT) && odds1 <= (15 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 45 * ONE_PERCENT) / ONE; } else if (odds2 <= (52 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 35 * ONE_PERCENT) / ONE; } else if (odds2 <= (52 * ONE_PERCENT) && odds1 > (72 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 35 * ONE_PERCENT) / ONE; } else if (odds2 <= (53 * ONE_PERCENT) && odds1 <= (24 * ONE_PERCENT)) { sgpFee2 = ONE + (sgpFee * 30 * ONE_PERCENT) / ONE; } else if (odds2 <= (53 * ONE_PERCENT) && odds1 <= (40 * ONE_PERCENT)) { sgpFee2 = ONE; } else if (odds2 < (54 * ONE_PERCENT) && odds1 >= (74 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee); } else if (odds2 < (54 * ONE_PERCENT) && odds1 >= (58 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee + 10 * ONE_PERCENT); } else if (odds2 < (54 * ONE_PERCENT) && odds1 >= (24 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee); } else if (odds2 < (54 * ONE_PERCENT) && odds1 < (24 * ONE_PERCENT)) { sgpFee2 = sgpFee + ((ONE - sgpFee) * 30 * ONE_PERCENT) / ONE; } else if (odds2 < (56 * ONE_PERCENT) && odds1 >= (82 * ONE_PERCENT)) { sgpFee2 = ONE + ((ONE - sgpFee) * 50 * ONE_PERCENT) / ONE; } else if (odds2 < (56 * ONE_PERCENT) && odds1 >= (40 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee); } else if (odds2 < (56 * ONE_PERCENT) && odds1 >= (10 * ONE_PERCENT)) { sgpFee2 = ONE + (ONE - sgpFee); } else { sgpFee2 = sgpFee; } } } else { sgpFee2 = sgpFee; } if (sgpFee2 > 0) { uint totalQuote = (odds1 * odds2) / ONE; uint totalQuoteWSGP = ((totalQuote * ONE * ONE) / sgpFee2) / ONE; if (totalQuoteWSGP < (10 * ONE_PERCENT)) { if (odds1 > (10 * ONE_PERCENT)) { sgpFee2 = ((totalQuote * ONE * ONE) / (10 * ONE_PERCENT)) / ONE; } else { sgpFee2 = ((totalQuote * ONE * ONE) / (odds1 - ((odds1 * 10 * ONE_PERCENT) / ONE))) / ONE; } } else if (totalQuoteWSGP > odds1 && odds1 < odds2) { sgpFee2 = odds2 + (4 * 1e15); } else if (totalQuoteWSGP > odds2 && odds2 <= odds1) { sgpFee2 = odds1 + (4 * 1e15); } } } } function calculateInitialQuotesForParlay(InitialQuoteParameters memory params) external view returns ( uint totalQuote, uint totalBuyAmount, uint skewImpact, uint[] memory finalQuotes, uint[] memory amountsToBuy ) { uint numOfMarkets = params.sportMarkets.length; uint inverseSum; bool eligible; uint[] memory marketOdds; (eligible, marketOdds, params.sgpFees) = _verifyMarkets( VerifyMarket(params.sportMarkets, params.positions, params.sportsAMM, params.parlayAMM) ); if (eligible && numOfMarkets == params.positions.length && numOfMarkets > 0 && numOfMarkets <= params.parlaySize) { finalQuotes = new uint[](numOfMarkets); amountsToBuy = new uint[](numOfMarkets); for (uint i = 0; i < numOfMarkets; i++) { if (params.positions[i] > 2) { totalQuote = 0; break; } if (marketOdds.length == 0) { totalQuote = 0; break; } finalQuotes[i] = (params.defaultONE * marketOdds[i]); totalQuote = totalQuote == 0 ? finalQuotes[i] : (totalQuote * finalQuotes[i]) / ONE; skewImpact = skewImpact + finalQuotes[i]; // use as inverseQuotes finalQuotes[i] = ONE - finalQuotes[i]; inverseSum = inverseSum + finalQuotes[i]; if (totalQuote == 0) { totalQuote = 0; break; } } if (totalQuote > 0) { for (uint i = 0; i < finalQuotes.length; i++) { // use finalQuotes as inverseQuotes in equation // skewImpact is sumOfQuotes // inverseSum is sum of InverseQuotes amountsToBuy[i] = ((ONE * finalQuotes[i] * params.totalSUSDToPay * skewImpact)) / (totalQuote * inverseSum * skewImpact); } (totalQuote, totalBuyAmount, skewImpact, finalQuotes, amountsToBuy) = calculateFinalQuotes( FinalQuoteParameters( params.sportMarkets, params.positions, amountsToBuy, params.sportsAMM, params.totalSUSDToPay, params.defaultONE, params.sgpFees ) ); } } } function calculateFinalQuotes(FinalQuoteParameters memory params) internal view returns ( uint totalQuote, uint totalBuyAmount, uint skewImpact, uint[] memory finalQuotes, uint[] memory buyAmountPerMarket ) { uint[] memory buyQuoteAmountPerMarket = new uint[](params.sportMarkets.length); buyAmountPerMarket = params.buyQuoteAmounts; finalQuotes = new uint[](params.sportMarkets.length); uint feesIncluded; for (uint i = 0; i < params.sportMarkets.length; i++) { totalBuyAmount += params.buyQuoteAmounts[i]; // buyQuote always calculated with added SportsAMM fees buyQuoteAmountPerMarket[i] = (params.defaultONE * params.sportsAmm.buyFromAmmQuote( params.sportMarkets[i], obtainSportsAMMPosition(params.positions[i]), params.buyQuoteAmounts[i] )); if (buyQuoteAmountPerMarket[i] == 0) { totalQuote = 0; totalBuyAmount = 0; } } for (uint i = 0; i < params.sportMarkets.length; i++) { finalQuotes[i] = ((buyQuoteAmountPerMarket[i] * ONE * ONE) / params.buyQuoteAmounts[i]) / ONE; // where the SGP fee is actually applied if (params.sgpFees[i] > 0) { finalQuotes[i] = ((finalQuotes[i] * ONE * ONE) / params.sgpFees[i]) / ONE; feesIncluded += params.sgpFees[i] > ONE ? params.sgpFees[i] - ONE : (ONE - params.sgpFees[i]); } totalQuote = (i == 0) ? finalQuotes[i] : (totalQuote * finalQuotes[i]) / ONE; } if (totalQuote > 0) { if (totalQuote < IParlayMarketsAMM(params.sportsAmm.parlayAMM()).maxSupportedOdds()) { totalQuote = IParlayMarketsAMM(params.sportsAmm.parlayAMM()).maxSupportedOdds(); } uint expectedPayout = ((params.sUSDAfterFees * ONE * ONE) / totalQuote) / ONE; skewImpact = expectedPayout > totalBuyAmount ? (((ONE * expectedPayout) - (ONE * totalBuyAmount)) / (totalBuyAmount)) : (((ONE * totalBuyAmount) - (ONE * expectedPayout)) / (totalBuyAmount)); buyAmountPerMarket = _applySkewImpactBatch(buyAmountPerMarket, skewImpact, (expectedPayout > totalBuyAmount)); totalBuyAmount = _applySkewImpact(totalBuyAmount, skewImpact, (expectedPayout > totalBuyAmount)); _calculateRisk(params.sportMarkets, (totalBuyAmount - params.sUSDAfterFees), params.sportsAmm.parlayAMM()); if (feesIncluded > 0) { if (skewImpact > feesIncluded) { skewImpact = skewImpact - feesIncluded; } else { skewImpact = feesIncluded - skewImpact; } } } else { totalBuyAmount = 0; } } function _applySkewImpact( uint _value, uint _skewImpact, bool _addition ) internal pure returns (uint newValue) { newValue = _addition ? (((ONE + _skewImpact) * _value) / ONE) : (((ONE - _skewImpact) * _value) / ONE); } function _applySkewImpactBatch( uint[] memory _values, uint _skewImpact, bool _addition ) internal pure returns (uint[] memory newValues) { newValues = new uint[](_values.length); for (uint i = 0; i < _values.length; i++) { newValues[i] = _applySkewImpact(_values[i], _skewImpact, _addition); } } function obtainSportsAMMPosition(uint _position) public pure returns (ISportsAMM.Position) { if (_position == 0) { return ISportsAMM.Position.Home; } else if (_position == 1) { return ISportsAMM.Position.Away; } return ISportsAMM.Position.Draw; } function _calculateRisk( address[] memory _sportMarkets, uint _sUSDInRisky, address _parlayAMM ) internal view returns (bool riskFree) { require(_checkRisk(_sportMarkets, _sUSDInRisky, _parlayAMM), "RiskPerComb exceeded"); riskFree = true; } function _checkRisk( address[] memory _sportMarkets, uint _sUSDInRisk, address _parlayAMM ) internal view returns (bool riskFree) { if (_sportMarkets.length > 1 && _sportMarkets.length <= IParlayMarketsAMM(_parlayAMM).parlaySize()) { uint riskCombination = IParlayMarketsAMM(_parlayAMM).riskPerPackedGamesCombination( _calculateCombinationKey(_sportMarkets) ); riskFree = (riskCombination + _sUSDInRisk) <= IParlayMarketsAMM(_parlayAMM).maxAllowedRiskPerCombination(); } } function _calculateCombinationKey(address[] memory _sportMarkets) internal pure returns (bytes32) { address[] memory sortedAddresses = new address[](_sportMarkets.length); sortedAddresses = _sort(_sportMarkets); return keccak256(abi.encodePacked(sortedAddresses)); } function _sort(address[] memory data) internal pure returns (address[] memory) { _quickSort(data, int(0), int(data.length - 1)); return data; } function _quickSort( address[] memory arr, int left, int right ) internal pure { int i = left; int j = right; if (i == j) return; address pivot = arr[uint(left + (right - left) / 2)]; while (i <= j) { while (arr[uint(i)] < pivot) i++; while (pivot < arr[uint(j)]) j--; if (i <= j) { (arr[uint(i)], arr[uint(j)]) = (arr[uint(j)], arr[uint(i)]); i++; j--; } } if (left < j) _quickSort(arr, left, j); if (i < right) _quickSort(arr, i, right); } function sort(address[] memory data) external pure returns (address[] memory) { _quickSort(data, int(0), int(data.length - 1)); return data; } function applySkewImpact( uint _value, uint _skewImpact, bool _addition ) external pure returns (uint newValue) { newValue = _applySkewImpact(_value, _skewImpact, _addition); } function calculateCombinationKey(address[] memory _sportMarkets) external pure returns (bytes32) { return _calculateCombinationKey(_sportMarkets); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../interfaces/ISportAMMRiskManager.sol"; interface ISportsAMM { /* ========== VIEWS / VARIABLES ========== */ enum Position { Home, Away, Draw } struct SellRequirements { address user; address market; Position position; uint amount; uint expectedPayout; uint additionalSlippage; } function theRundownConsumer() external view returns (address); function riskManager() external view returns (ISportAMMRiskManager riskManager); function getMarketDefaultOdds(address _market, bool isSell) external view returns (uint[] memory); function isMarketInAMMTrading(address _market) external view returns (bool); function isMarketForSportOnePositional(uint _tag) external view returns (bool); function availableToBuyFromAMM(address market, Position position) external view returns (uint _available); function parlayAMM() external view returns (address); function minSupportedOdds() external view returns (uint); function maxSupportedOdds() external view returns (uint); function minSupportedOddsPerSport(uint) external view returns (uint); function min_spread() external view returns (uint); function max_spread() external view returns (uint); function minimalTimeLeftToMaturity() external view returns (uint); function getSpentOnGame(address market) external view returns (uint); function safeBoxImpact() external view returns (uint); function manager() external view returns (address); function getLiquidityPool() external view returns (address); function buyFromAMM( address market, Position position, uint amount, uint expectedPayout, uint additionalSlippage ) external; function buyFromAmmQuote( address market, Position position, uint amount ) external view returns (uint); function buyFromAmmQuoteForParlayAMM( address market, Position position, uint amount ) external view returns (uint); function updateParlayVolume(address _account, uint _amount) external; function buyPriceImpact( address market, ISportsAMM.Position position, uint amount ) external view returns (int impact); function obtainOdds(address _market, ISportsAMM.Position _position) external view returns (uint oddsToReturn); function buyFromAmmQuoteWithDifferentCollateral( address market, ISportsAMM.Position position, uint amount, address collateral ) external view returns (uint collateralQuote, uint sUSDToPay); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ISportAMMRiskManager { function calculateCapToBeUsed(address _market) external view returns (uint toReturn); function isTotalSpendingLessThanTotalRisk(uint _totalSpent, address _market) external view returns (bool _isNotRisky); function isMarketForSportOnePositional(uint _tag) external view returns (bool); function isMarketForPlayerPropsOnePositional(uint _tag) external view returns (bool); function minSupportedOddsPerSport(uint tag) external view returns (uint); function minSpreadPerSport(uint tag1, uint tag2) external view returns (uint); function maxSpreadPerSport(uint tag) external view returns (uint); function getMinSpreadToUse( bool useDefaultMinSpread, address market, uint min_spread, uint min_spreadPerAddress ) external view returns (uint); function getMaxSpreadForMarket(address _market, uint max_spread) external view returns (uint); function getMinOddsForMarket(address _market, uint minSupportedOdds) external view returns (uint minOdds); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; import "../interfaces/IPositionalMarket.sol"; interface IPositionalMarketManager { /* ========== VIEWS / VARIABLES ========== */ function durations() external view returns (uint expiryDuration, uint maxTimeToMaturity); function capitalRequirement() external view returns (uint); function marketCreationEnabled() external view returns (bool); function onlyAMMMintingAndBurning() external view returns (bool); function transformCollateral(uint value) external view returns (uint); function reverseTransformCollateral(uint value) external view returns (uint); function totalDeposited() external view returns (uint); function numActiveMarkets() external view returns (uint); function activeMarkets(uint index, uint pageSize) external view returns (address[] memory); function numMaturedMarkets() external view returns (uint); function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory); function isActiveMarket(address candidate) external view returns (bool); function isKnownMarket(address candidate) external view returns (bool); function getThalesAMM() external view returns (address); /* ========== MUTATIVE FUNCTIONS ========== */ function createMarket( bytes32 oracleKey, uint strikePrice, uint maturity, uint initialMint // initial sUSD to mint options for, ) external returns (IPositionalMarket); function resolveMarket(address market) external; function expireMarkets(address[] calldata market) external; function transferSusdTo( address sender, address receiver, uint amount ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; import "./IPositionalMarket.sol"; interface IPosition { /* ========== VIEWS / VARIABLES ========== */ function getBalanceOf(address account) external view returns (uint); function getTotalSupply() external view returns (uint); function exerciseWithAmount(address claimant, uint amount) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; interface IPriceFeed { // Structs struct RateAndUpdatedTime { uint216 rate; uint40 time; } // Mutative functions function addAggregator(bytes32 currencyKey, address aggregatorAddress) external; function removeAggregator(bytes32 currencyKey) external; // Views function rateForCurrency(bytes32 currencyKey) external view returns (uint); function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time); function getRates() external view returns (uint[] memory); function getCurrencies() external view returns (bytes32[] memory); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; import "../interfaces/IPositionalMarketManager.sol"; import "../interfaces/IPosition.sol"; import "../interfaces/IPriceFeed.sol"; interface IPositionalMarket { /* ========== TYPES ========== */ enum Phase { Trading, Maturity, Expiry } enum Side { Up, Down } /* ========== VIEWS / VARIABLES ========== */ function getOptions() external view returns (IPosition up, IPosition down); function times() external view returns (uint maturity, uint destructino); function getOracleDetails() external view returns ( bytes32 key, uint strikePrice, uint finalPrice ); function fees() external view returns (uint poolFee, uint creatorFee); function deposited() external view returns (uint); function creator() external view returns (address); function resolved() external view returns (bool); function phase() external view returns (Phase); function oraclePrice() external view returns (uint); function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt); function canResolve() external view returns (bool); function result() external view returns (Side); function balancesOf(address account) external view returns (uint up, uint down); function totalSupplies() external view returns (uint up, uint down); function getMaximumBurnable(address account) external view returns (uint amount); /* ========== MUTATIVE FUNCTIONS ========== */ function mint(uint value) external; function exerciseOptions() external returns (uint); function burnOptions(uint amount) external; function burnOptionsMaximum() external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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":"uint256","name":"_tag1","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_eligible","type":"bool"}],"name":"SetEligibleSportForSamePropsCombination","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_parlayMarketsAMM","type":"address"}],"name":"SetParlayMarketsAMM","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_childMarket1","type":"address"},{"internalType":"address","name":"_childMarket2","type":"address"},{"internalType":"uint256","name":"_tag1","type":"uint256"}],"name":"areEligiblePropsMarkets","outputs":[{"internalType":"bool","name":"isEligible","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"consumer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"eligibleSportForSamePropsCombination","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sportMarket","type":"address"}],"name":"getChildMarketTotalLine","outputs":[{"internalType":"uint256","name":"childTotalsLine","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sportMarket","type":"address"},{"internalType":"uint256","name":"_position","type":"uint256"}],"name":"getMarketDefaultOdds","outputs":[{"internalType":"uint256","name":"odd","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"tag1","type":"uint256"},{"internalType":"uint256","name":"tag2_1","type":"uint256"},{"internalType":"uint256","name":"tag2_2","type":"uint256"},{"internalType":"uint256","name":"position1","type":"uint256"},{"internalType":"uint256","name":"position2","type":"uint256"}],"internalType":"struct IParlayPolicy.SGPData","name":"params","type":"tuple"}],"name":"getSgpFeePerCombination","outputs":[{"internalType":"uint256","name":"sgpFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_parlayMarketsAMM","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastPauseTime","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":"parlayMarketsAMM","outputs":[{"internalType":"contract IParlayMarketsAMM","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tag1","type":"uint256"},{"internalType":"bool","name":"_eligible","type":"bool"}],"name":"setEligibleSportForSamePropsCombination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_parlayMarketsAMM","type":"address"}],"name":"setParlayMarketsAMM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sportsAMM","outputs":[{"internalType":"contract ISportsAMMTiny","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061151e806100206000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806379ba5097116100ad578063be583ec711610071578063be583ec714610286578063c3b83f5f1461029e578063c9925288146102b1578063ec748e39146102c4578063febec2a7146102d757600080fd5b806379ba5097146102365780638da5cb5b1461023e57806391b4ded914610257578063a2abdac514610260578063b4fd72961461027357600080fd5b806340c5336c116100f457806340c5336c146101b7578063485cc955146101d857806353a47bb7146101eb5780635c975abb14610216578063699c2c601461022357600080fd5b806313af4035146101315780631627540c1461014657806316c38b3c1461015957806327ae1b0c1461016c578063363021151461017f575b600080fd5b61014461013f3660046111b5565b6102ea565b005b6101446101543660046111b5565b61042a565b61014461016736600461133f565b610480565b61014461017a366004611439565b6104f6565b6101a261018d366004611409565b60066020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6101ca6101c536600461126c565b610557565b6040519081526020016101ae565b6101446101e63660046111f4565b610614565b6001546101fe906001600160a01b031681565b6040516001600160a01b0390911681526020016101ae565b6003546101a29060ff1681565b6101ca6102313660046111b5565b61082f565b610144610aa1565b6000546101fe906201000090046001600160a01b031681565b6101ca60025481565b6101a261026e36600461122c565b610b9e565b6005546101fe906001600160a01b031681565b6003546101fe9061010090046001600160a01b031681565b6101446102ac3660046111b5565b610ddc565b6004546101fe906001600160a01b031681565b6101ca6102d2366004611377565b610ef5565b6101446102e53660046111b5565b610fae565b6001600160a01b0381166103455760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f7420626520300000000000000060448201526064015b60405180910390fd5b600154600160a01b900460ff16156103b15760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b606482015260840161033c565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b03831662010000810262010000600160b01b03199092169190911782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91015b60405180910390a150565b61043261113b565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200161041f565b61048861113b565b60035460ff161515811515141561049c5750565b6003805460ff191682151590811790915560ff16156104ba57426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59060200161041f565b50565b6104fe61113b565b600082815260066020908152604091829020805460ff19168415159081179091558251858152918201527f783b7e53ceac0b3ac526bc9b95f9360c69b44afa4e22a7efe33b9bc764b01815910160405180910390a15050565b6004805460405163115fbe5b60e31b81526001600160a01b03858116938201939093526000602482018190529290911690638afdf2d89060440160006040518083038186803b1580156105a957600080fd5b505afa1580156105bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105e59190810190611297565b828151811061060457634e487b7160e01b600052603260045260246000fd5b6020026020010151905092915050565b600054610100900460ff1661062f5760005460ff1615610633565b303b155b6106965760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161033c565b600054610100900460ff161580156106b8576000805461ffff19166101011790555b6106c1836102ea565b81600360016101000a8154816001600160a01b0302191690836001600160a01b03160217905550600360019054906101000a90046001600160a01b03166001600160a01b031663e2cc8e976040518163ffffffff1660e01b815260040160206040518083038186803b15801561073657600080fd5b505afa15801561074a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076e91906111d8565b600480546001600160a01b0319166001600160a01b039290921691821781556040805163bb96af6560e01b8152905163bb96af6592828101926020929190829003018186803b1580156107c057600080fd5b505afa1580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f891906111d8565b600580546001600160a01b0319166001600160a01b0392909216919091179055801561082a576000805461ff00191690555b505050565b6000816001600160a01b03166311f2d4946040518163ffffffff1660e01b815260040160206040518083038186803b15801561086a57600080fd5b505afa15801561087e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a2919061135b565b15610a9c57816001600160a01b031663d03ecc646040518163ffffffff1660e01b815260040160206040518083038186803b1580156108e057600080fd5b505afa1580156108f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091891906111d8565b6001600160a01b0316631a1dbabb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561095057600080fd5b505afa158015610964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109889190611421565b90506002811115610a9c57600560009054906101000a90046001600160a01b03166001600160a01b031663ad6b22ce6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109e157600080fd5b505afa1580156109f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1991906111d8565b6040516393ff69d760e01b81526001600160a01b03848116600483015291909116906393ff69d79060240160206040518083038186803b158015610a5c57600080fd5b505afa158015610a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9491906113e6565b62ffffff1690505b919050565b6001546001600160a01b03163314610b195760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b606482015260840161033c565b60005460015460408051620100009093046001600160a01b03908116845290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b600080600560009054906101000a90046001600160a01b03166001600160a01b0316635d7fb8e26040518163ffffffff1660e01b815260040160206040518083038186803b158015610bef57600080fd5b505afa158015610c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2791906111d8565b60008481526006602052604090205490915060ff168015610cc5575060405163dc8ad5cb60e01b81526001600160a01b0386811660048301526000919083169063dc8ad5cb9060240160206040518083038186803b158015610c8857600080fd5b505afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc0919061145d565b60ff16115b8015610dca575060405163dc8ad5cb60e01b81526001600160a01b03858116600483015282169063dc8ad5cb9060240160206040518083038186803b158015610d0d57600080fd5b505afa158015610d21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d45919061145d565b60405163dc8ad5cb60e01b81526001600160a01b03878116600483015260ff929092169183169063dc8ad5cb9060240160206040518083038186803b158015610d8d57600080fd5b505afa158015610da1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc5919061145d565b60ff16145b15610dd457600191505b509392505050565b610de461113b565b6001600160a01b038116610e2c5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640161033c565b600154600160a81b900460ff1615610e7c5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015260640161033c565b600080546001600160a01b038381166201000081810262010000600160b01b031990941693909317938490556001805460ff60a81b1916600160a81b1790556040805193909404909116825260208201527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910161041f565b60035481516020830151604080850151606086015160808701519251630bdc010d60e21b81526004810195909552602485019390935260448401526064830191909152608482015260009161010090046001600160a01b031690632f7004349060a40160206040518083038186803b158015610f7057600080fd5b505afa158015610f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa89190611421565b92915050565b610fb661113b565b80600360016101000a8154816001600160a01b0302191690836001600160a01b03160217905550600360019054906101000a90046001600160a01b03166001600160a01b031663e2cc8e976040518163ffffffff1660e01b815260040160206040518083038186803b15801561102b57600080fd5b505afa15801561103f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106391906111d8565b600480546001600160a01b0319166001600160a01b039290921691821781556040805163bb96af6560e01b8152905163bb96af6592828101926020929190829003018186803b1580156110b557600080fd5b505afa1580156110c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ed91906111d8565b600580546001600160a01b0319166001600160a01b0392831617905560405190821681527f8ead60d861e7aa1c4dd085c83f22affb53c375d4de371a5c6d41ab9ab2f0a18c9060200161041f565b6000546201000090046001600160a01b031633146111b35760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b606482015260840161033c565b565b6000602082840312156111c6578081fd5b81356111d1816114c5565b9392505050565b6000602082840312156111e9578081fd5b81516111d1816114c5565b60008060408385031215611206578081fd5b8235611211816114c5565b91506020830135611221816114c5565b809150509250929050565b600080600060608486031215611240578081fd5b833561124b816114c5565b9250602084013561125b816114c5565b929592945050506040919091013590565b6000806040838503121561127e578182fd5b8235611289816114c5565b946020939093013593505050565b600060208083850312156112a9578182fd5b825167ffffffffffffffff808211156112c0578384fd5b818501915085601f8301126112d3578384fd5b8151818111156112e5576112e56114af565b8060051b91506112f684830161147e565b8181528481019084860184860187018a1015611310578788fd5b8795505b83861015611332578051835260019590950194918601918601611314565b5098975050505050505050565b600060208284031215611350578081fd5b81356111d1816114da565b60006020828403121561136c578081fd5b81516111d1816114da565b600060a08284031215611388578081fd5b60405160a0810181811067ffffffffffffffff821117156113ab576113ab6114af565b806040525082358152602083013560208201526040830135604082015260608301356060820152608083013560808201528091505092915050565b6000602082840312156113f7578081fd5b815162ffffff811681146111d1578182fd5b60006020828403121561141a578081fd5b5035919050565b600060208284031215611432578081fd5b5051919050565b6000806040838503121561144b578182fd5b823591506020830135611221816114da565b60006020828403121561146e578081fd5b815160ff811681146111d1578182fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114a7576114a76114af565b604052919050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146104f357600080fd5b80151581146104f357600080fdfea26469706673582212203e125ba39ac77d576bd605d10ca2355d1ef6dd5d7bf6ca6c3e456aa02103eb6e64736f6c63430008040033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806379ba5097116100ad578063be583ec711610071578063be583ec714610286578063c3b83f5f1461029e578063c9925288146102b1578063ec748e39146102c4578063febec2a7146102d757600080fd5b806379ba5097146102365780638da5cb5b1461023e57806391b4ded914610257578063a2abdac514610260578063b4fd72961461027357600080fd5b806340c5336c116100f457806340c5336c146101b7578063485cc955146101d857806353a47bb7146101eb5780635c975abb14610216578063699c2c601461022357600080fd5b806313af4035146101315780631627540c1461014657806316c38b3c1461015957806327ae1b0c1461016c578063363021151461017f575b600080fd5b61014461013f3660046111b5565b6102ea565b005b6101446101543660046111b5565b61042a565b61014461016736600461133f565b610480565b61014461017a366004611439565b6104f6565b6101a261018d366004611409565b60066020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6101ca6101c536600461126c565b610557565b6040519081526020016101ae565b6101446101e63660046111f4565b610614565b6001546101fe906001600160a01b031681565b6040516001600160a01b0390911681526020016101ae565b6003546101a29060ff1681565b6101ca6102313660046111b5565b61082f565b610144610aa1565b6000546101fe906201000090046001600160a01b031681565b6101ca60025481565b6101a261026e36600461122c565b610b9e565b6005546101fe906001600160a01b031681565b6003546101fe9061010090046001600160a01b031681565b6101446102ac3660046111b5565b610ddc565b6004546101fe906001600160a01b031681565b6101ca6102d2366004611377565b610ef5565b6101446102e53660046111b5565b610fae565b6001600160a01b0381166103455760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f7420626520300000000000000060448201526064015b60405180910390fd5b600154600160a01b900460ff16156103b15760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b606482015260840161033c565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b03831662010000810262010000600160b01b03199092169190911782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91015b60405180910390a150565b61043261113b565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200161041f565b61048861113b565b60035460ff161515811515141561049c5750565b6003805460ff191682151590811790915560ff16156104ba57426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59060200161041f565b50565b6104fe61113b565b600082815260066020908152604091829020805460ff19168415159081179091558251858152918201527f783b7e53ceac0b3ac526bc9b95f9360c69b44afa4e22a7efe33b9bc764b01815910160405180910390a15050565b6004805460405163115fbe5b60e31b81526001600160a01b03858116938201939093526000602482018190529290911690638afdf2d89060440160006040518083038186803b1580156105a957600080fd5b505afa1580156105bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105e59190810190611297565b828151811061060457634e487b7160e01b600052603260045260246000fd5b6020026020010151905092915050565b600054610100900460ff1661062f5760005460ff1615610633565b303b155b6106965760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161033c565b600054610100900460ff161580156106b8576000805461ffff19166101011790555b6106c1836102ea565b81600360016101000a8154816001600160a01b0302191690836001600160a01b03160217905550600360019054906101000a90046001600160a01b03166001600160a01b031663e2cc8e976040518163ffffffff1660e01b815260040160206040518083038186803b15801561073657600080fd5b505afa15801561074a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076e91906111d8565b600480546001600160a01b0319166001600160a01b039290921691821781556040805163bb96af6560e01b8152905163bb96af6592828101926020929190829003018186803b1580156107c057600080fd5b505afa1580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f891906111d8565b600580546001600160a01b0319166001600160a01b0392909216919091179055801561082a576000805461ff00191690555b505050565b6000816001600160a01b03166311f2d4946040518163ffffffff1660e01b815260040160206040518083038186803b15801561086a57600080fd5b505afa15801561087e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a2919061135b565b15610a9c57816001600160a01b031663d03ecc646040518163ffffffff1660e01b815260040160206040518083038186803b1580156108e057600080fd5b505afa1580156108f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091891906111d8565b6001600160a01b0316631a1dbabb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561095057600080fd5b505afa158015610964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109889190611421565b90506002811115610a9c57600560009054906101000a90046001600160a01b03166001600160a01b031663ad6b22ce6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109e157600080fd5b505afa1580156109f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1991906111d8565b6040516393ff69d760e01b81526001600160a01b03848116600483015291909116906393ff69d79060240160206040518083038186803b158015610a5c57600080fd5b505afa158015610a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9491906113e6565b62ffffff1690505b919050565b6001546001600160a01b03163314610b195760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b606482015260840161033c565b60005460015460408051620100009093046001600160a01b03908116845290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b600080600560009054906101000a90046001600160a01b03166001600160a01b0316635d7fb8e26040518163ffffffff1660e01b815260040160206040518083038186803b158015610bef57600080fd5b505afa158015610c03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2791906111d8565b60008481526006602052604090205490915060ff168015610cc5575060405163dc8ad5cb60e01b81526001600160a01b0386811660048301526000919083169063dc8ad5cb9060240160206040518083038186803b158015610c8857600080fd5b505afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc0919061145d565b60ff16115b8015610dca575060405163dc8ad5cb60e01b81526001600160a01b03858116600483015282169063dc8ad5cb9060240160206040518083038186803b158015610d0d57600080fd5b505afa158015610d21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d45919061145d565b60405163dc8ad5cb60e01b81526001600160a01b03878116600483015260ff929092169183169063dc8ad5cb9060240160206040518083038186803b158015610d8d57600080fd5b505afa158015610da1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc5919061145d565b60ff16145b15610dd457600191505b509392505050565b610de461113b565b6001600160a01b038116610e2c5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640161033c565b600154600160a81b900460ff1615610e7c5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015260640161033c565b600080546001600160a01b038381166201000081810262010000600160b01b031990941693909317938490556001805460ff60a81b1916600160a81b1790556040805193909404909116825260208201527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910161041f565b60035481516020830151604080850151606086015160808701519251630bdc010d60e21b81526004810195909552602485019390935260448401526064830191909152608482015260009161010090046001600160a01b031690632f7004349060a40160206040518083038186803b158015610f7057600080fd5b505afa158015610f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa89190611421565b92915050565b610fb661113b565b80600360016101000a8154816001600160a01b0302191690836001600160a01b03160217905550600360019054906101000a90046001600160a01b03166001600160a01b031663e2cc8e976040518163ffffffff1660e01b815260040160206040518083038186803b15801561102b57600080fd5b505afa15801561103f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106391906111d8565b600480546001600160a01b0319166001600160a01b039290921691821781556040805163bb96af6560e01b8152905163bb96af6592828101926020929190829003018186803b1580156110b557600080fd5b505afa1580156110c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ed91906111d8565b600580546001600160a01b0319166001600160a01b0392831617905560405190821681527f8ead60d861e7aa1c4dd085c83f22affb53c375d4de371a5c6d41ab9ab2f0a18c9060200161041f565b6000546201000090046001600160a01b031633146111b35760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b606482015260840161033c565b565b6000602082840312156111c6578081fd5b81356111d1816114c5565b9392505050565b6000602082840312156111e9578081fd5b81516111d1816114c5565b60008060408385031215611206578081fd5b8235611211816114c5565b91506020830135611221816114c5565b809150509250929050565b600080600060608486031215611240578081fd5b833561124b816114c5565b9250602084013561125b816114c5565b929592945050506040919091013590565b6000806040838503121561127e578182fd5b8235611289816114c5565b946020939093013593505050565b600060208083850312156112a9578182fd5b825167ffffffffffffffff808211156112c0578384fd5b818501915085601f8301126112d3578384fd5b8151818111156112e5576112e56114af565b8060051b91506112f684830161147e565b8181528481019084860184860187018a1015611310578788fd5b8795505b83861015611332578051835260019590950194918601918601611314565b5098975050505050505050565b600060208284031215611350578081fd5b81356111d1816114da565b60006020828403121561136c578081fd5b81516111d1816114da565b600060a08284031215611388578081fd5b60405160a0810181811067ffffffffffffffff821117156113ab576113ab6114af565b806040525082358152602083013560208201526040830135604082015260608301356060820152608083013560808201528091505092915050565b6000602082840312156113f7578081fd5b815162ffffff811681146111d1578182fd5b60006020828403121561141a578081fd5b5035919050565b600060208284031215611432578081fd5b5051919050565b6000806040838503121561144b578182fd5b823591506020830135611221816114da565b60006020828403121561146e578081fd5b815160ff811681146111d1578182fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114a7576114a76114af565b604052919050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146104f357600080fd5b80151581146104f357600080fdfea26469706673582212203e125ba39ac77d576bd605d10ca2355d1ef6dd5d7bf6ca6c3e456aa02103eb6e64736f6c63430008040033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 29 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.