Overview
APE Balance
0.00000000099990257 APE
APE Value
Less Than $0.01 (@ $1.55/APE)More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 624,167 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create Tournamen... | 6531696 | 1 hr ago | IN | 0 APE | 0.00688122 | ||||
Liquidate | 6530862 | 1 hr ago | IN | 0 APE | 0.00559209 | ||||
Trade | 6530848 | 1 hr ago | IN | 0 APE | 0.00735443 | ||||
Trade | 6530830 | 1 hr ago | IN | 0 APE | 0.00673907 | ||||
Trade | 6530805 | 1 hr ago | IN | 0 APE | 0.00733587 | ||||
Trade | 6530788 | 1 hr ago | IN | 0 APE | 0.00673816 | ||||
Trade | 6530768 | 1 hr ago | IN | 0 APE | 0.00733173 | ||||
Trade | 6530764 | 1 hr ago | IN | 0 APE | 0.00673877 | ||||
Trade | 6530738 | 1 hr ago | IN | 0 APE | 0.00732469 | ||||
Trade | 6530729 | 1 hr ago | IN | 0 APE | 0.00673762 | ||||
Trade | 6530704 | 1 hr ago | IN | 0 APE | 0.00769997 | ||||
Enter Tournament | 6530675 | 1 hr ago | IN | 10 APE | 0.01078902 | ||||
Create Tournamen... | 6529210 | 2 hrs ago | IN | 0 APE | 0.0068812 | ||||
Trade | 6528493 | 2 hrs ago | IN | 0 APE | 0.00673078 | ||||
Trade | 6528475 | 2 hrs ago | IN | 0 APE | 0.00140472 | ||||
Trade | 6528474 | 2 hrs ago | IN | 0 APE | 0.00727608 | ||||
Create Tournamen... | 6527288 | 3 hrs ago | IN | 0 APE | 0.0068812 | ||||
Create Tournamen... | 6525861 | 4 hrs ago | IN | 0 APE | 0.0068812 | ||||
Trade | 6524170 | 5 hrs ago | IN | 0 APE | 0.00673899 | ||||
Create Tournamen... | 6524062 | 5 hrs ago | IN | 0 APE | 0.0068812 | ||||
Trade | 6523486 | 5 hrs ago | IN | 0 APE | 0.00726688 | ||||
Trade | 6522774 | 6 hrs ago | IN | 0 APE | 0.00672888 | ||||
Trade | 6522762 | 6 hrs ago | IN | 0 APE | 0.00140192 | ||||
Trade | 6522761 | 6 hrs ago | IN | 0 APE | 0.00727514 | ||||
Create Tournamen... | 6522442 | 6 hrs ago | IN | 0 APE | 0.0068812 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6530862 | 1 hr ago | 1 wei | ||||
6530861 | 1 hr ago | 1 wei | ||||
6530848 | 1 hr ago | 1 wei | ||||
6530830 | 1 hr ago | 1 wei | ||||
6530805 | 1 hr ago | 1 wei | ||||
6530788 | 1 hr ago | 1 wei | ||||
6530768 | 1 hr ago | 1 wei | ||||
6530764 | 1 hr ago | 1 wei | ||||
6530738 | 1 hr ago | 1 wei | ||||
6530729 | 1 hr ago | 1 wei | ||||
6530704 | 1 hr ago | 1 wei | ||||
6530675 | 1 hr ago | 10 APE | ||||
6530322 | 1 hr ago | 1 wei | ||||
6530296 | 1 hr ago | 1 wei | ||||
6530250 | 1 hr ago | 1 wei | ||||
6530228 | 1 hr ago | 1 wei | ||||
6530204 | 1 hr ago | 1 wei | ||||
6530179 | 1 hr ago | 1 wei | ||||
6530151 | 1 hr ago | 1 wei | ||||
6530124 | 1 hr ago | 1 wei | ||||
6530092 | 1 hr ago | 1 wei | ||||
6530064 | 1 hr ago | 1 wei | ||||
6528493 | 2 hrs ago | 1 wei | ||||
6528474 | 2 hrs ago | 1 wei | ||||
6524170 | 5 hrs ago | 1 wei |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TopTrader
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {IPyth} from "pyth-sdk-solidity/IPyth.sol"; import {PythStructs} from "pyth-sdk-solidity/PythStructs.sol"; import {OwnableRoles} from "solady/auth/OwnableRoles.sol"; import {SignatureCheckerLib} from "solady/utils/SignatureCheckerLib.sol"; import {IRebootTournament} from "./interfaces/IRebootTournament.sol"; import {Direction, Trade, InternalPrice, TournamentConfig} from "./structs/TopTraderStructs.sol"; /** * * * * * * * * * * * * * * * * * * * * * * * * * * _______ _____ _____ * * | | | |_____] * * | |_____| | * * * * _______ ______ _______ ______ _______ ______ * * | |_____/ |_____| | \ |______ |_____/ * * | | \_ | | |_____/ |______ | \_ * * * * * * * * * * * * * * * * * * * * * * * * * * * */ contract TopTrader is OwnableRoles { // The price is older than the valid time period. error StalePrice(); // block.timestamp is not within the tournament's start and end time. error NotActive(); // The pair does not match the current active trade. error MismatchedPairs(); // A transfer has reverted. error TransferFailed(); // The amount is 0. error InvalidAmount(); // The user has already entered the tournament. error AlreadyEntered(); // Must provide entry fee in the form of msg.value. error InsufficientEntryFee(); // Prices cannot be finalized while the tournament is active. error TournamentActive(); // The user does not have enough balance to execute the trade. error InsufficientBalance(int256 balanceInBips, int256 requiredAmountInBips); // The minimum hold duration has not been met. error MinimumHoldDurationNotMet(); // The slippage scaling factor is too high. error SlippageTooHigh(); // The liquidation bounty is too high. error LiquidationBountyTooHigh(); // An address is initialized to the zero address. error ZeroAddress(); // The minimum timestamp has not been met. error MinTimestampNotMet(); // The signature is invalid. error InvalidSignature(); // The nonce has already been used. error NonceAlreadyUsed(); // The caller is not the counterparty signer or the trader. error InvalidCaller(); // The signature has expired. error SignatureExpired(); // Trade function allows price updates of length 1 only. error InvalidPriceUpdates(); // The length of the pairs and prices arrays do not match. error ArrayLengthMismatch(); // The price update publish time is in the future. error InvalidTimestamp(); // Emitted when a new tournament is created. event TournamentCreated( uint256 indexed tournamentId, bytes32[] pairs, uint40 startTime, uint40 endTime, uint128 startBalance, uint16 maxLeverage, uint80 entryFee, uint16 minimumHoldDuration, uint64 rebuyLimit, uint256 bonusCollateral ); // Emitted when a user is successfully liquidated. event Liquidated(uint256 indexed tournamentId, address indexed user); // The user does not have a negative (balance + upnl). event InvalidLiquidation(uint256 indexed tournamentId, address indexed user, int256 balance, int256 pnl); // Emitted when a liquidation bounty is paid. event LiquidationBountyPaid(address indexed liquidator, uint256 amount); // Emitted when a trade is executed, to provide trade details. event TradeExecuted( uint256 indexed tournamentId, uint256 indexed nonce, address indexed user, int256 amount, int256 executionPrice, bytes32 pair ); // Emitted when a trade is executed, to provide new account details. event AccountUpdated( uint256 indexed tournamentId, address indexed user, int256 indexed balance, int256 amount, int256 entryPrice, bytes32 pair ); // Emitted when the base slippage scaling factor is updated. event BaseSlippageScalingFactorUpdated(uint256 newFactor); // Emitted when the slippage scaling factor is updated. event SlippageScalingFactorUpdated(uint256 newFactor); // Emitted when the liquidation bounty is updated. event LiquidationBountyUpdated(uint256 newBounty); // Emitted when the counterparty signer is updated. event CounterpartySignerUpdated(address newSigner); IPyth private immutable _PYTH; IRebootTournament private immutable _REBOOT; address private immutable _WAPE_CONTRACT_ADDRESS; uint64 private constant _FINAL_ENDTIME_GRACE_PERIOD = 5 seconds; int256 private constant _BIPS = 10_000; int256 private constant _FIRST_SLIPPAGE_BREAKPOINT = 1_000_000; int256 private constant _SECOND_SLIPPAGE_BREAKPOINT = 10_000_000; uint256 private constant _GLOBAL_CONFIG_MANAGER = _ROLE_42; uint256 private constant _TOURNAMENT_MANAGER = _ROLE_69; uint256 private constant _PRICE_MANAGER = _ROLE_88; uint256 private constant _MAX_BASE_SLIPPAGE_SCALING_FACTOR = 250; uint256 private constant _MAX_SLIPPAGE_INCREMENT_SCALING_FACTOR = 10; uint256 public constant SIGNATURE_VALIDITY_DURATION = 30 seconds; bytes4 private constant _MANUAL_PRICE_PAIR_IDENTIFIER = 0x00420069; address public counterpartySigner; uint256 public liquidationBounty; int256 public baseSlippageScalingFactor; int256 public slippageIncrementScalingFactor; mapping(uint256 tournamentId => TournamentConfig tournament) public tournaments; mapping(bytes32 pair => InternalPrice price) public internalPrices; mapping(uint256 nonce => bool isUsed) public usedNonces; constructor( address pyth, address reboot, address wape, address signer, uint256 _liquidationBounty, uint256 _baseSlippage, uint256 _slippageIncrement ) { if (pyth == address(0) || reboot == address(0) || wape == address(0)) revert ZeroAddress(); _initializeOwner(tx.origin); _grantRoles(tx.origin, _GLOBAL_CONFIG_MANAGER | _TOURNAMENT_MANAGER); _PYTH = IPyth(pyth); _REBOOT = IRebootTournament(reboot); _WAPE_CONTRACT_ADDRESS = wape; liquidationBounty = _liquidationBounty; _setCounterpartySigner(signer); _setBaseSlippageScalingFactor(_baseSlippage); _setSlippageIncrementScalingFactor(_slippageIncrement); } receive() external payable {} /** * @notice Creates a new tournament with the given parameters. * @param pairs The pairs that are allowed in the tournament (signature enforced). * @param startTime The start time of the tournament. * @param endTime The end time of the tournament. * @param startBalance The starting balance for each user. * @param maxLeverage The maximum leverage allowed for each user. * @param entryFee The entry fee in $APE for the tournament. * @param rebuyLimit The maximum number of rebuys allowed per user, after initial entry. * @param bonusCollateral Optional bonus collateral pool. */ function createTournament( bytes32[] calldata pairs, uint16 minimumHoldDuration, uint40 startTime, uint40 endTime, uint128 startBalance, uint16 maxLeverage, uint80 entryFee, uint64 rebuyLimit, uint256 bonusCollateral ) external onlyRoles(_TOURNAMENT_MANAGER) returns (uint256 tournamentId) { tournamentId = _REBOOT.register( IRebootTournament.Config({ entryFee: entryFee, rebuyFee: entryFee, isExactFee: true, entryLimit: type(uint64).max, maxEntriesPerRoom: type(uint64).max, rebuyLimit: rebuyLimit, startDate: startTime, endDate: endTime, ticketProfitToTickets: 1 ether, creditProfitToTickets: 1 ether, creditEntryToTickets: 1 ether, entryDuration: endTime - startTime, tournamentDuration: 0, payoutDuration: 30 days, creditRatio: 0, creditId: _WAPE_CONTRACT_ADDRESS, bonusCollateral: bonusCollateral, priceFeedPair: 0x0 }) ); _REBOOT.createRoom(tournamentId, 0, uint64(startTime)); TournamentConfig storage tournament = tournaments[tournamentId]; tournament.minimumHoldDuration = minimumHoldDuration; tournament.startTime = startTime; tournament.endTime = endTime; tournament.startBalance = startBalance; tournament.maxLeverage = maxLeverage; emit TournamentCreated( tournamentId, pairs, startTime, endTime, startBalance, maxLeverage, entryFee, minimumHoldDuration, rebuyLimit, bonusCollateral ); return tournamentId; } /** * @notice Enters a user into a tournament. * @param tournamentId The ID of the tournament. */ function enterTournament(uint256 tournamentId) external payable { _enterTournament(msg.sender, tournamentId); } /** * @notice Enters a user into a tournament * @param user The address of the user * @param tournamentId The ID of the tournament */ function enterTournamentFor(address user, uint256 tournamentId) external payable { _enterTournament(user, tournamentId); } /** * @notice Executes a trade for a user in a tournament. * @param tournamentId The ID of the tournament. * @param pair The pair to trade. If the pair is not supported by Pyth, it should begin with _MANUAL_PRICE_PAIR_IDENTIFIER. * @param priceUpdates The Pyth price update data (empty if pair is not supported by Pyth). * @param amountInBips The amount to trade in bips. Positive for long, negative for short. * @param trader The address of the trader. If not msg.sender, `signature` must recover to msg.sender. * @param minTimestamp The minimum timestamp for the trade. * @param nonce The random nonce for the trade. * @param signature The signature of the trader, if trader != msg.sender. */ function trade( uint256 tournamentId, bytes32 pair, bytes[] calldata priceUpdates, int256 amountInBips, address trader, uint256 minTimestamp, uint256 nonce, bytes calldata signature ) external { uint256 signatureExpirationTimestamp; unchecked { signatureExpirationTimestamp = minTimestamp + SIGNATURE_VALIDITY_DURATION; } if (amountInBips == 0) revert InvalidAmount(); if (block.timestamp < minTimestamp) revert MinTimestampNotMet(); if (block.timestamp > signatureExpirationTimestamp) revert SignatureExpired(); TournamentConfig storage tournament = tournaments[tournamentId]; _assertTournamentOpen(tournament); Trade memory currentPosition = tournament.activeTrade[trader]; bool isReduce = false; if (currentPosition.pair != 0x0) { if (currentPosition.pair != pair) { revert MismatchedPairs(); } else if ( // Enforce minimum hold duration if the user has an open position and is reducing or closing it. (currentPosition.amountInBips > 0) != (amountInBips > 0) ) { if (currentPosition.lastUpdatedAt + tournament.minimumHoldDuration > block.timestamp) { revert MinimumHoldDurationNotMet(); } isReduce = true; } } // Prevent signature re-use. if (usedNonces[nonce]) revert NonceAlreadyUsed(); usedNonces[nonce] = true; Direction direction = amountInBips > 0 ? Direction.LONG : Direction.SHORT; bytes32 hash = SignatureCheckerLib.toEthSignedMessageHash( keccak256(abi.encodePacked(trader, tournamentId, pair, direction, minTimestamp, nonce)) ); if (msg.sender == trader) { // If trader is submitting the trade, ensure counterparty has signed for it. if (!SignatureCheckerLib.isValidSignatureNowCalldata(counterpartySigner, hash, signature)) { revert InvalidSignature(); } } else if (msg.sender == counterpartySigner) { // If counterparty is submitting trade, ensure the trader has signed for it. if (!SignatureCheckerLib.isValidSignatureNowCalldata(trader, hash, signature)) { revert InvalidSignature(); } } else { // In real life this is where a bouncer would break your kneecaps. revert InvalidCaller(); } updatePythPriceFeeds(priceUpdates); int256 normalizedPrice = _fetchAndNormalizePrice(pair); int256 currentUSDNPnlInBips = _currentPnlForPositionAndPrice(currentPosition, normalizedPrice); int256 usdnBalance = tournament.userBalance[trader]; int256 absoluteActivePositionAmountInBips = _abs(currentPosition.amountInBips); int256 usdnMaxTradeInBips; unchecked { // At very large balances, this math will over/underflow and cause unintended side effects. // Break the contract. Achieve eternal glory. Bet more. int256 usdnTotalAvailableCapital = (usdnBalance * _BIPS + currentUSDNPnlInBips) * int256(uint256(tournament.maxLeverage)) / _BIPS; int256 absoluteExistingExposure = absoluteActivePositionAmountInBips * normalizedPrice / _BIPS; usdnMaxTradeInBips = ( isReduce ? usdnTotalAvailableCapital + absoluteExistingExposure : usdnTotalAvailableCapital - absoluteExistingExposure ) * _BIPS; } int256 absoluteAmountInBips = _abs(amountInBips); // Leave this checked to prevent malicious over/underflow in subsequent calcs. int256 tradeSizeInBips = absoluteAmountInBips * normalizedPrice; if (tradeSizeInBips > usdnMaxTradeInBips) { // Set max trade to 0 if negative, for event clarity. if (usdnMaxTradeInBips < 0) usdnMaxTradeInBips = 0; revert InsufficientBalance(usdnMaxTradeInBips, tradeSizeInBips); } int104 openAmount; if (isReduce) { if (absoluteAmountInBips == absoluteActivePositionAmountInBips) { // Position is being closed. Should never be used. Liquidation or glory. unchecked { usdnBalance += (currentUSDNPnlInBips / _BIPS); } // Apply profits and close position. tournament.userBalance[trader] = usdnBalance; tournament.activeTrade[trader] = Trade(0x0, uint40(block.timestamp), 0, 0); emit TradeExecuted(tournamentId, nonce, trader, amountInBips, normalizedPrice, pair); emit AccountUpdated(tournamentId, trader, tournament.userBalance[trader], 0, 0, 0x0); } else if (absoluteAmountInBips < absoluteActivePositionAmountInBips) { // Position is being reduced. For use by cowards only. unchecked { openAmount = currentPosition.amountInBips + int104(amountInBips); usdnBalance += currentUSDNPnlInBips * absoluteAmountInBips / absoluteActivePositionAmountInBips / _BIPS; } // Apply scaled profits, reduce position, and reset open timstamp. tournament.userBalance[trader] = usdnBalance; tournament.activeTrade[trader].amountInBips = openAmount; tournament.activeTrade[trader].lastUpdatedAt = uint40(block.timestamp); emit TradeExecuted(tournamentId, nonce, trader, amountInBips, normalizedPrice, pair); emit AccountUpdated( tournamentId, trader, tournament.userBalance[trader], openAmount, currentPosition.entryPrice, pair ); } else { // Position is being flipped. For use by the candle chasers. // We need to close and apply profits without slippage, then open a new position with slippage. unchecked { openAmount = currentPosition.amountInBips + int104(amountInBips); usdnBalance += currentUSDNPnlInBips / _BIPS; } // Apply profits to user's balance and emit event to represent close with no slippage. tournament.userBalance[trader] = usdnBalance; emit TradeExecuted( tournamentId, nonce, trader, currentPosition.amountInBips * -1, normalizedPrice, pair ); // Slippage is applied only to the new position. int256 newTradeSizeInBips; unchecked { newTradeSizeInBips = openAmount * normalizedPrice; } int256 executionPrice = _calculateEntryPriceWithSlippageApplied(_abs(newTradeSizeInBips), normalizedPrice, direction); tournament.activeTrade[trader] = Trade(pair, uint40(block.timestamp), int104(executionPrice), openAmount); emit TradeExecuted(tournamentId, nonce, trader, openAmount, executionPrice, pair); emit AccountUpdated( tournamentId, trader, tournament.userBalance[trader], openAmount, executionPrice, pair ); } } else { // Position is being opened or increased. Both are commendable actions. int256 executionPrice = _calculateEntryPriceWithSlippageApplied(tradeSizeInBips, normalizedPrice, direction); int256 entryPrice; unchecked { // Scale position size up and calculate new entry price as weighted average of current and new trade. openAmount = currentPosition.amountInBips + int104(amountInBips); entryPrice = ( currentPosition.entryPrice * absoluteActivePositionAmountInBips + executionPrice * absoluteAmountInBips ) / (absoluteActivePositionAmountInBips + absoluteAmountInBips); } tournament.activeTrade[trader] = Trade(pair, uint40(block.timestamp), int104(entryPrice), openAmount); emit TradeExecuted(tournamentId, nonce, trader, amountInBips, executionPrice, pair); emit AccountUpdated(tournamentId, trader, tournament.userBalance[trader], openAmount, entryPrice, pair); } } /** * @notice Liquidates a user in a tournament, as long as their balance + pnl is negative. * @param tournamentId The ID of the tournament. * @param users The users to liquidate. * @param priceUpdates The Pyth price update data. */ function liquidate(uint256 tournamentId, address[] calldata users, bytes[] calldata priceUpdates) external { TournamentConfig storage tournament = tournaments[tournamentId]; _assertTournamentOpen(tournament); updatePythPriceFeeds(priceUpdates); uint256 liquidationBountyPayout; for (uint256 i = 0; i < users.length; i++) { int256 currentPnl = _currentPnlFor(tournament, users[i]); if (currentPnl + tournament.userBalance[users[i]] < 0) { // Get rekt noob. tournament.userBalance[users[i]] = 0; delete tournament.activeTrade[users[i]]; unchecked { liquidationBountyPayout += liquidationBounty; } emit Liquidated(tournamentId, users[i]); } else { // You're safe for now. emit InvalidLiquidation(tournamentId, users[i], tournament.userBalance[users[i]], currentPnl); } } if (liquidationBountyPayout > 0) { (bool success,) = msg.sender.call{value: liquidationBountyPayout}(""); if (!success) revert TransferFailed(); emit LiquidationBountyPaid(msg.sender, liquidationBountyPayout); } } /** * @notice Manual price update. * @param priceUpdates The Pyth price update data. */ function updatePythPriceFeeds(bytes[] calldata priceUpdates) public { if (priceUpdates.length > 0) { uint256 fee = _PYTH.getUpdateFee(priceUpdates); _PYTH.updatePriceFeeds{value: fee}(priceUpdates); } } /** * @notice Manual price update. * @param pairs The pairs to update. * @param prices The prices to update. */ function updateManualPriceFeeds(bytes32[] calldata pairs, InternalPrice[] calldata prices) external onlyRoles(_PRICE_MANAGER) { if (pairs.length != prices.length) revert ArrayLengthMismatch(); for (uint256 i = 0; i < pairs.length; i++) { InternalPrice memory price = prices[i]; bytes32 pair = pairs[i]; if (!_isManualPriceOverride(pair)) revert InvalidPriceUpdates(); // disallow future timestamps. if (price.publishTime > block.timestamp) revert InvalidTimestamp(); if (price.publishTime <= internalPrices[pair].publishTime) continue; internalPrices[pair] = price; } } /** * @notice Finalize prices for a tournament. * @param tournamentId The ID of the tournament. * @param priceUpdates The Pyth price update data. * @param pairs The pairs to finalize prices for. */ function finalizePrices(uint256 tournamentId, bytes[] calldata priceUpdates, bytes32[] calldata pairs) external onlyRoles(_TOURNAMENT_MANAGER) { TournamentConfig storage tournament = tournaments[tournamentId]; if (tournament.endTime > block.timestamp) revert TournamentActive(); uint256 fee = _PYTH.getUpdateFee(priceUpdates); PythStructs.PriceFeed[] memory priceFeeds = _PYTH.parsePriceFeedUpdates{value: fee}( priceUpdates, pairs, tournament.endTime, tournament.endTime + _FINAL_ENDTIME_GRACE_PERIOD ); for (uint256 i = 0; i < priceFeeds.length; i++) { PythStructs.Price memory price = priceFeeds[i].price; // convert to InternalPrice to save a storage slot. tournament.finalPrices[priceFeeds[i].id] = InternalPrice({price: price.price, expo: price.expo, publishTime: uint40(price.publishTime)}); } } /** * @notice Sets the counterparty signer. * @param signer The new counterparty signer. */ function setCounterpartySigner(address signer) external onlyRoles(_GLOBAL_CONFIG_MANAGER) { _setCounterpartySigner(signer); } /** * @notice Sets the liquidation bounty. * @param bounty The new liquidation bounty. */ function setLiquidationBounty(uint256 bounty) external onlyRoles(_GLOBAL_CONFIG_MANAGER) { _setLiquidationBounty(bounty); } /** * @notice Returns the final pyth price for a pair in a tournament. * @param tournamentId The ID of the tournament. * @param pair The pair to get final pyth price for. */ function finalPrice(uint256 tournamentId, bytes32 pair) external view returns (InternalPrice memory) { return tournaments[tournamentId].finalPrices[pair]; } /** * @notice Sets the base slippage scaling factor. * @param factor The new base slippage scaling factor. */ function setBaseSlippageScalingFactor(uint256 factor) external onlyRoles(_GLOBAL_CONFIG_MANAGER) { _setBaseSlippageScalingFactor(factor); } /** * @notice Sets the slippage increment scaling factor. * @param factor The new slippage increment scaling factor. */ function setSlippageIncrementScalingFactor(uint256 factor) external onlyRoles(_GLOBAL_CONFIG_MANAGER) { _setSlippageIncrementScalingFactor(factor); } /** * @notice Submit results for a tournament. * @param tournamentId The ID of the tournament. * @param results The results to propose. */ function submitResults(uint256 tournamentId, IRebootTournament.Result[] calldata results) external onlyRoles(_TOURNAMENT_MANAGER) { _REBOOT.submitResults(tournamentId, 0, results); } function cleanup(uint256 tournamentId) external onlyRoles(_TOURNAMENT_MANAGER) { _REBOOT.cleanup(tournamentId, 0); } /** * @notice Withdraws the contract balance. * @dev If there is a liquidation bounty in place, calling this while a tournament is active will cause liquidations to fail. */ function withdraw() external onlyOwner { (bool success,) = msg.sender.call{value: address(this).balance}(""); if (!success) revert TransferFailed(); } /** * @notice Returns the most recent Reboot tournament ID. */ function currentTournamentId() external view returns (uint256) { return _REBOOT.tournamentCount(); } /** * @notice Returns the active trade for a user in a tournament. * @param tournamentId The ID of the tournament. * @param user The address of the user. */ function activeTrade(uint256 tournamentId, address user) external view returns (Trade memory) { return tournaments[tournamentId].activeTrade[user]; } /** * . * @notice Returns the balance for a user in a tournament. * @param tournamentId The ID of the tournament. * @param user The address of the user. */ function userBalance(uint256 tournamentId, address user) external view returns (int256) { return tournaments[tournamentId].userBalance[user]; } /** * @notice Returns the current UPnL for a user in a tournament. * @param tournamentId The ID of the tournament. * @param user The address of the user. * @dev UPnL does not include the user's balance. * @dev Does not perform a price update, so may be stale. Use updatePrices to ensure the most recent prices. * @dev accounts for slippage on close. */ function currentPnlFor(uint256 tournamentId, address user) external view returns (int256) { TournamentConfig storage tournament = tournaments[tournamentId]; return _currentPnlFor(tournament, user); } /** * @notice Enters a user into a tournament. * @param tournamentId The ID of the tournament. */ function _enterTournament(address user, uint256 tournamentId) internal { TournamentConfig storage tournament = tournaments[tournamentId]; if (tournament.userBalance[user] != 0) { revert AlreadyEntered(); } _assertTournamentOpen(tournament); // A valid underflow is incredibly impractical. uint256 valueToTransfer; unchecked { valueToTransfer = msg.value - liquidationBounty; } uint256 entryFee = _REBOOT.getTournament(tournamentId).entryFee; // If msg.sender == user, they can use their reboot credits to enter. If not, msg.value must be used for entry fee. if (msg.sender != user && valueToTransfer < entryFee) revert InsufficientEntryFee(); _REBOOT.enter{value: valueToTransfer}( IRebootTournament.EntryParams(user, tournamentId, 0, address(0), 0, entryFee) ); tournament.userBalance[user] = int256(int128(tournament.startBalance)); } function _setCounterpartySigner(address signer) internal { if (signer == address(0)) revert ZeroAddress(); counterpartySigner = signer; emit CounterpartySignerUpdated(signer); } function _setBaseSlippageScalingFactor(uint256 factor) internal { // revert if slippage scaling factor > _MAX_BASE_SLIPPAGE_SCALING_FACTOR. if (factor > _MAX_BASE_SLIPPAGE_SCALING_FACTOR) revert SlippageTooHigh(); baseSlippageScalingFactor = int256(factor); emit BaseSlippageScalingFactorUpdated(factor); } function _setSlippageIncrementScalingFactor(uint256 factor) internal { // revert if slippage scaling factor > _MAX_SLIPPAGE_INCREMENT_SCALING_FACTOR. if (factor > _MAX_SLIPPAGE_INCREMENT_SCALING_FACTOR) revert SlippageTooHigh(); slippageIncrementScalingFactor = int256(factor); emit SlippageScalingFactorUpdated(factor); } function _setLiquidationBounty(uint256 bounty) internal { // bounty should typically be ~1 apecoin or less. if (bounty > 1_000 ether) revert LiquidationBountyTooHigh(); liquidationBounty = bounty; emit LiquidationBountyUpdated(bounty); } function _updateAndFetchPythPrice(bytes32 pair, bytes[] calldata priceUpdates) internal returns (PythStructs.Price memory) { updatePythPriceFeeds(priceUpdates); return _PYTH.getPrice(pair); } function _fetchAndNormalizePrice(bytes32 pair) internal view returns (int256) { if (bytes4(pair) == _MANUAL_PRICE_PAIR_IDENTIFIER) { InternalPrice memory price = internalPrices[pair]; if (price.publishTime < block.timestamp - _PYTH.getValidTimePeriod()) { revert StalePrice(); } return _normalizePrice(price.price, price.expo); } else { PythStructs.Price memory price = _PYTH.getPrice(pair); return _normalizePrice(price.price, price.expo); } } function _currentPnlFor(TournamentConfig storage tournament, address user) internal view returns (int256) { Trade memory activePosition = tournament.activeTrade[user]; bytes32 pair = activePosition.pair; if (pair == 0x0) { return 0; } int256 normalizedPrice; if (tournament.finalPrices[pair].price != 0) { InternalPrice memory price = tournament.finalPrices[pair]; normalizedPrice = _normalizePrice(price.price, price.expo); } else { normalizedPrice = _fetchAndNormalizePrice(pair); } return _currentPnlForPositionAndPrice(activePosition, normalizedPrice) / _BIPS; } function _assertTournamentOpen(TournamentConfig storage tournament) internal view { if (block.timestamp < tournament.startTime || block.timestamp > tournament.endTime) { revert NotActive(); } } // No free rides. function _calculateEntryPriceWithSlippageApplied(int256 tradeSizeInBips, int256 rawEntryPrice, Direction direction) internal view returns (int256 executionPrice) { int256 floorTradeSize; unchecked { floorTradeSize = tradeSizeInBips / (_BIPS * 1e18); } int256 directionModifier = direction == Direction.LONG ? int256(1) : int256(-1); if (floorTradeSize < _FIRST_SLIPPAGE_BREAKPOINT) { // Apply 1x base slippage to raw entry price. unchecked { int256 slippage = rawEntryPrice * baseSlippageScalingFactor / 1_000_000; executionPrice = directionModifier * slippage + rawEntryPrice; } } else if (floorTradeSize < _SECOND_SLIPPAGE_BREAKPOINT) { // Apply 2x base slippage to raw entry price. unchecked { int256 slippage = rawEntryPrice * baseSlippageScalingFactor / 500_000; executionPrice = directionModifier * slippage + rawEntryPrice; } } else { // Apply 2x base slippage + additional slippage for every order of magnitude increase. int256 additionalSlippage = 0; unchecked { int256 baseSlippage = rawEntryPrice * baseSlippageScalingFactor / 500_000; int256 slippageIncrement = rawEntryPrice * slippageIncrementScalingFactor / 10_000_000; while (floorTradeSize >= _SECOND_SLIPPAGE_BREAKPOINT) { additionalSlippage += slippageIncrement; floorTradeSize = floorTradeSize * 7943 / 10000; // Reduce by 1/10th of a magnitude (20.57%). } int256 totalSlippage = baseSlippage + additionalSlippage; executionPrice = directionModifier * totalSlippage + rawEntryPrice; } } } function _normalizePrice(int64 price, int32 expo) internal pure returns (int256) { unchecked { if (expo < -18) { return int256(price) / int256(10 ** uint256(uint32(-(18 + expo)))); } else { return int256(price) * int256(10 ** uint256(uint32(18 + expo))); } } } function _currentPnlForPositionAndPrice(Trade memory activePosition, int256 normalizedPrice) internal pure returns (int256) { unchecked { return (normalizedPrice - activePosition.entryPrice) * activePosition.amountInBips; } } function _isManualPriceOverride(bytes32 pair) internal pure returns (bool) { return bytes4(pair) == _MANUAL_PRICE_PAIR_IDENTIFIER; } function _abs(int256 x) internal pure returns (int256) { return x >= 0 ? x : -x; } } /** * _ _ _______ _______ _____ _______ _____ _______ _ _ _____ __ _ ______ * |____/ |______ |______ |_____] | | | | |____/ | | \ | | ____ * | \_ |______ |______ | |_____ |_____ __|__ |_____ | \_ __|__ | \_| |_____| . * * ______ _____ ______ __ __ _______ _ _ _ _______ _____ _______ _______ * | ____ | | | |_____/ \_/ |_____| | | | |_____| | | |______ * |_____| |_____ |_____| | \_ | | | |__|__| | | __|__ | ______| . * * ______ _______ _______ _______ _____ ______ _______ * |_____] |______ | | | | | | |_____/ |______ * |_____] |______ | | | | |_____| | \_ |______ . */
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "./PythStructs.sol"; import "./IPythEvents.sol"; /// @title Consume prices from the Pyth Network (https://pyth.network/). /// @dev Please refer to the guidance at https://docs.pyth.network/consumers/best-practices for how to consume prices safely. /// @author Pyth Data Association interface IPyth is IPythEvents { /// @notice Returns the period (in seconds) that a price feed is considered valid since its publish time function getValidTimePeriod() external view returns (uint validTimePeriod); /// @notice Returns the price and confidence interval. /// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds. /// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPrice( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price and confidence interval. /// @dev Reverts if the EMA price is not available. /// @param id The Pyth Price Feed ID of which to fetch the EMA price and confidence interval. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPrice( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the price of a price feed without any sanity checks. /// @dev This function returns the most recent price update in this contract without any recency checks. /// This function is unsafe as the returned price update may be arbitrarily far in the past. /// /// Users of this function should check the `publishTime` in the price to ensure that the returned price is /// sufficiently recent for their application. If you are considering using this function, it may be /// safer / easier to use either `getPrice` or `getPriceNoOlderThan`. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPriceUnsafe( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the price that is no older than `age` seconds of the current time. /// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently /// recently. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPriceNoOlderThan( bytes32 id, uint age ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks. /// @dev This function returns the same price as `getEmaPrice` in the case where the price is available. /// However, if the price is not recent this function returns the latest available price. /// /// The returned price can be from arbitrarily far in the past; this function makes no guarantees that /// the returned price is recent or useful for any particular application. /// /// Users of this function should check the `publishTime` in the price to ensure that the returned price is /// sufficiently recent for their application. If you are considering using this function, it may be /// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPriceUnsafe( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds /// of the current time. /// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently /// recently. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPriceNoOlderThan( bytes32 id, uint age ) external view returns (PythStructs.Price memory price); /// @notice Update price feeds with given update messages. /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// Prices will be updated if they are more recent than the current stored prices. /// The call will succeed even if the update is not the most recent. /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid. /// @param updateData Array of price update data. function updatePriceFeeds(bytes[] calldata updateData) external payable; /// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is /// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the /// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`. /// /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// /// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime /// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have /// a newer or equal publish time than the given publish time, it will reject the transaction to save gas. /// Otherwise, it calls updatePriceFeeds method to update the prices. /// /// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid. /// @param updateData Array of price update data. /// @param priceIds Array of price ids. /// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]` function updatePriceFeedsIfNecessary( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes ) external payable; /// @notice Returns the required fee to update an array of price updates. /// @param updateData Array of price update data. /// @return feeAmount The required fee in Wei. function getUpdateFee( bytes[] calldata updateData ) external view returns (uint feeAmount); /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published /// within `minPublishTime` and `maxPublishTime`. /// /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price; /// otherwise, please consider using `updatePriceFeeds`. This method does not store the price updates on-chain. /// /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// /// /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is /// no update for any of the given `priceIds` within the given time range. /// @param updateData Array of price update data. /// @param priceIds Array of price ids. /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`. /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`. /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order). function parsePriceFeedUpdates( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64 minPublishTime, uint64 maxPublishTime ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; contract PythStructs { // A price with a degree of uncertainty, represented as a price +- a confidence interval. // // The confidence interval roughly corresponds to the standard error of a normal distribution. // Both the price and confidence are stored in a fixed-point numeric representation, // `x * (10^expo)`, where `expo` is the exponent. // // Please refer to the documentation at https://docs.pyth.network/consumers/best-practices for how // to how this price safely. struct Price { // Price int64 price; // Confidence interval around the price uint64 conf; // Price exponent int32 expo; // Unix timestamp describing when the price was published uint publishTime; } // PriceFeed represents a current aggregate price from pyth publisher feeds. struct PriceFeed { // The price ID. bytes32 id; // Latest available price Price price; // Latest available exponentially-weighted moving average price Price emaPrice; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {Ownable} from "./Ownable.sol"; /// @notice Simple single owner and multiroles authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173) /// for compatibility, the nomenclature for the 2-step ownership handover and roles /// may be unique to this codebase. abstract contract OwnableRoles is Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The `user`'s roles is updated to `roles`. /// Each bit of `roles` represents whether the role is set. event RolesUpdated(address indexed user, uint256 indexed roles); /// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`. uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE = 0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The role slot of `user` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED)) /// let roleSlot := keccak256(0x00, 0x20) /// ``` /// This automatically ignores the upper bits of the `user` in case /// they are not clean, as well as keep the `keccak256` under 32-bytes. /// /// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`. uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Overwrite the roles directly without authorization guard. function _setRoles(address user, uint256 roles) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Store the new value. sstore(keccak256(0x0c, 0x20), roles) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles) } } /// @dev Updates the roles directly without authorization guard. /// If `on` is true, each set bit of `roles` will be turned on, /// otherwise, each set bit of `roles` will be turned off. function _updateRoles(address user, uint256 roles, bool on) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) let roleSlot := keccak256(0x0c, 0x20) // Load the current value. let current := sload(roleSlot) // Compute the updated roles if `on` is true. let updated := or(current, roles) // Compute the updated roles if `on` is false. // Use `and` to compute the intersection of `current` and `roles`, // `xor` it with `current` to flip the bits in the intersection. if iszero(on) { updated := xor(current, and(current, roles)) } // Then, store the new value. sstore(roleSlot, updated) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated) } } /// @dev Grants the roles directly without authorization guard. /// Each bit of `roles` represents the role to turn on. function _grantRoles(address user, uint256 roles) internal virtual { _updateRoles(user, roles, true); } /// @dev Removes the roles directly without authorization guard. /// Each bit of `roles` represents the role to turn off. function _removeRoles(address user, uint256 roles) internal virtual { _updateRoles(user, roles, false); } /// @dev Throws if the sender does not have any of the `roles`. function _checkRoles(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Throws if the sender is not the owner, /// and does not have any of the `roles`. /// Checks for ownership first, then lazily checks for roles. function _checkOwnerOrRoles(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner. // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`. if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } } /// @dev Throws if the sender does not have any of the `roles`, /// and is not the owner. /// Checks for roles first, then lazily checks for ownership. function _checkRolesOrOwner(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { // If the caller is not the stored owner. // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`. if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } } /// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`. /// This is meant for frontends like Etherscan, and is therefore not fully optimized. /// Not recommended to be called on-chain. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) { /// @solidity memory-safe-assembly assembly { for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } { // We don't need to mask the values of `ordinals`, as Solidity // cleans dirty upper bits when storing variables into memory. roles := or(shl(mload(add(ordinals, i)), 1), roles) } } } /// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap. /// This is meant for frontends like Etherscan, and is therefore not fully optimized. /// Not recommended to be called on-chain. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) { /// @solidity memory-safe-assembly assembly { // Grab the pointer to the free memory. ordinals := mload(0x40) let ptr := add(ordinals, 0x20) let o := 0 // The absence of lookup tables, De Bruijn, etc., here is intentional for // smaller bytecode, as this function is not meant to be called on-chain. for { let t := roles } 1 {} { mstore(ptr, o) // `shr` 5 is equivalent to multiplying by 0x20. // Push back into the ordinals array if the bit is set. ptr := add(ptr, shl(5, and(t, 1))) o := add(o, 1) t := shr(o, roles) if iszero(t) { break } } // Store the length of `ordinals`. mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20)))) // Allocate the memory. mstore(0x40, ptr) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to grant `user` `roles`. /// If the `user` already has a role, then it will be an no-op for the role. function grantRoles(address user, uint256 roles) public payable virtual onlyOwner { _grantRoles(user, roles); } /// @dev Allows the owner to remove `user` `roles`. /// If the `user` does not have a role, then it will be an no-op for the role. function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner { _removeRoles(user, roles); } /// @dev Allow the caller to remove their own roles. /// If the caller does not have a role, then it will be an no-op for the role. function renounceRoles(uint256 roles) public payable virtual { _removeRoles(msg.sender, roles); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the roles of `user`. function rolesOf(address user) public view virtual returns (uint256 roles) { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Load the stored value. roles := sload(keccak256(0x0c, 0x20)) } } /// @dev Returns whether `user` has any of `roles`. function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) { return rolesOf(user) & roles != 0; } /// @dev Returns whether `user` has all of `roles`. function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) { return rolesOf(user) & roles == roles; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by an account with `roles`. modifier onlyRoles(uint256 roles) virtual { _checkRoles(roles); _; } /// @dev Marks a function as only callable by the owner or by an account /// with `roles`. Checks for ownership first, then lazily checks for roles. modifier onlyOwnerOrRoles(uint256 roles) virtual { _checkOwnerOrRoles(roles); _; } /// @dev Marks a function as only callable by an account with `roles` /// or the owner. Checks for roles first, then lazily checks for ownership. modifier onlyRolesOrOwner(uint256 roles) virtual { _checkRolesOrOwner(roles); _; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ROLE CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // IYKYK uint256 internal constant _ROLE_0 = 1 << 0; uint256 internal constant _ROLE_1 = 1 << 1; uint256 internal constant _ROLE_2 = 1 << 2; uint256 internal constant _ROLE_3 = 1 << 3; uint256 internal constant _ROLE_4 = 1 << 4; uint256 internal constant _ROLE_5 = 1 << 5; uint256 internal constant _ROLE_6 = 1 << 6; uint256 internal constant _ROLE_7 = 1 << 7; uint256 internal constant _ROLE_8 = 1 << 8; uint256 internal constant _ROLE_9 = 1 << 9; uint256 internal constant _ROLE_10 = 1 << 10; uint256 internal constant _ROLE_11 = 1 << 11; uint256 internal constant _ROLE_12 = 1 << 12; uint256 internal constant _ROLE_13 = 1 << 13; uint256 internal constant _ROLE_14 = 1 << 14; uint256 internal constant _ROLE_15 = 1 << 15; uint256 internal constant _ROLE_16 = 1 << 16; uint256 internal constant _ROLE_17 = 1 << 17; uint256 internal constant _ROLE_18 = 1 << 18; uint256 internal constant _ROLE_19 = 1 << 19; uint256 internal constant _ROLE_20 = 1 << 20; uint256 internal constant _ROLE_21 = 1 << 21; uint256 internal constant _ROLE_22 = 1 << 22; uint256 internal constant _ROLE_23 = 1 << 23; uint256 internal constant _ROLE_24 = 1 << 24; uint256 internal constant _ROLE_25 = 1 << 25; uint256 internal constant _ROLE_26 = 1 << 26; uint256 internal constant _ROLE_27 = 1 << 27; uint256 internal constant _ROLE_28 = 1 << 28; uint256 internal constant _ROLE_29 = 1 << 29; uint256 internal constant _ROLE_30 = 1 << 30; uint256 internal constant _ROLE_31 = 1 << 31; uint256 internal constant _ROLE_32 = 1 << 32; uint256 internal constant _ROLE_33 = 1 << 33; uint256 internal constant _ROLE_34 = 1 << 34; uint256 internal constant _ROLE_35 = 1 << 35; uint256 internal constant _ROLE_36 = 1 << 36; uint256 internal constant _ROLE_37 = 1 << 37; uint256 internal constant _ROLE_38 = 1 << 38; uint256 internal constant _ROLE_39 = 1 << 39; uint256 internal constant _ROLE_40 = 1 << 40; uint256 internal constant _ROLE_41 = 1 << 41; uint256 internal constant _ROLE_42 = 1 << 42; uint256 internal constant _ROLE_43 = 1 << 43; uint256 internal constant _ROLE_44 = 1 << 44; uint256 internal constant _ROLE_45 = 1 << 45; uint256 internal constant _ROLE_46 = 1 << 46; uint256 internal constant _ROLE_47 = 1 << 47; uint256 internal constant _ROLE_48 = 1 << 48; uint256 internal constant _ROLE_49 = 1 << 49; uint256 internal constant _ROLE_50 = 1 << 50; uint256 internal constant _ROLE_51 = 1 << 51; uint256 internal constant _ROLE_52 = 1 << 52; uint256 internal constant _ROLE_53 = 1 << 53; uint256 internal constant _ROLE_54 = 1 << 54; uint256 internal constant _ROLE_55 = 1 << 55; uint256 internal constant _ROLE_56 = 1 << 56; uint256 internal constant _ROLE_57 = 1 << 57; uint256 internal constant _ROLE_58 = 1 << 58; uint256 internal constant _ROLE_59 = 1 << 59; uint256 internal constant _ROLE_60 = 1 << 60; uint256 internal constant _ROLE_61 = 1 << 61; uint256 internal constant _ROLE_62 = 1 << 62; uint256 internal constant _ROLE_63 = 1 << 63; uint256 internal constant _ROLE_64 = 1 << 64; uint256 internal constant _ROLE_65 = 1 << 65; uint256 internal constant _ROLE_66 = 1 << 66; uint256 internal constant _ROLE_67 = 1 << 67; uint256 internal constant _ROLE_68 = 1 << 68; uint256 internal constant _ROLE_69 = 1 << 69; uint256 internal constant _ROLE_70 = 1 << 70; uint256 internal constant _ROLE_71 = 1 << 71; uint256 internal constant _ROLE_72 = 1 << 72; uint256 internal constant _ROLE_73 = 1 << 73; uint256 internal constant _ROLE_74 = 1 << 74; uint256 internal constant _ROLE_75 = 1 << 75; uint256 internal constant _ROLE_76 = 1 << 76; uint256 internal constant _ROLE_77 = 1 << 77; uint256 internal constant _ROLE_78 = 1 << 78; uint256 internal constant _ROLE_79 = 1 << 79; uint256 internal constant _ROLE_80 = 1 << 80; uint256 internal constant _ROLE_81 = 1 << 81; uint256 internal constant _ROLE_82 = 1 << 82; uint256 internal constant _ROLE_83 = 1 << 83; uint256 internal constant _ROLE_84 = 1 << 84; uint256 internal constant _ROLE_85 = 1 << 85; uint256 internal constant _ROLE_86 = 1 << 86; uint256 internal constant _ROLE_87 = 1 << 87; uint256 internal constant _ROLE_88 = 1 << 88; uint256 internal constant _ROLE_89 = 1 << 89; uint256 internal constant _ROLE_90 = 1 << 90; uint256 internal constant _ROLE_91 = 1 << 91; uint256 internal constant _ROLE_92 = 1 << 92; uint256 internal constant _ROLE_93 = 1 << 93; uint256 internal constant _ROLE_94 = 1 << 94; uint256 internal constant _ROLE_95 = 1 << 95; uint256 internal constant _ROLE_96 = 1 << 96; uint256 internal constant _ROLE_97 = 1 << 97; uint256 internal constant _ROLE_98 = 1 << 98; uint256 internal constant _ROLE_99 = 1 << 99; uint256 internal constant _ROLE_100 = 1 << 100; uint256 internal constant _ROLE_101 = 1 << 101; uint256 internal constant _ROLE_102 = 1 << 102; uint256 internal constant _ROLE_103 = 1 << 103; uint256 internal constant _ROLE_104 = 1 << 104; uint256 internal constant _ROLE_105 = 1 << 105; uint256 internal constant _ROLE_106 = 1 << 106; uint256 internal constant _ROLE_107 = 1 << 107; uint256 internal constant _ROLE_108 = 1 << 108; uint256 internal constant _ROLE_109 = 1 << 109; uint256 internal constant _ROLE_110 = 1 << 110; uint256 internal constant _ROLE_111 = 1 << 111; uint256 internal constant _ROLE_112 = 1 << 112; uint256 internal constant _ROLE_113 = 1 << 113; uint256 internal constant _ROLE_114 = 1 << 114; uint256 internal constant _ROLE_115 = 1 << 115; uint256 internal constant _ROLE_116 = 1 << 116; uint256 internal constant _ROLE_117 = 1 << 117; uint256 internal constant _ROLE_118 = 1 << 118; uint256 internal constant _ROLE_119 = 1 << 119; uint256 internal constant _ROLE_120 = 1 << 120; uint256 internal constant _ROLE_121 = 1 << 121; uint256 internal constant _ROLE_122 = 1 << 122; uint256 internal constant _ROLE_123 = 1 << 123; uint256 internal constant _ROLE_124 = 1 << 124; uint256 internal constant _ROLE_125 = 1 << 125; uint256 internal constant _ROLE_126 = 1 << 126; uint256 internal constant _ROLE_127 = 1 << 127; uint256 internal constant _ROLE_128 = 1 << 128; uint256 internal constant _ROLE_129 = 1 << 129; uint256 internal constant _ROLE_130 = 1 << 130; uint256 internal constant _ROLE_131 = 1 << 131; uint256 internal constant _ROLE_132 = 1 << 132; uint256 internal constant _ROLE_133 = 1 << 133; uint256 internal constant _ROLE_134 = 1 << 134; uint256 internal constant _ROLE_135 = 1 << 135; uint256 internal constant _ROLE_136 = 1 << 136; uint256 internal constant _ROLE_137 = 1 << 137; uint256 internal constant _ROLE_138 = 1 << 138; uint256 internal constant _ROLE_139 = 1 << 139; uint256 internal constant _ROLE_140 = 1 << 140; uint256 internal constant _ROLE_141 = 1 << 141; uint256 internal constant _ROLE_142 = 1 << 142; uint256 internal constant _ROLE_143 = 1 << 143; uint256 internal constant _ROLE_144 = 1 << 144; uint256 internal constant _ROLE_145 = 1 << 145; uint256 internal constant _ROLE_146 = 1 << 146; uint256 internal constant _ROLE_147 = 1 << 147; uint256 internal constant _ROLE_148 = 1 << 148; uint256 internal constant _ROLE_149 = 1 << 149; uint256 internal constant _ROLE_150 = 1 << 150; uint256 internal constant _ROLE_151 = 1 << 151; uint256 internal constant _ROLE_152 = 1 << 152; uint256 internal constant _ROLE_153 = 1 << 153; uint256 internal constant _ROLE_154 = 1 << 154; uint256 internal constant _ROLE_155 = 1 << 155; uint256 internal constant _ROLE_156 = 1 << 156; uint256 internal constant _ROLE_157 = 1 << 157; uint256 internal constant _ROLE_158 = 1 << 158; uint256 internal constant _ROLE_159 = 1 << 159; uint256 internal constant _ROLE_160 = 1 << 160; uint256 internal constant _ROLE_161 = 1 << 161; uint256 internal constant _ROLE_162 = 1 << 162; uint256 internal constant _ROLE_163 = 1 << 163; uint256 internal constant _ROLE_164 = 1 << 164; uint256 internal constant _ROLE_165 = 1 << 165; uint256 internal constant _ROLE_166 = 1 << 166; uint256 internal constant _ROLE_167 = 1 << 167; uint256 internal constant _ROLE_168 = 1 << 168; uint256 internal constant _ROLE_169 = 1 << 169; uint256 internal constant _ROLE_170 = 1 << 170; uint256 internal constant _ROLE_171 = 1 << 171; uint256 internal constant _ROLE_172 = 1 << 172; uint256 internal constant _ROLE_173 = 1 << 173; uint256 internal constant _ROLE_174 = 1 << 174; uint256 internal constant _ROLE_175 = 1 << 175; uint256 internal constant _ROLE_176 = 1 << 176; uint256 internal constant _ROLE_177 = 1 << 177; uint256 internal constant _ROLE_178 = 1 << 178; uint256 internal constant _ROLE_179 = 1 << 179; uint256 internal constant _ROLE_180 = 1 << 180; uint256 internal constant _ROLE_181 = 1 << 181; uint256 internal constant _ROLE_182 = 1 << 182; uint256 internal constant _ROLE_183 = 1 << 183; uint256 internal constant _ROLE_184 = 1 << 184; uint256 internal constant _ROLE_185 = 1 << 185; uint256 internal constant _ROLE_186 = 1 << 186; uint256 internal constant _ROLE_187 = 1 << 187; uint256 internal constant _ROLE_188 = 1 << 188; uint256 internal constant _ROLE_189 = 1 << 189; uint256 internal constant _ROLE_190 = 1 << 190; uint256 internal constant _ROLE_191 = 1 << 191; uint256 internal constant _ROLE_192 = 1 << 192; uint256 internal constant _ROLE_193 = 1 << 193; uint256 internal constant _ROLE_194 = 1 << 194; uint256 internal constant _ROLE_195 = 1 << 195; uint256 internal constant _ROLE_196 = 1 << 196; uint256 internal constant _ROLE_197 = 1 << 197; uint256 internal constant _ROLE_198 = 1 << 198; uint256 internal constant _ROLE_199 = 1 << 199; uint256 internal constant _ROLE_200 = 1 << 200; uint256 internal constant _ROLE_201 = 1 << 201; uint256 internal constant _ROLE_202 = 1 << 202; uint256 internal constant _ROLE_203 = 1 << 203; uint256 internal constant _ROLE_204 = 1 << 204; uint256 internal constant _ROLE_205 = 1 << 205; uint256 internal constant _ROLE_206 = 1 << 206; uint256 internal constant _ROLE_207 = 1 << 207; uint256 internal constant _ROLE_208 = 1 << 208; uint256 internal constant _ROLE_209 = 1 << 209; uint256 internal constant _ROLE_210 = 1 << 210; uint256 internal constant _ROLE_211 = 1 << 211; uint256 internal constant _ROLE_212 = 1 << 212; uint256 internal constant _ROLE_213 = 1 << 213; uint256 internal constant _ROLE_214 = 1 << 214; uint256 internal constant _ROLE_215 = 1 << 215; uint256 internal constant _ROLE_216 = 1 << 216; uint256 internal constant _ROLE_217 = 1 << 217; uint256 internal constant _ROLE_218 = 1 << 218; uint256 internal constant _ROLE_219 = 1 << 219; uint256 internal constant _ROLE_220 = 1 << 220; uint256 internal constant _ROLE_221 = 1 << 221; uint256 internal constant _ROLE_222 = 1 << 222; uint256 internal constant _ROLE_223 = 1 << 223; uint256 internal constant _ROLE_224 = 1 << 224; uint256 internal constant _ROLE_225 = 1 << 225; uint256 internal constant _ROLE_226 = 1 << 226; uint256 internal constant _ROLE_227 = 1 << 227; uint256 internal constant _ROLE_228 = 1 << 228; uint256 internal constant _ROLE_229 = 1 << 229; uint256 internal constant _ROLE_230 = 1 << 230; uint256 internal constant _ROLE_231 = 1 << 231; uint256 internal constant _ROLE_232 = 1 << 232; uint256 internal constant _ROLE_233 = 1 << 233; uint256 internal constant _ROLE_234 = 1 << 234; uint256 internal constant _ROLE_235 = 1 << 235; uint256 internal constant _ROLE_236 = 1 << 236; uint256 internal constant _ROLE_237 = 1 << 237; uint256 internal constant _ROLE_238 = 1 << 238; uint256 internal constant _ROLE_239 = 1 << 239; uint256 internal constant _ROLE_240 = 1 << 240; uint256 internal constant _ROLE_241 = 1 << 241; uint256 internal constant _ROLE_242 = 1 << 242; uint256 internal constant _ROLE_243 = 1 << 243; uint256 internal constant _ROLE_244 = 1 << 244; uint256 internal constant _ROLE_245 = 1 << 245; uint256 internal constant _ROLE_246 = 1 << 246; uint256 internal constant _ROLE_247 = 1 << 247; uint256 internal constant _ROLE_248 = 1 << 248; uint256 internal constant _ROLE_249 = 1 << 249; uint256 internal constant _ROLE_250 = 1 << 250; uint256 internal constant _ROLE_251 = 1 << 251; uint256 internal constant _ROLE_252 = 1 << 252; uint256 internal constant _ROLE_253 = 1 << 253; uint256 internal constant _ROLE_254 = 1 << 254; uint256 internal constant _ROLE_255 = 1 << 255; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Signature verification helper that supports both ECDSA signatures from EOAs /// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol) /// /// @dev Note: /// - The signature checking functions use the ecrecover precompile (0x1). /// - The `bytes memory signature` variants use the identity precompile (0x4) /// to copy memory internally. /// - Unlike ECDSA signatures, contract signatures are revocable. /// - As of Solady version 0.0.134, all `bytes signature` variants accept both /// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// This is for calldata efficiency on smart accounts prevalent on L2s. /// /// WARNING! Do NOT use signatures as unique identifiers: /// - Use a nonce in the digest to prevent replay attacks on the same contract. /// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts. /// EIP-712 also enables readable signing of typed data for better user safety. /// This implementation does NOT check if a signature is non-malleable. library SignatureCheckerLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIGNATURE CHECKING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. if eq(mload(signature), 64) { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } if eq(mload(signature), 65) { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. // Copy the `signature` over. let n := add(0x20, mload(signature)) pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n)) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(returndatasize(), 0x44), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) if eq(signature.length, 64) { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } if eq(signature.length, 65) { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signature.length, 0x64), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), mload(0x60)) // `s`. mstore8(add(m, 0xa4), mload(0x20)) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) mstore(0x20, and(v, 0xff)) // `v`. mstore(0x40, r) // `r`. mstore(0x60, s) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), s) // `s`. mstore8(add(m, 0xa4), v) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1271 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Note: These ERC1271 operations do NOT have an ECDSA fallback. // These functions are intended to be used with the regular `isValidSignatureNow` functions // or other signature verification functions (e.g. P256). /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. // Copy the `signature` over. let n := add(0x20, mload(signature)) pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n)) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(returndatasize(), 0x44), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract. function isValidERC1271SignatureNowCalldata( address signer, bytes32 hash, bytes calldata signature ) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signature.length, 0x64), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`. mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), s) // `s`. mstore8(add(m, 0xa4), v) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC6492 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Note: These ERC6492 operations do NOT have an ECDSA fallback. // These functions are intended to be used with the regular `isValidSignatureNow` functions // or other signature verification functions (e.g. P256). // The calldata variants are excluded for brevity. /// @dev Returns whether `signature` is valid for `hash`. /// If the signature is postfixed with the ERC6492 magic number, it will attempt to /// deploy / prepare the `signer` smart account before doing a regular ERC1271 check. /// Note: This function is NOT reentrancy safe. function isValidERC6492SignatureNowAllowSideEffects( address signer, bytes32 hash, bytes memory signature ) internal returns (bool isValid) { /// @solidity memory-safe-assembly assembly { function callIsValidSignature(signer_, hash_, signature_) -> _isValid { let m_ := mload(0x40) let f_ := shl(224, 0x1626ba7e) mstore(m_, f_) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m_, 0x04), hash_) let d_ := add(m_, 0x24) mstore(d_, 0x40) // The offset of the `signature` in the calldata. let n_ := add(0x20, mload(signature_)) pop(staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_)) _isValid := and( eq(mload(d_), f_), staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20) ) } for { let n := mload(signature) } 1 {} { if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) { isValid := callIsValidSignature(signer, hash, signature) break } let o := add(signature, 0x20) // Signature bytes. let d := add(o, mload(add(o, 0x20))) // Factory calldata. if iszero(extcodesize(signer)) { if iszero(call(gas(), mload(o), 0, add(d, 0x20), mload(d), codesize(), 0x00)) { break } } let s := add(o, mload(add(o, 0x40))) // Inner signature. isValid := callIsValidSignature(signer, hash, s) if iszero(isValid) { if call(gas(), mload(o), 0, add(d, 0x20), mload(d), codesize(), 0x00) { isValid := callIsValidSignature(signer, hash, s) } } break } } } /// @dev Returns whether `signature` is valid for `hash`. /// If the signature is postfixed with the ERC6492 magic number, it will attempt /// to use a reverting verifier to deploy / prepare the `signer` smart account /// and do a `isValidSignature` check via the reverting verifier. /// Note: This function is reentrancy safe. /// The reverting verifier must be be deployed. /// Otherwise, the function will return false if `signer` is not yet deployed / prepared. /// See: https://gist.github.com/Vectorized/846a474c855eee9e441506676800a9ad function isValidERC6492SignatureNow(address signer, bytes32 hash, bytes memory signature) internal returns (bool isValid) { /// @solidity memory-safe-assembly assembly { function callIsValidSignature(signer_, hash_, signature_) -> _isValid { let m_ := mload(0x40) let f_ := shl(224, 0x1626ba7e) mstore(m_, f_) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m_, 0x04), hash_) let d_ := add(m_, 0x24) mstore(d_, 0x40) // The offset of the `signature` in the calldata. let n_ := add(0x20, mload(signature_)) pop(staticcall(gas(), 4, signature_, n_, add(m_, 0x44), n_)) _isValid := and( eq(mload(d_), f_), staticcall(gas(), signer_, m_, add(returndatasize(), 0x44), d_, 0x20) ) } for { let n := mload(signature) } 1 {} { if iszero(eq(mload(add(signature, n)), mul(0x6492, div(not(isValid), 0xffff)))) { isValid := callIsValidSignature(signer, hash, signature) break } if extcodesize(signer) { let o := add(signature, 0x20) // Signature bytes. isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40)))) if isValid { break } } let m := mload(0x40) mstore(m, signer) mstore(add(m, 0x20), hash) let willBeZeroIfRevertingVerifierExists := call( gas(), // Remaining gas. 0x00007bd799e4A591FeA53f8A8a3E9f931626Ba7e, // Reverting verifier. 0, // Send zero ETH. m, // Start of memory. add(returndatasize(), 0x40), // Length of calldata in memory. staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1. 0x00 // Length of returndata to write. ) isValid := gt(returndatasize(), willBeZeroIfRevertingVerifierExists) break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, hash) // Store into scratch space for keccak256. mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes. result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`. } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. /// Note: Supports lengths of `s` up to 999999 bytes. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let sLength := mload(s) let o := 0x20 mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded. mstore(0x00, 0x00) // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`. for { let temp := sLength } 1 {} { o := sub(o, 1) mstore8(o, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } let n := sub(0x3a, o) // Header length: `26 + 32 - o`. // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes. returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20)) mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header. result := keccak256(add(s, sub(0x20, n)), add(n, sLength)) mstore(s, sLength) // Restore the length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IRebootTournament { struct Entry { uint256 ticketBasedCollateral; uint256 creditBasedCollateral; uint256 totalCollateralPaid; uint248 rebuyCount; bool payoutReceived; } struct Result { address player; uint256 multiplier; } struct EntryParams { address account; uint256 tournamentId; uint256 roomId; address swapFromCredit; uint256 swapMinCollateral; uint256 entryAmount; } struct Config { uint256 entryFee; // credit fee to enter tournament (new entry for a new score) uint256 rebuyFee; // credit fee to rebuy into tournament (re-attempt an existing entry to try to improve score) bool isExactFee; // if true, above fees are exact required fees. if false, above fees are minimum fees uint64 entryLimit; // max number of entries allowed per player uint64 maxEntriesPerRoom; // max number of entries allowed per room uint64 rebuyLimit; // max number of rebuys allowed per player per entry uint64 startDate; // start date of tournament (block timestamp) uint64 endDate; // end date of tournament (block timestamp) uint64 ticketProfitToTickets; // % of profit from ticket entry converted to ticket payout (in wei) uint64 creditProfitToTickets; // % of profit from credit entry converted to credit payout (in wei) uint64 creditEntryToTickets; // % of credit entry converted to ticket payout (in wei) uint64 entryDuration; // duration in seconds of entry period for a room once the room is opened uint64 tournamentDuration; // duration in seconds of tournament instance (room) once started uint64 payoutDuration; // duration in seconds to allow payouts for after tournament ends uint96 creditRatio; // ratio of collateral to credits (gets set during register transaction) address creditId; // credit id to use for entry fee (the id is the collateral token address) uint256 bonusCollateral; // amount of collateral to request each time it's needed bytes32 priceFeedPair; // pair to use for price feed (use bytes32(0) for a flat credit fee) } // Tournament IDs function tournamentCount() external view returns (uint256); // Allowed to set contract configs and register tournaments function ADMIN_ROLE() external view returns (bytes32); // Allowed to call `enter`, `rebuy` and `submitResults` function RELAYER_ROLE() external view returns (bytes32); /** * @notice Get the tournament config set by contract admin * * @param _tournamentId ID of the tournament */ function getTournament(uint256 _tournamentId) external view returns (Config memory); /** * @notice Opens a new room for an active tournament * * @param _tournamentId ID of the tournament * @param _roomId ID of the tournament room * @param _openTimestamp Timestamp to open the room */ function createRoom(uint256 _tournamentId, uint256 _roomId, uint64 _openTimestamp) external; /** * @notice Enters a player into a tournament room. If the room does not exist, it will be created. * * @dev A player can only enter a specific room once. * * @param _params entry params struct */ function enter(EntryParams calldata _params) external payable; /** * @notice Allows a player to rebuy into a tournament room for a chance to improve their score * * @param _tournamentId ID of the tournament * @param _account Address of player * @param _roomId ID of the tournament room * @param _swapFromCredit credit token to swap from, use zero address if swap not wanted * @param _swapMinCollateral min amount of output collateral to receive from swap * @param _entryAmount credit amount to spend to enter - if tournament config has `isExactFee` set to true, must be equivalent to `rebuyFee`. Otherwise, must be >= `rebuyFee` */ function rebuy( uint256 _tournamentId, address _account, uint256 _roomId, address _swapFromCredit, uint256 _swapMinCollateral, uint256 _entryAmount ) external payable; /** * @notice Submits the results of a tournament room. Payouts are calculated and credits are minted to players. * * @param _tournamentId ID of the tournament * @param _roomId ID of the tournament room * @param _results Array of results for the room */ function submitResults(uint256 _tournamentId, uint256 _roomId, Result[] memory _results) external; function credits() external view returns (address); /** * @notice Admin function to register a new tournament * * @param _c Config struct for the tournament */ function register(Config memory _c) external returns (uint256 _tournamentId); /** * @notice Get the entry for a player in a room * * @param _tournamentId ID of the tournament * @param _player Address of the player * @param _roomId ID of the tournament room */ function getEntry(uint256 _tournamentId, address _player, uint256 _roomId) external view returns (Entry memory); /** * @notice Cleans up a tournament room after the payout duration has ended. Returns any remaining collateral to the game dev or bonus contract. * * @param _tournamentId ID of the tournament * @param _roomId ID of the tournament room */ function cleanup(uint256 _tournamentId, uint256 _roomId) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; enum Direction { LONG, SHORT } struct Trade { bytes32 pair; uint40 lastUpdatedAt; int104 entryPrice; int104 amountInBips; } struct InternalPrice { int64 price; int32 expo; uint40 publishTime; } struct TournamentConfig { uint16 minimumHoldDuration; uint16 maxLeverage; uint40 startTime; uint40 endTime; uint128 startBalance; mapping(bytes32 pair => InternalPrice finalPrice) finalPrices; mapping(address user => int256 balance) userBalance; mapping(address user => Trade trade) activeTrade; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; /// @title IPythEvents contains the events that Pyth contract emits. /// @dev This interface can be used for listening to the updates for off-chain and testing purposes. interface IPythEvents { /// @dev Emitted when the price feed with `id` has received a fresh update. /// @param id The Pyth Price Feed ID. /// @param publishTime Publish time of the given price update. /// @param price Price of the given price update. /// @param conf Confidence interval of the given price update. event PriceFeedUpdate( bytes32 indexed id, uint64 publishTime, int64 price, uint64 conf ); /// @dev Emitted when a batch price update is processed successfully. /// @param chainId ID of the source chain that the batch price update comes from. /// @param sequenceNumber Sequence number of the batch price update. event BatchPriceFeedUpdate(uint16 chainId, uint64 sequenceNumber); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "solady/=lib/solady/src/", "pyth/=lib/pyth-sdk-solidity/", "NFTMIrror/=lib/NFTMIrror/src/", "pyth-sdk-solidity/=lib/pyth-sdk-solidity/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"pyth","type":"address"},{"internalType":"address","name":"reboot","type":"address"},{"internalType":"address","name":"wape","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"_liquidationBounty","type":"uint256"},{"internalType":"uint256","name":"_baseSlippage","type":"uint256"},{"internalType":"uint256","name":"_slippageIncrement","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyEntered","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[{"internalType":"int256","name":"balanceInBips","type":"int256"},{"internalType":"int256","name":"requiredAmountInBips","type":"int256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientEntryFee","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidPriceUpdates","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"LiquidationBountyTooHigh","type":"error"},{"inputs":[],"name":"MinTimestampNotMet","type":"error"},{"inputs":[],"name":"MinimumHoldDurationNotMet","type":"error"},{"inputs":[],"name":"MismatchedPairs","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NonceAlreadyUsed","type":"error"},{"inputs":[],"name":"NotActive","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"SlippageTooHigh","type":"error"},{"inputs":[],"name":"StalePrice","type":"error"},{"inputs":[],"name":"TournamentActive","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"int256","name":"balance","type":"int256"},{"indexed":false,"internalType":"int256","name":"amount","type":"int256"},{"indexed":false,"internalType":"int256","name":"entryPrice","type":"int256"},{"indexed":false,"internalType":"bytes32","name":"pair","type":"bytes32"}],"name":"AccountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFactor","type":"uint256"}],"name":"BaseSlippageScalingFactorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSigner","type":"address"}],"name":"CounterpartySignerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"int256","name":"balance","type":"int256"},{"indexed":false,"internalType":"int256","name":"pnl","type":"int256"}],"name":"InvalidLiquidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Liquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LiquidationBountyPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newBounty","type":"uint256"}],"name":"LiquidationBountyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFactor","type":"uint256"}],"name":"SlippageScalingFactorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":false,"internalType":"bytes32[]","name":"pairs","type":"bytes32[]"},{"indexed":false,"internalType":"uint40","name":"startTime","type":"uint40"},{"indexed":false,"internalType":"uint40","name":"endTime","type":"uint40"},{"indexed":false,"internalType":"uint128","name":"startBalance","type":"uint128"},{"indexed":false,"internalType":"uint16","name":"maxLeverage","type":"uint16"},{"indexed":false,"internalType":"uint80","name":"entryFee","type":"uint80"},{"indexed":false,"internalType":"uint16","name":"minimumHoldDuration","type":"uint16"},{"indexed":false,"internalType":"uint64","name":"rebuyLimit","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"bonusCollateral","type":"uint256"}],"name":"TournamentCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"int256","name":"amount","type":"int256"},{"indexed":false,"internalType":"int256","name":"executionPrice","type":"int256"},{"indexed":false,"internalType":"bytes32","name":"pair","type":"bytes32"}],"name":"TradeExecuted","type":"event"},{"inputs":[],"name":"SIGNATURE_VALIDITY_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"activeTrade","outputs":[{"components":[{"internalType":"bytes32","name":"pair","type":"bytes32"},{"internalType":"uint40","name":"lastUpdatedAt","type":"uint40"},{"internalType":"int104","name":"entryPrice","type":"int104"},{"internalType":"int104","name":"amountInBips","type":"int104"}],"internalType":"struct Trade","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseSlippageScalingFactor","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"counterpartySigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"pairs","type":"bytes32[]"},{"internalType":"uint16","name":"minimumHoldDuration","type":"uint16"},{"internalType":"uint40","name":"startTime","type":"uint40"},{"internalType":"uint40","name":"endTime","type":"uint40"},{"internalType":"uint128","name":"startBalance","type":"uint128"},{"internalType":"uint16","name":"maxLeverage","type":"uint16"},{"internalType":"uint80","name":"entryFee","type":"uint80"},{"internalType":"uint64","name":"rebuyLimit","type":"uint64"},{"internalType":"uint256","name":"bonusCollateral","type":"uint256"}],"name":"createTournament","outputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"currentPnlFor","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTournamentId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"}],"name":"enterTournament","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"tournamentId","type":"uint256"}],"name":"enterTournamentFor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"},{"internalType":"bytes32","name":"pair","type":"bytes32"}],"name":"finalPrice","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint40","name":"publishTime","type":"uint40"}],"internalType":"struct InternalPrice","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"},{"internalType":"bytes[]","name":"priceUpdates","type":"bytes[]"},{"internalType":"bytes32[]","name":"pairs","type":"bytes32[]"}],"name":"finalizePrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"pair","type":"bytes32"}],"name":"internalPrices","outputs":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint40","name":"publishTime","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"},{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"bytes[]","name":"priceUpdates","type":"bytes[]"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidationBounty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"factor","type":"uint256"}],"name":"setBaseSlippageScalingFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"setCounterpartySigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bounty","type":"uint256"}],"name":"setLiquidationBounty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"factor","type":"uint256"}],"name":"setSlippageIncrementScalingFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slippageIncrementScalingFactor","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"},{"components":[{"internalType":"address","name":"player","type":"address"},{"internalType":"uint256","name":"multiplier","type":"uint256"}],"internalType":"struct IRebootTournament.Result[]","name":"results","type":"tuple[]"}],"name":"submitResults","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"}],"name":"tournaments","outputs":[{"internalType":"uint16","name":"minimumHoldDuration","type":"uint16"},{"internalType":"uint16","name":"maxLeverage","type":"uint16"},{"internalType":"uint40","name":"startTime","type":"uint40"},{"internalType":"uint40","name":"endTime","type":"uint40"},{"internalType":"uint128","name":"startBalance","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"},{"internalType":"bytes32","name":"pair","type":"bytes32"},{"internalType":"bytes[]","name":"priceUpdates","type":"bytes[]"},{"internalType":"int256","name":"amountInBips","type":"int256"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"minTimestamp","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"trade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"pairs","type":"bytes32[]"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint40","name":"publishTime","type":"uint40"}],"internalType":"struct InternalPrice[]","name":"prices","type":"tuple[]"}],"name":"updateManualPriceFeeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"priceUpdates","type":"bytes[]"}],"name":"updatePythPriceFeeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"usedNonces","outputs":[{"internalType":"bool","name":"isUsed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tournamentId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"userBalance","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e03461029357601f61353038819003918201601f19168301916001600160401b038311848410176102985780849260e09460405283398101031261029357610047816102ae565b90610054602082016102ae565b610060604083016102ae565b9061006d606084016102ae565b9160808401519160c060a08601519501519560018060a01b031680158015610282575b8015610271575b6102605732638b78c6d819553260007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3638b78c6d8600c52326000526020600c2068200000040000000000815417809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a36080526001600160a01b0390811660a05260c09190915260019190915516801561026057600080546001600160a01b031916821790556040519081527f433d5aa4c8f989b56375c20361c91cb7dca10cebc7e123572fa796421e85251e90602090a160fa811161024f576020817fd7bf6fb5afa6dde675c1b0e83381bb3d5dc5a0f4711c590e63a0a4ec6494395e92600255604051908152a1600a811161024f576020817f3fff8b1775def0fb5bb8d5be4d00c6de3f320bd44db6653469073a7ded6ddb6992600355604051908152a160405161326d90816102c382396080518181816104d60152818161263c01528181612dee0152612ec7015260a0518181816102460152818161085901528181610c8c01528181610cbf01528181610d1d01528181612175015261292f015260c05181610afc0152f35b63428637bb60e11b60005260046000fd5b63d92e233d60e01b60005260046000fd5b506001600160a01b03831615610097565b506001600160a01b03821615610090565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036102935756fe6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c8063032e9c761461240a5780630989e8df146121f55780630aa4001814612158578063183a4f6e1461213f57806318d913bd1461212157806319a4edb1146120615780631c10893f14611fff5780631cd64df414611fc557806323a1625614611fa95780632569296214611f5e57806326097b5a14611f3d5780632de9480714611f0a57806330a4d88114611eb35780633ccfd60b14611e725780633d46f265146114885780634a4ee7b11461145f5780634d22beb3146114385780634e609e32146113d2578063514e62fc1461139957806354343c551461118257806354d1f13d1461113c5780636717e41c1461110d5780636e5f7d06146110ef578063715018a6146110a45780637503e1b7146110365780637ed3a26414610fc85780638519870514610f7e5780638da5cb5b14610f515780638efaaea914610f08578063b26c24bc14610956578063b2bedf2314610938578063b4e517f6146107fe578063b965cc6b146107c4578063d4f9365814610484578063dcfb21ed14610405578063e2a399e5146103ec578063f04e283e1461039e578063f2fde38b1461035f578063f4277a7e146102cc578063fc8e75041461021f5763fee81cf4146101ea575061000e565b3461021c57602036600319011261021c5761020361248a565b9063389a75e1600c5252602080600c2054604051908152f35b80fd5b503461021c578060031936011261021c57604051631b8acb1f60e21b8152906020826004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156102c05790610288575b602090604051908152f35b506020813d6020116102b8575b816102a26020938361255d565b810103126102b3576020905161027d565b600080fd5b3d9150610295565b604051903d90823e3d90fd5b503461021c57604036600319011261021c576040816060928280516102f0816124f5565b82815282602082015201526004358152600460205260018282200160243582526020522064ffffffffff60405191610327836124f5565b548060070b92838152826040602083019284821c60030b84520192861c1682526040519384525160030b602084015251166040820152f35b50602036600319011261021c5761037461248a565b61037c6128dc565b8060601b156103915761038e9061312e565b80f35b637448fbae82526004601cfd5b50602036600319011261021c576103b361248a565b6103bb6128dc565b63389a75e1600c528082526020600c20805442116103df57908261038e925561312e565b636f5e881883526004601cfd5b50602036600319011261021c5761038e600435336128eb565b503461021c57602036600319011261021c5761041f61248a565b6104276128bb565b6001600160a01b031680156104755781546001600160a01b031916811782556040519081527f433d5aa4c8f989b56375c20361c91cb7dca10cebc7e123572fa796421e85251e90602090a180f35b63d92e233d60e01b8252600482fd5b503461021c57610493366124a0565b92909361049e612889565b85526004602052604085209364ffffffffff855460481c16924284116107b55760405163d47eed4560e01b81526020600482018190527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695919390848061051260248201878a61257e565b0381895afa9384156107aa578994610776575b5060058201906001600160401b03821161076257916001600160401b036105749694926105868c9997956040519b8c9a8b998a98634716e9c560e01b8a52608060048b015260848a019161257e565b878103600319016024890152916127e5565b92604485015216606483015203925af190811561075757839161065b575b5090600101825b8251811015610657578060206105c360019386612875565b510151805160070b9064ffffffffff6060604083015160030b92015116604051926105ed846124f5565b835260208301918252604083019081526106078488612875565b5151885285602052604088209251916001600160401b038454915160401b9264ffffffffff60601b905160601b169316906001600160881b031916179063ffffffff60401b1617179055016105ab565b8380f35b90503d8084833e61066c818361255d565b81019060208183031261074f578051906001600160401b038211610753570181601f8201121561074f578051906001600160401b03821161073b57604051926106bb60208460051b018561255d565b828452602061012081860194028301019181831161073757602001925b8284106106e95750505050386105a4565b6101208483031261073757602061012091604051610706816124f5565b865181526107168584890161281d565b838201526107278560a0890161281d565b60408201528152019301926106d8565b8680fd5b634e487b7160e01b85526041600452602485fd5b8380fd5b8480fd5b6040513d85823e3d90fd5b634e487b7160e01b8a52601160045260248afd5b9093506020813d6020116107a2575b816107926020938361255d565b810103126102b357519238610525565b3d9150610785565b6040513d8b823e3d90fd5b634a65fe1160e01b8752600487fd5b503461021c57604036600319011261021c576107f660209160406107e6612474565b916004358152600485522061303c565b604051908152f35b503461021c57604036600319011261021c57602435906001600160401b03821161021c573660238301121561021c5781600401356001600160401b038111610934573660248260061b8501011161093457610857612889565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692833b156109305760405191639eed5e2160e01b835280606484016004356004860152856024860152606060448601525260246084840192019084905b8082106108fd57505050818394818581819503925af180156108f2576108e15750f35b816108eb9161255d565b61021c5780f35b6040513d84823e3d90fd5b909192833560018060a01b03811680910361073757604082819260019452602087013560208201520194019201906108be565b8280fd5b5080fd5b503461021c578060031936011261021c576020600354604051908152f35b503461021c5761012036600319011261021c576004356001600160401b03811161093457610988903690600401612444565b906024359161ffff8316830361074f5760443564ffffffffff81168103610753576064359364ffffffffff85168503610f04576001600160801b036084351660843503610f045760a4359061ffff821682036107375760c43569ffffffffffffffffffff81168103610f005760e435926001600160401b0384168403610efc57610a10612889565b64ffffffffff808616818a160311610ee85760405197610a2f89612541565b69ffffffffffffffffffff8316895269ffffffffffffffffffff831660208a0152600160408a01526001600160401b0360608a01526001600160401b0360808a01526001600160401b03851660a08a015264ffffffffff861660c08a015264ffffffffff811660e08a0152670de0b6b3a76400006101008a0152670de0b6b3a76400006101208a0152670de0b6b3a76400006101408a015264ffffffffff80871681831603166101608a0152896101808a015262278d006101a08a0152896101c08a015260018060a01b037f0000000000000000000000000000000000000000000000000000000000000000166101e08a0152610104356102008a0152896102208a0152610220604051996328889c6d60e21b8b52805160048c0152602081015160248c01526040810151151560448c01526001600160401b0360608201511660648c01526001600160401b0360808201511660848c01526001600160401b0360a08201511660a48c01526001600160401b0360c08201511660c48c01526001600160401b0360e08201511660e48c01526001600160401b03610100820151166101048c01526001600160401b03610120820151166101248c01526001600160401b03610140820151166101448c01526001600160401b03610160820151166101648c01526001600160401b03610180820151166101848c01526001600160401b036101a0820151166101a48c01526001600160601b036101c0820151166101c48c015260018060a01b036101e0820151166101e48c01526102008101516102048c015201516102248a0152602089610244818d60018060a01b037f0000000000000000000000000000000000000000000000000000000000000000165af1988915610edd578a99610ea9575b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163b15610e9a57604051637aac643f60e01b8152600481018a9052602481018b905264ffffffffff871660448201528a81606481837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af18015610e9e57610e85575b508989809b5260046020526040902080548360101b63ffff0000169063ffff000019906001600160801b0360701b199061ffff8916906dffffffffffffffffffff0000ffff191617168960201b68ffffffffff000000001617168360481b6dffffffffff00000000000000000016176001600160801b0360701b60843560701b16171790556040519788976101208952610120890190610df1926127e5565b9564ffffffffff16602088015264ffffffffff1660408701526084356001600160801b0316606087015261ffff16608086015269ffffffffffffffffffff1660a085015261ffff1660c08401526001600160401b031660e083015261010435610100830152037f07f0d15dca459300ceadf62f30ae8e6b90af800ea554cc7530cc837b96b5d50991a2604051908152602090f35b610e908b809261255d565b610e9a5738610d52565b8980fd5b6040513d8d823e3d90fd5b9098506020813d602011610ed5575b81610ec56020938361255d565b810103126102b357519738610cbc565b3d9150610eb8565b6040513d8c823e3d90fd5b634e487b7160e01b89526011600452602489fd5b8880fd5b8780fd5b8580fd5b503461021c57602036600319011261021c57604060609160043581526005602052205464ffffffffff604051918060070b83528060401c60030b6020840152831c166040820152f35b503461021c578060031936011261021c57638b78c6d819546040516001600160a01b039091168152602090f35b503461021c57604036600319011261021c5760026040610f9c612474565b926004358152600460205220019060018060a01b03166000526020526020604060002054604051908152f35b503461021c57602036600319011261021c57600435610fe56128bb565b683635c9adc5dea000008111611027576020817fa6635fc6998b0f79d9889a9d1cba35ab931d2e68ebe46f897c1fb915a5b874e492600155604051908152a180f35b63263d748960e11b8252600482fd5b503461021c57602036600319011261021c57604060a0916004358152600460205220546001600160801b036040519161ffff8116835261ffff8160101c16602084015264ffffffffff8160201c16604084015264ffffffffff8160481c16606084015260701c166080820152f35b508060031936011261021c576110b86128dc565b80638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380638b78c6d8195580f35b503461021c578060031936011261021c576020600154604051908152f35b503461021c57602036600319011261021c5760ff60406020926004358152600684522054166040519015158152f35b508060031936011261021c5763389a75e1600c52338152806020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c928280a280f35b503461021c576111b5611194366124a0565b848796929394959652600460205260408720926111b084612c26565b612617565b8493859360028301925b848610611225578787806111d1575080f35b8180808084335af16111e1612740565b5015611216576040519081527f0b8af83edb58a3c0794e9aadbac8779b13e493370e536255cf3b1a7da9239d3e60203392a280f35b6312171d8360e31b8252600482fd5b90919293949561124761124161123c89898761271a565b6127d1565b8361303c565b604061125761123c8a8a8861271a565b6001600160a01b0316600090815260208890522054818101908a831280159183129182169115161761076257891315611326575060019088604061129f61123c8b8b8961271a565b600090858060a01b03168152886020522055888260406112c361123c8c8c8a61271a565b600090838060a01b031681526003870160205220828155015581540196818060a01b036112f461123c838a8861271a565b16857f03b910a1639200ab2b0061788a7e4d39f45a305c900ac7f92a77b9a8447df9dc8b80a35b0194939291906111bf565b9660019197857fdc57291b7b129d2079685e49dc1d00cea767d4f624f9523d658fd5ce90a6469660408a8161136e61123c8861136761123c828f889061271a565b948d61271a565b600090898060a01b031681528c60205220549482519586526020860152868060a01b031693a361131b565b503461021c57604036600319011261021c576113b361248a565b90638b78c6d8600c5252602060243581600c2054161515604051908152f35b503461021c57602036600319011261021c576004356113ef6128bb565b600a8111611429576020817f3fff8b1775def0fb5bb8d5be4d00c6de3f320bd44db6653469073a7ded6ddb6992600355604051908152a180f35b63428637bb60e11b8252600482fd5b503461021c578060031936011261021c57546040516001600160a01b039091168152602090f35b50604036600319011261021c5761038e61147761248a565b61147f6128dc565b6024359061316c565b503461021c5761010036600319011261021c576044356001600160401b038111610934576114ba903690600401612444565b608435906001600160a01b038216820361074f5760e435906001600160401b0382116107535736602383011215610753576001600160401b03826004013511610753573660248360040135840101116107535760643515611e635760a4354210611e5457601e60a435014211611e4557600435855260046020526040852061154181612c26565b60018060a01b038416600052600381016020526040600020916040519561156787612526565b6001845494858952015464ffffffffff811660208901528060281c600c0b60408901528060901c600c0b6060890152889480611dce575b505060c4358852600660205260ff604089205416611dc05760c4358852600660205260408820805460ff19166001179055606435881215611db85787945b6040516001600160601b03198860601b166020820152600435603482015260243560548201526002871015611da4578660f81b607482015260a435607582015260c43560958201526095815261163360b58261255d565b805160209182012090527b19457468657265756d205369676e6564204d6573736167653a0a33328952603c600420336001600160a01b03891603611d6d578954611691926004810135926024909101916001600160a01b0316612c68565b15611d5e57906116a091612617565b6116ab602435612d7c565b916116c98387906060906040830151600c0b9003910151600c0b0290565b90600283019460018060a01b03871660005285602052604060002054916116f660608a0151600c0b612f53565b916127108061ffff885460101c168782880201020581898602059084600014611d5857015b02611727606435612f53565b92888402918d8512600160ff1b8b1416611d44578483058a1485151715611d4457808313611d1e575015611bb557508183036118a157505050611817939495965060018060a01b03871660005285602052612710604060002092050190556040519061179282612526565b868252602082019164ffffffffff4216835264ffffffffff80600160408401938b8552600360608201968d8852838060a01b038d1660005201602052604060002090518155019451161664ffffffffff198454161783555182549060281b600160281b600160901b031690600160281b600160901b03191617825551600c0b9061279f565b6040805160643581526020810192909252602435908201526001600160a01b0383169060c435906004359060008051602061321883398151915290606090a460018060a01b038216600052602052604060002054906040519083825283602083015283604083015260018060a01b0316906000805160206131f8833981519152606060043592a480f35b939796959493828212156119cb57506118d560039493926127109260608c0151600c0b606435600c0b01600c0b9a0261277f565b050160018060a01b0386166000528460205260406000205560018060a01b03851660005281810160205261191086600160406000200161279f565b6001600160a01b0385166000818152919092016020908152604091829020600101805464ffffffffff421664ffffffffff199091161790558151606435815290810193909352602435908301529060c435906004359060008051602061321883398151915290606090a460018060a01b03821660005260205260408060002054930151600c0b6040519283526020830152602435604083015260018060a01b0316906000805160206131f8833981519152606060043592a480f35b949396989150506060919682820151600c0b606435600c0b01600c0b9760018060a01b038a1660005286602052612710604060002092050190550151600c0b870380600c0b908103611ba15760408051600c9290920b82526020820183905260243590820152611b0a92611a729290916001600160a01b0389169060c435906004359060008051602061321883398151915290606090a4611a6d818802612f53565b612f83565b9260405190611a8082612526565b6024358252602082019164ffffffffff4216835264ffffffffff806001604084019389600c0b8552600360608201968c88528d848060a01b031660005201602052604060002090518155019451161664ffffffffff198454161783555182549060281b600160281b600160901b031690600160281b600160901b03191617825551600c0b9061279f565b60408051600c85900b815260208101849052602435918101919091526001600160a01b0385169060c435906004359060008051602061321883398151915290606090a46001600160a01b039390931660008181526020948552604090819020548151600c9590950b8552948401929092526024359183019190915290600435906000805160206131f883398151915290606090a480f35b634e487b7160e01b88526011600452602488fd5b611c8b9550611bf9945096611bd092939698979a999a612f83565b938181604060608b0151600c0b606435600c0b01600c0b9a0151600c0b0291019185020161277f565b93858764ffffffffff806001604051611c1181612526565b602435815260036020820197844216895260408301968d600c0b885260608401988952848060a01b031660005201602052604060002090518155019451161664ffffffffff198454161783555182549060281b600160281b600160901b031690600160281b600160901b03191617825551600c0b9061279f565b6040805160643581526020810192909252602435908201526001600160a01b0385169060c435906004359060008051602061321883398151915290606090a46001600160a01b039390931660008181526020948552604090819020548151600c9590950b8552948401929092526024359183019190915290600435906000805160206131f883398151915290606090a480f35b8d83828260449412611d3d575b63e3f3d0e360e01b8352600452602452fd5b5081611d2b565b634e487b7160e01b8e52601160045260248efd5b0361171b565b638baa579f60e01b8852600488fd5b8954336001600160a01b0390911603611d955790611691916024826004013592019089612c68565b6348f5c3ed60e01b8a5260048afd5b634e487b7160e01b8a52602160045260248afd5b6001946115dc565b623f613760e71b8852600488fd5b60243514611de557630631dbcd60e11b8952600489fd5b8860643513898260901c600c0b1303611e01575b50388061159e565b90935064ffffffffff61ffff84541691160164ffffffffff8111611ba15764ffffffffff42911611611e365760019238611df9565b633e7c0cc760e11b8752600487fd5b630819bdcd60e01b8552600485fd5b631abad6d560e11b8552600485fd5b63162908e360e11b8552600485fd5b503461021c578060031936011261021c57611e8b6128dc565b8080808047335af1611e9b612740565b5015611ea45780f35b6312171d8360e31b8152600490fd5b503461021c57602036600319011261021c57600435611ed06128bb565b60fa8111611429576020817fd7bf6fb5afa6dde675c1b0e83381bb3d5dc5a0f4711c590e63a0a4ec6494395e92600255604051908152a180f35b503461021c57602036600319011261021c57611f2461248a565b90638b78c6d8600c5252602080600c2054604051908152f35b50604036600319011261021c5761038e611f5561248a565b602435906128eb565b508060031936011261021c5763389a75e1600c523381526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d8280a280f35b503461021c578060031936011261021c576020604051601e8152f35b503461021c57604036600319011261021c57602090611fe261248a565b60243591638b78c6d8600c52528082600c20541614604051908152f35b50604036600319011261021c5761201461248a565b61201c6128dc565b638b78c6d8600c5281526020600c20602435815417809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe268380a380f35b503461021c57604036600319011261021c576003604061207f612474565b92806060835161208e81612526565b828152826020820152828582015201526004358152600460205220019060018060a01b0316600052602052608060406000206040516120cc81612526565b600182549283835201549064ffffffffff602082018184168152606060408401938560281c600c0b8552019360901c600c0b84526040519485525116602084015251600c0b604083015251600c0b6060820152f35b503461021c578060031936011261021c576020600254604051908152f35b50602036600319011261021c5761038e6004353361316c565b503461021c57602036600319011261021c57612172612889565b807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156121f257818091604460405180958193633d1a69db60e21b835260043560048401528160248401525af180156121e5576121d75780f35b6121e09161255d565b388180f35b50604051903d90823e3d90fd5b50fd5b503461021c57604036600319011261021c576004356001600160401b03811161093457612226903690600401612444565b602435916001600160401b03831161074f573660238401121561074f578260040135926001600160401b03841161075357366024606086028301011161075357638b78c6d8600c52338552600160581b6020600c205416156123fd578383036123ee57845b838110612296578580f35b848110156123da576060810282016060602319823603011261073757604051906122bf826124f5565b60248101358060070b8103610efc5782526044810135908160030b8203610efc57602083019182526064013564ffffffffff81168103610efc576040830190815261230b84888861271a565b3560016242006960e01b03196001600160e01b03198216016123cb574264ffffffffff835116116123bc579060019493929164ffffffffff825116818c52600560205264ffffffffff60408d205460601c1610156123b3578a52600560205260408a209251916001600160401b038454915160401b9264ffffffffff60601b905160601b169316906001600160881b031916179063ffffffff60401b16171790555b0161228b565b505050506123ad565b63b7d0949760e01b8a5260048afd5b631bd2d0af60e01b8a5260048afd5b634e487b7160e01b86526032600452602486fd5b63512509d360e11b8552600485fd5b6382b4290085526004601cfd5b503461021c57602036600319011261021c576004356001600160401b0381116109345761243e61038e913690600401612444565b90612617565b9181601f840112156102b3578235916001600160401b0383116102b3576020808501948460051b0101116102b357565b602435906001600160a01b03821682036102b357565b600435906001600160a01b03821682036102b357565b9060606003198301126102b357600435916024356001600160401b0381116102b357816124cf91600401612444565b92909291604435906001600160401b0382116102b3576124f191600401612444565b9091565b606081019081106001600160401b0382111761251057604052565b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b0382111761251057604052565b61024081019081106001600160401b0382111761251057604052565b90601f801991011681019081106001600160401b0382111761251057604052565b90602083828152019060208160051b85010193836000915b8383106125a65750505050505090565b909192939495601f198282030186528635601e19843603018112156102b357830190602082359201916001600160401b0381116102b35780360383136102b3576020828280600196849695859652848401376000828201840152601f01601f19160101980196019493019190612596565b6000918061262457505050565b60405163d47eed4560e01b81526020600482018190527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316929190818061267760248201868961257e565b0381865afa90811561270f5785916126dd575b50823b1561075357916126be93918593604051809681958294631df3cbc560e31b845260206004850152602484019161257e565b03925af180156108f2576126d0575050565b816126da9161255d565b50565b90506020813d602011612707575b816126f86020938361255d565b8101031261075357513861268a565b3d91506126eb565b6040513d87823e3d90fd5b919081101561272a5760051b0190565b634e487b7160e01b600052603260045260246000fd5b3d1561277a573d906001600160401b038211612510576040519161276e601f8201601f19166020018461255d565b82523d6000602084013e565b606090565b8115612789570590565b634e487b7160e01b600052601260045260246000fd5b9081549060901b6cffffffffffffffffffffffffff60901b16906cffffffffffffffffffffffffff60901b1916179055565b356001600160a01b03811681036102b35790565b81835290916001600160fb1b0383116102b35760209260051b809284830137010190565b51906001600160401b03821682036102b357565b91908260809103126102b35760405161283581612526565b809280518060070b81036102b357825261285160208201612809565b602083015260408101518060030b81036102b3576040830152606090810151910152565b805182101561272a5760209160051b010190565b638b78c6d8600c5233600052682000000000000000006020600c205416156128ad57565b6382b429006000526004601cfd5b638b78c6d8600c5233600052650400000000006020600c205416156128ad57565b638b78c6d8195433036128ad57565b600082815260046020526040812090600282019260018060a01b0381168252836020526040822054612c175761292083612c26565b60015434039460018060a01b037f000000000000000000000000000000000000000000000000000000000000000016604051630696f5ff60e21b815282600482015261024081602481855afa90811561270f578591612a9f575b50516001600160a01b03909316963388141580612a96575b612a87576040519160c083018381106001600160401b03821117612a735760405288835260208301938452604083019486865260608401878152608085019088825260a08601928352833b15610efc57604051633116e47560e01b815295516001600160a01b03908116600488015296516024870152965160448601529551909416606484015293516084830152915160a4820152918391839160c49183915af180156108f257906001600160801b03939291612a63575b50505460701c16600f0b91600052602052604060002055565b81612a6d9161255d565b38612a4a565b634e487b7160e01b87526041600452602487fd5b6388935db960e01b8552600485fd5b50838110612992565b9050610240813d8211612c0f575b81612abb610240938361255d565b810103126107535760405190612ad082612541565b805182526020810151602083015260408101518015158103610737576040830152612afd60608201612809565b6060830152612b0e60808201612809565b6080830152612b1f60a08201612809565b60a0830152612b3060c08201612809565b60c0830152612b4160e08201612809565b60e0830152612b536101008201612809565b610100830152612b666101208201612809565b610120830152612b796101408201612809565b610140830152612b8c6101608201612809565b610160830152612b9f6101808201612809565b610180830152612bb26101a08201612809565b6101a08301526101c08101516001600160601b0381168103610737576101c08301526101e08101516001600160a01b03811681036107375790610220916101e084015261020081015161020084015201516102208201523861297a565b3d9150612aad565b637863668360e01b8252600482fd5b5464ffffffffff8160201c164210908115612c54575b50612c4357565b634065aaf160e11b60005260046000fd5b64ffffffffff915060481c16421138612c3c565b600094939192906001600160a01b031680612c84575b50505050565b9091929450604051948060005260408414612d30575b60418414612cf3575b946020939495600060605281604052630b135d3f60e11b8252600482015260648560248301968795604087528160448601528385013701915afa9051630b135d3f60e11b14169038808080612c7e565b604083013560001a60205260408381376020600160806000825afa5182183d1517612ca35750505050600191600060605260405238808080612c7e565b60208381013560ff81901c601b01825284356040526001600160ff1b0316606052600160806000825afa5182183d1517612c9a5750505050600191600060605260405238808080612c7e565b6001600160e01b031981166242006960e01b03612eaa576000526005602052604060002060405190612dad826124f5565b548060070b825264ffffffffff60208301918060401c60030b835260601c1680604084015260405163e18910a360e01b815260208160048160018060a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa908115612e9e57600091612e6c575b50420390428211612e565710612e4557612e42915160070b905160030b906131b3565b90565b630cd5fa0760e11b60005260046000fd5b634e487b7160e01b600052601160045260246000fd5b90506020813d602011612e96575b81612e876020938361255d565b810103126102b3575138612e1f565b3d9150612e7a565b6040513d6000823e3d90fd5b6040516331d98b3f60e01b815260048101919091526080816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa8015612e9e57600090612f17575b612e4291506040815160070b91015160030b906131b3565b5060803d608011612f4c575b612f2d818361255d565b8101906080818303126102b357612e4291612f479161281d565b612eff565b503d612f23565b6000808212612f60575090565b600160ff1b8214612f6f570390565b634e487b7160e01b81526011600452602490fd5b69021e19e0c9bab2400000909291920590819060028110156130265761301d576001915b620f4240811215612fc3575050620f4240600254830205020190565b629896801315612fdd57506207a120600254830205020190565b6000906207a12060025485020590629896806003548602055b6298968082121561300957505001020190565b9092611f0782612710920194020590612ff6565b60001991612fa7565b634e487b7160e01b600052602160045260246000fd5b9060018060a01b03166000526003810160205260406000209060405161306181612526565b6001835493848352015464ffffffffff811660208301528060281c600c0b604083015260901c600c0b6060820152821561312657612710926001613118930190806000528160205260406000205460070b151560001461311c576000526020526131016040600020604051906130d6826124f5565b54908160070b90818152604064ffffffffff84821c60030b9485602085015260601c169101526131b3565b6060906040830151600c0b9003910151600c0b0290565b0590565b6131019150612d7c565b505050600090565b60018060a01b031680638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3638b78c6d81955565b638b78c6d8600c526000526020600c2090815490811618809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3565b90601119600382900b12156131e2579063ffffffff612e429260120160030b60000316600a0a9060070b61277f565b63ffffffff9060120116600a0a9060070b029056fec1c8f5dd8ba0a07eb2a8a0b712b36ad1cc969c7f934c8decf86f98390b197ca412cce1add089ae91857f01bb906472895a65b5f522b9d100325a7f551e530f5ca26469706673582212204bd0c5a03a900e82ca61e3b0968be7ffbaee172c0d8d5625b735d0f6e047ac9064736f6c634300081c00330000000000000000000000002880ab155794e7179c9ee2e38200202908c17b430000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac5600000000000000000000000048b62137edfa95a428d35c09e44256a739f6b5570000000000000000000000007a114d38a11b8b4dc2f74555b5b2bb1f5bd742c9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c8063032e9c761461240a5780630989e8df146121f55780630aa4001814612158578063183a4f6e1461213f57806318d913bd1461212157806319a4edb1146120615780631c10893f14611fff5780631cd64df414611fc557806323a1625614611fa95780632569296214611f5e57806326097b5a14611f3d5780632de9480714611f0a57806330a4d88114611eb35780633ccfd60b14611e725780633d46f265146114885780634a4ee7b11461145f5780634d22beb3146114385780634e609e32146113d2578063514e62fc1461139957806354343c551461118257806354d1f13d1461113c5780636717e41c1461110d5780636e5f7d06146110ef578063715018a6146110a45780637503e1b7146110365780637ed3a26414610fc85780638519870514610f7e5780638da5cb5b14610f515780638efaaea914610f08578063b26c24bc14610956578063b2bedf2314610938578063b4e517f6146107fe578063b965cc6b146107c4578063d4f9365814610484578063dcfb21ed14610405578063e2a399e5146103ec578063f04e283e1461039e578063f2fde38b1461035f578063f4277a7e146102cc578063fc8e75041461021f5763fee81cf4146101ea575061000e565b3461021c57602036600319011261021c5761020361248a565b9063389a75e1600c5252602080600c2054604051908152f35b80fd5b503461021c578060031936011261021c57604051631b8acb1f60e21b8152906020826004817f0000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac566001600160a01b03165afa9081156102c05790610288575b602090604051908152f35b506020813d6020116102b8575b816102a26020938361255d565b810103126102b3576020905161027d565b600080fd5b3d9150610295565b604051903d90823e3d90fd5b503461021c57604036600319011261021c576040816060928280516102f0816124f5565b82815282602082015201526004358152600460205260018282200160243582526020522064ffffffffff60405191610327836124f5565b548060070b92838152826040602083019284821c60030b84520192861c1682526040519384525160030b602084015251166040820152f35b50602036600319011261021c5761037461248a565b61037c6128dc565b8060601b156103915761038e9061312e565b80f35b637448fbae82526004601cfd5b50602036600319011261021c576103b361248a565b6103bb6128dc565b63389a75e1600c528082526020600c20805442116103df57908261038e925561312e565b636f5e881883526004601cfd5b50602036600319011261021c5761038e600435336128eb565b503461021c57602036600319011261021c5761041f61248a565b6104276128bb565b6001600160a01b031680156104755781546001600160a01b031916811782556040519081527f433d5aa4c8f989b56375c20361c91cb7dca10cebc7e123572fa796421e85251e90602090a180f35b63d92e233d60e01b8252600482fd5b503461021c57610493366124a0565b92909361049e612889565b85526004602052604085209364ffffffffff855460481c16924284116107b55760405163d47eed4560e01b81526020600482018190527f0000000000000000000000002880ab155794e7179c9ee2e38200202908c17b436001600160a01b031695919390848061051260248201878a61257e565b0381895afa9384156107aa578994610776575b5060058201906001600160401b03821161076257916001600160401b036105749694926105868c9997956040519b8c9a8b998a98634716e9c560e01b8a52608060048b015260848a019161257e565b878103600319016024890152916127e5565b92604485015216606483015203925af190811561075757839161065b575b5090600101825b8251811015610657578060206105c360019386612875565b510151805160070b9064ffffffffff6060604083015160030b92015116604051926105ed846124f5565b835260208301918252604083019081526106078488612875565b5151885285602052604088209251916001600160401b038454915160401b9264ffffffffff60601b905160601b169316906001600160881b031916179063ffffffff60401b1617179055016105ab565b8380f35b90503d8084833e61066c818361255d565b81019060208183031261074f578051906001600160401b038211610753570181601f8201121561074f578051906001600160401b03821161073b57604051926106bb60208460051b018561255d565b828452602061012081860194028301019181831161073757602001925b8284106106e95750505050386105a4565b6101208483031261073757602061012091604051610706816124f5565b865181526107168584890161281d565b838201526107278560a0890161281d565b60408201528152019301926106d8565b8680fd5b634e487b7160e01b85526041600452602485fd5b8380fd5b8480fd5b6040513d85823e3d90fd5b634e487b7160e01b8a52601160045260248afd5b9093506020813d6020116107a2575b816107926020938361255d565b810103126102b357519238610525565b3d9150610785565b6040513d8b823e3d90fd5b634a65fe1160e01b8752600487fd5b503461021c57604036600319011261021c576107f660209160406107e6612474565b916004358152600485522061303c565b604051908152f35b503461021c57604036600319011261021c57602435906001600160401b03821161021c573660238301121561021c5781600401356001600160401b038111610934573660248260061b8501011161093457610857612889565b7f0000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac566001600160a01b031692833b156109305760405191639eed5e2160e01b835280606484016004356004860152856024860152606060448601525260246084840192019084905b8082106108fd57505050818394818581819503925af180156108f2576108e15750f35b816108eb9161255d565b61021c5780f35b6040513d84823e3d90fd5b909192833560018060a01b03811680910361073757604082819260019452602087013560208201520194019201906108be565b8280fd5b5080fd5b503461021c578060031936011261021c576020600354604051908152f35b503461021c5761012036600319011261021c576004356001600160401b03811161093457610988903690600401612444565b906024359161ffff8316830361074f5760443564ffffffffff81168103610753576064359364ffffffffff85168503610f04576001600160801b036084351660843503610f045760a4359061ffff821682036107375760c43569ffffffffffffffffffff81168103610f005760e435926001600160401b0384168403610efc57610a10612889565b64ffffffffff808616818a160311610ee85760405197610a2f89612541565b69ffffffffffffffffffff8316895269ffffffffffffffffffff831660208a0152600160408a01526001600160401b0360608a01526001600160401b0360808a01526001600160401b03851660a08a015264ffffffffff861660c08a015264ffffffffff811660e08a0152670de0b6b3a76400006101008a0152670de0b6b3a76400006101208a0152670de0b6b3a76400006101408a015264ffffffffff80871681831603166101608a0152896101808a015262278d006101a08a0152896101c08a015260018060a01b037f00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557166101e08a0152610104356102008a0152896102208a0152610220604051996328889c6d60e21b8b52805160048c0152602081015160248c01526040810151151560448c01526001600160401b0360608201511660648c01526001600160401b0360808201511660848c01526001600160401b0360a08201511660a48c01526001600160401b0360c08201511660c48c01526001600160401b0360e08201511660e48c01526001600160401b03610100820151166101048c01526001600160401b03610120820151166101248c01526001600160401b03610140820151166101448c01526001600160401b03610160820151166101648c01526001600160401b03610180820151166101848c01526001600160401b036101a0820151166101a48c01526001600160601b036101c0820151166101c48c015260018060a01b036101e0820151166101e48c01526102008101516102048c015201516102248a0152602089610244818d60018060a01b037f0000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac56165af1988915610edd578a99610ea9575b507f0000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac566001600160a01b03163b15610e9a57604051637aac643f60e01b8152600481018a9052602481018b905264ffffffffff871660448201528a81606481837f0000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac566001600160a01b03165af18015610e9e57610e85575b508989809b5260046020526040902080548360101b63ffff0000169063ffff000019906001600160801b0360701b199061ffff8916906dffffffffffffffffffff0000ffff191617168960201b68ffffffffff000000001617168360481b6dffffffffff00000000000000000016176001600160801b0360701b60843560701b16171790556040519788976101208952610120890190610df1926127e5565b9564ffffffffff16602088015264ffffffffff1660408701526084356001600160801b0316606087015261ffff16608086015269ffffffffffffffffffff1660a085015261ffff1660c08401526001600160401b031660e083015261010435610100830152037f07f0d15dca459300ceadf62f30ae8e6b90af800ea554cc7530cc837b96b5d50991a2604051908152602090f35b610e908b809261255d565b610e9a5738610d52565b8980fd5b6040513d8d823e3d90fd5b9098506020813d602011610ed5575b81610ec56020938361255d565b810103126102b357519738610cbc565b3d9150610eb8565b6040513d8c823e3d90fd5b634e487b7160e01b89526011600452602489fd5b8880fd5b8780fd5b8580fd5b503461021c57602036600319011261021c57604060609160043581526005602052205464ffffffffff604051918060070b83528060401c60030b6020840152831c166040820152f35b503461021c578060031936011261021c57638b78c6d819546040516001600160a01b039091168152602090f35b503461021c57604036600319011261021c5760026040610f9c612474565b926004358152600460205220019060018060a01b03166000526020526020604060002054604051908152f35b503461021c57602036600319011261021c57600435610fe56128bb565b683635c9adc5dea000008111611027576020817fa6635fc6998b0f79d9889a9d1cba35ab931d2e68ebe46f897c1fb915a5b874e492600155604051908152a180f35b63263d748960e11b8252600482fd5b503461021c57602036600319011261021c57604060a0916004358152600460205220546001600160801b036040519161ffff8116835261ffff8160101c16602084015264ffffffffff8160201c16604084015264ffffffffff8160481c16606084015260701c166080820152f35b508060031936011261021c576110b86128dc565b80638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380638b78c6d8195580f35b503461021c578060031936011261021c576020600154604051908152f35b503461021c57602036600319011261021c5760ff60406020926004358152600684522054166040519015158152f35b508060031936011261021c5763389a75e1600c52338152806020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c928280a280f35b503461021c576111b5611194366124a0565b848796929394959652600460205260408720926111b084612c26565b612617565b8493859360028301925b848610611225578787806111d1575080f35b8180808084335af16111e1612740565b5015611216576040519081527f0b8af83edb58a3c0794e9aadbac8779b13e493370e536255cf3b1a7da9239d3e60203392a280f35b6312171d8360e31b8252600482fd5b90919293949561124761124161123c89898761271a565b6127d1565b8361303c565b604061125761123c8a8a8861271a565b6001600160a01b0316600090815260208890522054818101908a831280159183129182169115161761076257891315611326575060019088604061129f61123c8b8b8961271a565b600090858060a01b03168152886020522055888260406112c361123c8c8c8a61271a565b600090838060a01b031681526003870160205220828155015581540196818060a01b036112f461123c838a8861271a565b16857f03b910a1639200ab2b0061788a7e4d39f45a305c900ac7f92a77b9a8447df9dc8b80a35b0194939291906111bf565b9660019197857fdc57291b7b129d2079685e49dc1d00cea767d4f624f9523d658fd5ce90a6469660408a8161136e61123c8861136761123c828f889061271a565b948d61271a565b600090898060a01b031681528c60205220549482519586526020860152868060a01b031693a361131b565b503461021c57604036600319011261021c576113b361248a565b90638b78c6d8600c5252602060243581600c2054161515604051908152f35b503461021c57602036600319011261021c576004356113ef6128bb565b600a8111611429576020817f3fff8b1775def0fb5bb8d5be4d00c6de3f320bd44db6653469073a7ded6ddb6992600355604051908152a180f35b63428637bb60e11b8252600482fd5b503461021c578060031936011261021c57546040516001600160a01b039091168152602090f35b50604036600319011261021c5761038e61147761248a565b61147f6128dc565b6024359061316c565b503461021c5761010036600319011261021c576044356001600160401b038111610934576114ba903690600401612444565b608435906001600160a01b038216820361074f5760e435906001600160401b0382116107535736602383011215610753576001600160401b03826004013511610753573660248360040135840101116107535760643515611e635760a4354210611e5457601e60a435014211611e4557600435855260046020526040852061154181612c26565b60018060a01b038416600052600381016020526040600020916040519561156787612526565b6001845494858952015464ffffffffff811660208901528060281c600c0b60408901528060901c600c0b6060890152889480611dce575b505060c4358852600660205260ff604089205416611dc05760c4358852600660205260408820805460ff19166001179055606435881215611db85787945b6040516001600160601b03198860601b166020820152600435603482015260243560548201526002871015611da4578660f81b607482015260a435607582015260c43560958201526095815261163360b58261255d565b805160209182012090527b19457468657265756d205369676e6564204d6573736167653a0a33328952603c600420336001600160a01b03891603611d6d578954611691926004810135926024909101916001600160a01b0316612c68565b15611d5e57906116a091612617565b6116ab602435612d7c565b916116c98387906060906040830151600c0b9003910151600c0b0290565b90600283019460018060a01b03871660005285602052604060002054916116f660608a0151600c0b612f53565b916127108061ffff885460101c168782880201020581898602059084600014611d5857015b02611727606435612f53565b92888402918d8512600160ff1b8b1416611d44578483058a1485151715611d4457808313611d1e575015611bb557508183036118a157505050611817939495965060018060a01b03871660005285602052612710604060002092050190556040519061179282612526565b868252602082019164ffffffffff4216835264ffffffffff80600160408401938b8552600360608201968d8852838060a01b038d1660005201602052604060002090518155019451161664ffffffffff198454161783555182549060281b600160281b600160901b031690600160281b600160901b03191617825551600c0b9061279f565b6040805160643581526020810192909252602435908201526001600160a01b0383169060c435906004359060008051602061321883398151915290606090a460018060a01b038216600052602052604060002054906040519083825283602083015283604083015260018060a01b0316906000805160206131f8833981519152606060043592a480f35b939796959493828212156119cb57506118d560039493926127109260608c0151600c0b606435600c0b01600c0b9a0261277f565b050160018060a01b0386166000528460205260406000205560018060a01b03851660005281810160205261191086600160406000200161279f565b6001600160a01b0385166000818152919092016020908152604091829020600101805464ffffffffff421664ffffffffff199091161790558151606435815290810193909352602435908301529060c435906004359060008051602061321883398151915290606090a460018060a01b03821660005260205260408060002054930151600c0b6040519283526020830152602435604083015260018060a01b0316906000805160206131f8833981519152606060043592a480f35b949396989150506060919682820151600c0b606435600c0b01600c0b9760018060a01b038a1660005286602052612710604060002092050190550151600c0b870380600c0b908103611ba15760408051600c9290920b82526020820183905260243590820152611b0a92611a729290916001600160a01b0389169060c435906004359060008051602061321883398151915290606090a4611a6d818802612f53565b612f83565b9260405190611a8082612526565b6024358252602082019164ffffffffff4216835264ffffffffff806001604084019389600c0b8552600360608201968c88528d848060a01b031660005201602052604060002090518155019451161664ffffffffff198454161783555182549060281b600160281b600160901b031690600160281b600160901b03191617825551600c0b9061279f565b60408051600c85900b815260208101849052602435918101919091526001600160a01b0385169060c435906004359060008051602061321883398151915290606090a46001600160a01b039390931660008181526020948552604090819020548151600c9590950b8552948401929092526024359183019190915290600435906000805160206131f883398151915290606090a480f35b634e487b7160e01b88526011600452602488fd5b611c8b9550611bf9945096611bd092939698979a999a612f83565b938181604060608b0151600c0b606435600c0b01600c0b9a0151600c0b0291019185020161277f565b93858764ffffffffff806001604051611c1181612526565b602435815260036020820197844216895260408301968d600c0b885260608401988952848060a01b031660005201602052604060002090518155019451161664ffffffffff198454161783555182549060281b600160281b600160901b031690600160281b600160901b03191617825551600c0b9061279f565b6040805160643581526020810192909252602435908201526001600160a01b0385169060c435906004359060008051602061321883398151915290606090a46001600160a01b039390931660008181526020948552604090819020548151600c9590950b8552948401929092526024359183019190915290600435906000805160206131f883398151915290606090a480f35b8d83828260449412611d3d575b63e3f3d0e360e01b8352600452602452fd5b5081611d2b565b634e487b7160e01b8e52601160045260248efd5b0361171b565b638baa579f60e01b8852600488fd5b8954336001600160a01b0390911603611d955790611691916024826004013592019089612c68565b6348f5c3ed60e01b8a5260048afd5b634e487b7160e01b8a52602160045260248afd5b6001946115dc565b623f613760e71b8852600488fd5b60243514611de557630631dbcd60e11b8952600489fd5b8860643513898260901c600c0b1303611e01575b50388061159e565b90935064ffffffffff61ffff84541691160164ffffffffff8111611ba15764ffffffffff42911611611e365760019238611df9565b633e7c0cc760e11b8752600487fd5b630819bdcd60e01b8552600485fd5b631abad6d560e11b8552600485fd5b63162908e360e11b8552600485fd5b503461021c578060031936011261021c57611e8b6128dc565b8080808047335af1611e9b612740565b5015611ea45780f35b6312171d8360e31b8152600490fd5b503461021c57602036600319011261021c57600435611ed06128bb565b60fa8111611429576020817fd7bf6fb5afa6dde675c1b0e83381bb3d5dc5a0f4711c590e63a0a4ec6494395e92600255604051908152a180f35b503461021c57602036600319011261021c57611f2461248a565b90638b78c6d8600c5252602080600c2054604051908152f35b50604036600319011261021c5761038e611f5561248a565b602435906128eb565b508060031936011261021c5763389a75e1600c523381526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d8280a280f35b503461021c578060031936011261021c576020604051601e8152f35b503461021c57604036600319011261021c57602090611fe261248a565b60243591638b78c6d8600c52528082600c20541614604051908152f35b50604036600319011261021c5761201461248a565b61201c6128dc565b638b78c6d8600c5281526020600c20602435815417809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe268380a380f35b503461021c57604036600319011261021c576003604061207f612474565b92806060835161208e81612526565b828152826020820152828582015201526004358152600460205220019060018060a01b0316600052602052608060406000206040516120cc81612526565b600182549283835201549064ffffffffff602082018184168152606060408401938560281c600c0b8552019360901c600c0b84526040519485525116602084015251600c0b604083015251600c0b6060820152f35b503461021c578060031936011261021c576020600254604051908152f35b50602036600319011261021c5761038e6004353361316c565b503461021c57602036600319011261021c57612172612889565b807f0000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac566001600160a01b0316803b156121f257818091604460405180958193633d1a69db60e21b835260043560048401528160248401525af180156121e5576121d75780f35b6121e09161255d565b388180f35b50604051903d90823e3d90fd5b50fd5b503461021c57604036600319011261021c576004356001600160401b03811161093457612226903690600401612444565b602435916001600160401b03831161074f573660238401121561074f578260040135926001600160401b03841161075357366024606086028301011161075357638b78c6d8600c52338552600160581b6020600c205416156123fd578383036123ee57845b838110612296578580f35b848110156123da576060810282016060602319823603011261073757604051906122bf826124f5565b60248101358060070b8103610efc5782526044810135908160030b8203610efc57602083019182526064013564ffffffffff81168103610efc576040830190815261230b84888861271a565b3560016242006960e01b03196001600160e01b03198216016123cb574264ffffffffff835116116123bc579060019493929164ffffffffff825116818c52600560205264ffffffffff60408d205460601c1610156123b3578a52600560205260408a209251916001600160401b038454915160401b9264ffffffffff60601b905160601b169316906001600160881b031916179063ffffffff60401b16171790555b0161228b565b505050506123ad565b63b7d0949760e01b8a5260048afd5b631bd2d0af60e01b8a5260048afd5b634e487b7160e01b86526032600452602486fd5b63512509d360e11b8552600485fd5b6382b4290085526004601cfd5b503461021c57602036600319011261021c576004356001600160401b0381116109345761243e61038e913690600401612444565b90612617565b9181601f840112156102b3578235916001600160401b0383116102b3576020808501948460051b0101116102b357565b602435906001600160a01b03821682036102b357565b600435906001600160a01b03821682036102b357565b9060606003198301126102b357600435916024356001600160401b0381116102b357816124cf91600401612444565b92909291604435906001600160401b0382116102b3576124f191600401612444565b9091565b606081019081106001600160401b0382111761251057604052565b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b0382111761251057604052565b61024081019081106001600160401b0382111761251057604052565b90601f801991011681019081106001600160401b0382111761251057604052565b90602083828152019060208160051b85010193836000915b8383106125a65750505050505090565b909192939495601f198282030186528635601e19843603018112156102b357830190602082359201916001600160401b0381116102b35780360383136102b3576020828280600196849695859652848401376000828201840152601f01601f19160101980196019493019190612596565b6000918061262457505050565b60405163d47eed4560e01b81526020600482018190527f0000000000000000000000002880ab155794e7179c9ee2e38200202908c17b436001600160a01b0316929190818061267760248201868961257e565b0381865afa90811561270f5785916126dd575b50823b1561075357916126be93918593604051809681958294631df3cbc560e31b845260206004850152602484019161257e565b03925af180156108f2576126d0575050565b816126da9161255d565b50565b90506020813d602011612707575b816126f86020938361255d565b8101031261075357513861268a565b3d91506126eb565b6040513d87823e3d90fd5b919081101561272a5760051b0190565b634e487b7160e01b600052603260045260246000fd5b3d1561277a573d906001600160401b038211612510576040519161276e601f8201601f19166020018461255d565b82523d6000602084013e565b606090565b8115612789570590565b634e487b7160e01b600052601260045260246000fd5b9081549060901b6cffffffffffffffffffffffffff60901b16906cffffffffffffffffffffffffff60901b1916179055565b356001600160a01b03811681036102b35790565b81835290916001600160fb1b0383116102b35760209260051b809284830137010190565b51906001600160401b03821682036102b357565b91908260809103126102b35760405161283581612526565b809280518060070b81036102b357825261285160208201612809565b602083015260408101518060030b81036102b3576040830152606090810151910152565b805182101561272a5760209160051b010190565b638b78c6d8600c5233600052682000000000000000006020600c205416156128ad57565b6382b429006000526004601cfd5b638b78c6d8600c5233600052650400000000006020600c205416156128ad57565b638b78c6d8195433036128ad57565b600082815260046020526040812090600282019260018060a01b0381168252836020526040822054612c175761292083612c26565b60015434039460018060a01b037f0000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac5616604051630696f5ff60e21b815282600482015261024081602481855afa90811561270f578591612a9f575b50516001600160a01b03909316963388141580612a96575b612a87576040519160c083018381106001600160401b03821117612a735760405288835260208301938452604083019486865260608401878152608085019088825260a08601928352833b15610efc57604051633116e47560e01b815295516001600160a01b03908116600488015296516024870152965160448601529551909416606484015293516084830152915160a4820152918391839160c49183915af180156108f257906001600160801b03939291612a63575b50505460701c16600f0b91600052602052604060002055565b81612a6d9161255d565b38612a4a565b634e487b7160e01b87526041600452602487fd5b6388935db960e01b8552600485fd5b50838110612992565b9050610240813d8211612c0f575b81612abb610240938361255d565b810103126107535760405190612ad082612541565b805182526020810151602083015260408101518015158103610737576040830152612afd60608201612809565b6060830152612b0e60808201612809565b6080830152612b1f60a08201612809565b60a0830152612b3060c08201612809565b60c0830152612b4160e08201612809565b60e0830152612b536101008201612809565b610100830152612b666101208201612809565b610120830152612b796101408201612809565b610140830152612b8c6101608201612809565b610160830152612b9f6101808201612809565b610180830152612bb26101a08201612809565b6101a08301526101c08101516001600160601b0381168103610737576101c08301526101e08101516001600160a01b03811681036107375790610220916101e084015261020081015161020084015201516102208201523861297a565b3d9150612aad565b637863668360e01b8252600482fd5b5464ffffffffff8160201c164210908115612c54575b50612c4357565b634065aaf160e11b60005260046000fd5b64ffffffffff915060481c16421138612c3c565b600094939192906001600160a01b031680612c84575b50505050565b9091929450604051948060005260408414612d30575b60418414612cf3575b946020939495600060605281604052630b135d3f60e11b8252600482015260648560248301968795604087528160448601528385013701915afa9051630b135d3f60e11b14169038808080612c7e565b604083013560001a60205260408381376020600160806000825afa5182183d1517612ca35750505050600191600060605260405238808080612c7e565b60208381013560ff81901c601b01825284356040526001600160ff1b0316606052600160806000825afa5182183d1517612c9a5750505050600191600060605260405238808080612c7e565b6001600160e01b031981166242006960e01b03612eaa576000526005602052604060002060405190612dad826124f5565b548060070b825264ffffffffff60208301918060401c60030b835260601c1680604084015260405163e18910a360e01b815260208160048160018060a01b037f0000000000000000000000002880ab155794e7179c9ee2e38200202908c17b43165afa908115612e9e57600091612e6c575b50420390428211612e565710612e4557612e42915160070b905160030b906131b3565b90565b630cd5fa0760e11b60005260046000fd5b634e487b7160e01b600052601160045260246000fd5b90506020813d602011612e96575b81612e876020938361255d565b810103126102b3575138612e1f565b3d9150612e7a565b6040513d6000823e3d90fd5b6040516331d98b3f60e01b815260048101919091526080816024817f0000000000000000000000002880ab155794e7179c9ee2e38200202908c17b436001600160a01b03165afa8015612e9e57600090612f17575b612e4291506040815160070b91015160030b906131b3565b5060803d608011612f4c575b612f2d818361255d565b8101906080818303126102b357612e4291612f479161281d565b612eff565b503d612f23565b6000808212612f60575090565b600160ff1b8214612f6f570390565b634e487b7160e01b81526011600452602490fd5b69021e19e0c9bab2400000909291920590819060028110156130265761301d576001915b620f4240811215612fc3575050620f4240600254830205020190565b629896801315612fdd57506207a120600254830205020190565b6000906207a12060025485020590629896806003548602055b6298968082121561300957505001020190565b9092611f0782612710920194020590612ff6565b60001991612fa7565b634e487b7160e01b600052602160045260246000fd5b9060018060a01b03166000526003810160205260406000209060405161306181612526565b6001835493848352015464ffffffffff811660208301528060281c600c0b604083015260901c600c0b6060820152821561312657612710926001613118930190806000528160205260406000205460070b151560001461311c576000526020526131016040600020604051906130d6826124f5565b54908160070b90818152604064ffffffffff84821c60030b9485602085015260601c169101526131b3565b6060906040830151600c0b9003910151600c0b0290565b0590565b6131019150612d7c565b505050600090565b60018060a01b031680638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3638b78c6d81955565b638b78c6d8600c526000526020600c2090815490811618809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3565b90601119600382900b12156131e2579063ffffffff612e429260120160030b60000316600a0a9060070b61277f565b63ffffffff9060120116600a0a9060070b029056fec1c8f5dd8ba0a07eb2a8a0b712b36ad1cc969c7f934c8decf86f98390b197ca412cce1add089ae91857f01bb906472895a65b5f522b9d100325a7f551e530f5ca26469706673582212204bd0c5a03a900e82ca61e3b0968be7ffbaee172c0d8d5625b735d0f6e047ac9064736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002880ab155794e7179c9ee2e38200202908c17b430000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac5600000000000000000000000048b62137edfa95a428d35c09e44256a739f6b5570000000000000000000000007a114d38a11b8b4dc2f74555b5b2bb1f5bd742c9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : pyth (address): 0x2880aB155794e7179c9eE2e38200202908C17B43
Arg [1] : reboot (address): 0x3B44BDa7a37ba06CB4272f0775E4CEEa453CAc56
Arg [2] : wape (address): 0x48b62137EdfA95a428D35C09E44256a739F6B557
Arg [3] : signer (address): 0x7A114d38a11B8B4Dc2f74555b5B2BB1f5BD742c9
Arg [4] : _liquidationBounty (uint256): 0
Arg [5] : _baseSlippage (uint256): 25
Arg [6] : _slippageIncrement (uint256): 1
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000002880ab155794e7179c9ee2e38200202908c17b43
Arg [1] : 0000000000000000000000003b44bda7a37ba06cb4272f0775e4ceea453cac56
Arg [2] : 00000000000000000000000048b62137edfa95a428d35c09e44256a739f6b557
Arg [3] : 0000000000000000000000007a114d38a11b8b4dc2f74555b5b2bb1f5bd742c9
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000019
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
971:32794:6:-:0;;;;;;;;;-1:-1:-1;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4811:9;971:32794;4811:9;;;971:32794;25547:25;;;971:32794;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;:::i;:::-;11885:237:3;;;;;971:32794:6;11885:237:3;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;25547:25:6;;971:32794;25547:25;971:32794;;;25547:7;-1:-1:-1;;;;;971:32794:6;25547:25;;;;;;;;;;971:32794;25547:25;971:32794;;;;;;;25547:25;;;;;;;;;;;;971:32794;25547:25;;;:::i;:::-;;;971:32794;;;;25547:25;971:32794;;25547:25;;971:32794;-1:-1:-1;971:32794:6;;25547:25;;;-1:-1:-1;25547:25:6;;;971:32794;;;;;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;4811:9;971:32794;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;23856:37;971:32794;;;;;;;;;;;;;;:::i;:::-;;;;;4811:9;;;;971:32794;;;;;;;;;;;4811:9;;971:32794;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;971:32794:6;;-1:-1:-1;;971:32794:6;;;;;;:::i;:::-;12478:70:3;;:::i;:::-;8479:183;;;;;;8681:8;;;:::i;:::-;971:32794:6;;8479:183:3;;;;971:32794:6;8479:183:3;;971:32794:6;-1:-1:-1;971:32794:6;;-1:-1:-1;;971:32794:6;;;;;;:::i;:::-;12478:70:3;;:::i;:::-;10506:526;;;;;;971:32794:6;10506:526:3;;;;;;;;;;11051:12;10506:526;;11051:12;:::i;10506:526::-;;;;971:32794:6;10506:526:3;;971:32794:6;-1:-1:-1;971:32794:6;;-1:-1:-1;;971:32794:6;;;;9464:12;971:32794;;9452:10;9464:12;:::i;971:32794::-;;;;;;;-1:-1:-1;;971:32794:6;;;;;;:::i;:::-;11745:5:4;;:::i;:::-;-1:-1:-1;;;;;971:32794:6;28084:20;;28080:46;;971:32794;;-1:-1:-1;;;;;;971:32794:6;;;;;;;;;;28180:33;;971:32794;;28180:33;971:32794;;28080:46;-1:-1:-1;;;28113:13:6;;971:32794;28113:13;;971:32794;;;;;;;;:::i;:::-;11745:5:4;;;;;:::i;:::-;971:32794:6;;;;;;;;;;;;;;;22352:15;;22331:36;;22327:67;;971:32794;;-1:-1:-1;;;22419:32:6;;971:32794;;22419:32;;971:32794;;;22419:5;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;:::i;:::-;22419:32;;;;;;;;;;;;;;971:32794;4811:9;;;;;-1:-1:-1;;;;;4811:9:6;;;;971:32794;-1:-1:-1;;;;;4811:9:6;971:32794;;;4811:9;971:32794;;;;;;;;;;;;;;;;22505:152;;4811:9;971:32794;22505:152;;4811:9;;;;;;:::i;:::-;;;;-1:-1:-1;;4811:9:6;971:32794;4811:9;;;971:32794;4811:9;:::i;:::-;;;;;;971:32794;4811:9;;;971:32794;22505:152;;;;;;;;;;;;;971:32794;-1:-1:-1;22673:13:6;22861:22;;22673:13;22711:3;971:32794;;22688:21;;;;;22763:13;971:32794;22763:13;22861:22;22763:13;;;:::i;:::-;;:19;;971:32794;;;;22961:10;971:32794;4811:9;971:32794;22961:10;;971:32794;;;22993:17;;4811:9;971:32794;;;;;;;:::i;:::-;4811:9;;971:32794;22920:93;;4811:9;;;971:32794;22920:93;;971:32794;;;22884:13;;;;:::i;:::-;;971:32794;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;4811:9;971:32794;;;;;-1:-1:-1;;;;;971:32794:6;;;;-1:-1:-1;;;971:32794:6;;;;;;22673:13;;22688:21;;971:32794;;22505:152;;;;;;;;;;;;:::i;:::-;;;4811:9;971:32794;4811:9;;;;;;;;;-1:-1:-1;;;;;4811:9:6;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4811:9:6;;;;971:32794;;4811:9;971:32794;;4811:9;;;;971:32794;;:::i;:::-;4811:9;;;971:32794;4811:9;;;;;;;;;;;;;;;971:32794;4811:9;;;;;;;;22505:152;;;;;;;4811:9;;;;;;;;971:32794;4811:9;971:32794;;;;;;:::i;:::-;4811:9;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;971:32794;4811:9;;;;;;;;;;;;971:32794;;;4811:9;-1:-1:-1;;;971:32794:6;;;;;;;;4811:9;971:32794;;;4811:9;971:32794;;;22505:152;971:32794;;;;;;;;;4811:9;-1:-1:-1;;;971:32794:6;;;;;;;;22419:32;;;;971:32794;22419:32;;971:32794;22419:32;;;;;;971:32794;22419:32;;;:::i;:::-;;;971:32794;;;;;22419:32;;;;;;;-1:-1:-1;22419:32:6;;;971:32794;;;;;;;;;22327:67;-1:-1:-1;;;22376:18:6;;971:32794;22376:18;;971:32794;;;;;;;-1:-1:-1;;971:32794:6;;;;26852:32;971:32794;;;;;:::i;:::-;;;;;;;;;;26852:32;:::i;:::-;971:32794;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;11745:5:4;;:::i;:::-;24827:7:6;-1:-1:-1;;;;;971:32794:6;;24827:47;;;;;971:32794;;;;;;24827:47;;971:32794;;;;;;;24827:47;;971:32794;;;;;;;;;;;;;;;;;;;;;;;;;;;24827:47;;;;;;;;;;;;;;;;;;;;;971:32794;;24827:47;;;;;:::i;:::-;971:32794;;24827:47;971:32794;24827:47;971:32794;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24827:47;971:32794;;;;;;;;;;;;;;;;;;;;;5599:44;971:32794;;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;11745:5:4;;:::i;:::-;971:32794:6;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;7724:800;;971:32794;;;7724:800;;971:32794;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;-1:-1:-1;;;;;971:32794:6;;;7724:800;;971:32794;;;;;7724:800;;971:32794;;;;;7724:800;;971:32794;8107:7;971:32794;7724:800;;971:32794;8107:7;971:32794;7724:800;;971:32794;8107:7;7724:800;;;971:32794;;;;;;;;;;7724:800;;;971:32794;7724:800;;;;971:32794;8334:7;7724:800;;;971:32794;7724:800;;;;971:32794;;;;;;8401:22;971:32794;7724:800;;;971:32794;;;7724:800;;;971:32794;7724:800;;;;971:32794;7724:800;971:32794;;;;;;7694:840;;971:32794;;;7694:840;;971:32794;;7724:800;;971:32794;;;;;;7724:800;;971:32794;;;;;;;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;;;;;;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;;;;;;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;;;;;;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;;;;;;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;;;;;;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;;;;;;-1:-1:-1;;;;;971:32794:6;7724:800;;971:32794;;;;;;-1:-1:-1;;;;;7724:800:6;;;971:32794;;;;;;-1:-1:-1;;;;;7724:800:6;;;971:32794;;;;;;-1:-1:-1;;;;;7724:800:6;;;971:32794;;;;;;-1:-1:-1;;;;;7724:800:6;;;971:32794;;;;;;-1:-1:-1;;;;;7724:800:6;;;971:32794;;;;;;;;;;;7724:800;;;971:32794;;;;;;7724:800;;;971:32794;;;;;7724:800;971:32794;;;;;;;7694:840;971:32794;;;;;;;7694:7;971:32794;7694:840;;;;;;;;;;;971:32794;-1:-1:-1;7694:7:6;-1:-1:-1;;;;;971:32794:6;8545:54;;;;971:32794;;-1:-1:-1;;;8545:54:6;;971:32794;8545:54;;971:32794;;;;;;;;;;;;;;;;;;;;;7694:7;-1:-1:-1;;;;;971:32794:6;8545:54;;;;;;;;971:32794;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;8926:275;;;;971:32794;;;;;;;;8545:54;;;;;;:::i;:::-;971:32794;;8545:54;;;971:32794;;;;8545:54;971:32794;;;;;;;;;7694:840;;;;971:32794;7694:840;;971:32794;7694:840;;;;;;971:32794;7694:840;;;:::i;:::-;;;971:32794;;;;;7694:840;;;;;;;-1:-1:-1;7694:840:6;;;971:32794;;;;;;;;;;-1:-1:-1;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;;;;;;5735:66;971:32794;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11523:61:3;971:32794:6;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;26223:37;971:32794;;;:::i;:::-;;;;;;;;;;26223:37;:43;971:32794;;;;;;-1:-1:-1;971:32794:6;;;;;-1:-1:-1;971:32794:6;;;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;11745:5:4;;:::i;:::-;29079:11:6;29070:20;;29066:59;;971:32794;4858:6;29178:32;4858:6;971:32794;4858:6;971:32794;;;;;29178:32;971:32794;;29066:59;-1:-1:-1;;;29099:26:6;;971:32794;29099:26;;971:32794;;;;;;;-1:-1:-1;;971:32794:6;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12478:70:3;;:::i;:::-;6813:405;4606:437:4;6813:405:3;;;;;;;4606:437:4;6813:405:3;;971:32794:6;;;;;;;;;;;;;;;;5516:32;971:32794;;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;;;;;;;5807:55;971:32794;;;;;;;;;;;;;;;;;;;;;;;9831:339:3;;;;;;;;;;;;;;;;971:32794:6;;;;;;;19627:12;971:32794;;;:::i;:::-;;;;;;;;;;;;;;;;19585:10;;;;:::i;:::-;19627:12;:::i;:::-;19651:31;19698:13;;19838:22;;;;19693:695;19713:16;;;;;;20402:27;;;20398:256;;971:32794;;;20398:256;20463:10;;;;;;:51;;;;:::i;:::-;;20532:8;20528:37;;971:32794;;;;;20585:58;971:32794;20463:10;20585:58;;971:32794;;20528:37;-1:-1:-1;;;20549:16:6;;971:32794;25361:16;20549;19731:3;19797:8;;;;;;19770:36;19797:8;;;;;;:::i;:::-;;:::i;:::-;19770:36;;:::i;:::-;971:32794;19861:8;;;;;;:::i;:::-;-1:-1:-1;;;;;971:32794:6;-1:-1:-1;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;19951:8;971:32794;19951:8;;971:32794;19951:8;;;;;;:::i;:::-;-1:-1:-1;971:32794:6;;;;;;;;;;;;;4858:6;20012:8;;971:32794;20012:8;;;;;;:::i;:::-;-1:-1:-1;971:32794:6;;;;;;;;;19989:22;;;971:32794;;;;;;;;;;;;;;;;;20182:8;;;;;;:::i;:::-;971:32794;20157:34;;;;;19821:557;971:32794;19698:13;;;;;;;19821:557;20308:8;971:32794;20308:8;;;20275:88;971:32794;20308:8;;20341;;20308;;;;;;;;:::i;:::-;20341;;;:::i;:::-;-1:-1:-1;971:32794:6;;;;;;;;;;;;;;;;;;;;;4858:6;;971:32794;;;;;;;20275:88;;19821:557;;971:32794;;;;;;;-1:-1:-1;;971:32794:6;;;;;;:::i;:::-;10695:219:4;;;;;971:32794:6;;;10695:219:4;;;;11083:21;:26;;971:32794:6;;;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;11745:5:4;;:::i;:::-;5325:2:6;28746:47;;28742:77;;971:32794;4858:6;28893:36;4858:6;28830:47;4858:6;971:32794;;;;;28893:36;971:32794;;28742:77;-1:-1:-1;;;28802:17:6;;971:32794;28437:17;28802;971:32794;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;-1:-1:-1;971:32794:6;;-1:-1:-1;;971:32794:6;;;;4408:5:4;971:32794:6;;:::i;:::-;12478:70:3;;:::i;:::-;971:32794:6;;4408:5:4;;:::i;971:32794:6:-;;;;;;;-1:-1:-1;;971:32794:6;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;10976:17;10972:45;;971:32794;;11031:15;:30;11027:63;;5388:10;971:32794;;;11031:15;11104:46;11100:77;;971:32794;;;;;;;;;;11283:10;;;:::i;:::-;971:32794;;;;;;;-1:-1:-1;971:32794:6;11336:22;;;971:32794;;;-1:-1:-1;971:32794:6;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11377:21;11413:27;;11409:586;;971:32794;;;;;;;12046:10;971:32794;;;;;;;;12042:48;;971:32794;;;;12046:10;971:32794;;;;;;;-1:-1:-1;;971:32794:6;;;;;;;12157:16;-1:-1:-1;971:32794:6;;;12157:51;;;971:32794;;-1:-1:-1;;;;;971:32794:6;;;;;;12299:76;;971:32794;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12299:76;;;;;;:::i;:::-;971:32794;;;12299:76;;;12289:87;30476:265:5;;;;;;971:32794:6;30476:265:5;12401:10:6;-1:-1:-1;;;;;971:32794:6;;12401:20;971:32794;;;;12531:84;;971:32794;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;12531:84;:::i;:::-;12530:85;12526:149;;12397:714;13142:12;12397:714;13142:12;:::i;:::-;13190:29;971:32794;;13190:29;:::i;:::-;13260:64;;;;33228:285;33469:27;33228:285;33440:25;;;971:32794;;;4858:6;;33469:27;;971:32794;;;4858:6;33228:285;;13260:64;13355:22;971:32794;13355:22;;:30;971:32794;;;;;;;-1:-1:-1;971:32794:6;;;;;-1:-1:-1;971:32794:6;;;13439:34;971:32794;;;;;;13439:34;:::i;:::-;13484:25;4858:6;971:32794;;;;;;;4858:6;;;;;;;;;;;;14021:158;;;;;;4858:6;14021:158;4858:6;14252:18;971:32794;;14252:18;:::i;:::-;4858:6;;;;;;;;-1:-1:-1;;;4858:6:6;;;;;;;;;;;;;;;;14445:36;;;14441:261;;-1:-1:-1;14739:4359:6;;;-1:-1:-1;14771:58:6;;;;;15105:30;;;4858:6;15105:30;;;;;971:32794;;;;;;;-1:-1:-1;971:32794:6;;;;4858:6;971:32794;-1:-1:-1;971:32794:6;4858:6;;971:32794;4858:6;;971:32794;;;;;;:::i;:::-;;;;;15200:41;;11031:15;971:32794;11031:15;971:32794;;;;15200:41;971:32794;;15200:41;;971:32794;;;;11336:22;971:32794;15200:41;;971:32794;;;;;;;;;;;-1:-1:-1;971:32794:6;11336:22;971:32794;;;-1:-1:-1;971:32794:6;;;4858:6;;;971:32794;;;;;4858:6;;;;;;;971:32794;4858:6;;;971:32794;4858:6;-1:-1:-1;;;;;;;4858:6:6;;-1:-1:-1;;;;;;;4858:6:6;;;;;971:32794;;;4858:6;;:::i;:::-;971:32794;;;;;;;4858:6;;;971:32794;;;;;;4858:6;;;971:32794;-1:-1:-1;;;;;971:32794:6;;;;;;;;;-1:-1:-1;;;;;;;;;;;15265:79:6;4858:6;;15265:79;971:32794;;;;;;;-1:-1:-1;971:32794:6;;;;-1:-1:-1;971:32794:6;;;;;;;;;4858:6;971:32794;4858:6;;971:32794;4858:6;971:32794;4858:6;;971:32794;;;;;;;;-1:-1:-1;;;;;;;;;;;971:32794:6;;;15367:79;;971:32794;;14767:3237;15471:57;;;;;;;;;;;;971:32794;15776:80;11336:22;971:32794;;;4858:6;971:32794;;;;;;;;;;;4858:6;971:32794;;4858:6;;15776:80;:::i;:::-;4858:6;971:32794;;;;;;;;-1:-1:-1;971:32794:6;;;;;-1:-1:-1;971:32794:6;4858:6;971:32794;;;;;;;-1:-1:-1;971:32794:6;11336:22;;;971:32794;;16046:56;971:32794;;;-1:-1:-1;971:32794:6;16046:43;:56;:::i;:::-;-1:-1:-1;;;;;971:32794:6;;-1:-1:-1;971:32794:6;;;11336:22;;;;971:32794;;;;;;;;;;16120:44;4858:6;;971:32794;11031:15;971:32794;-1:-1:-1;;4858:6:6;;;;;;971:32794;;;;;;4858:6;;;971:32794;;;;;;4858:6;;;971:32794;;;;;;;;-1:-1:-1;;;;;;;;;;;16214:79:6;4858:6;;16214:79;971:32794;;;;;;;-1:-1:-1;971:32794:6;;;;;-1:-1:-1;971:32794:6;;;;;;;;;;;;;4858:6;;971:32794;;;;4858:6;;971:32794;;;;;;;;-1:-1:-1;;;;;;;;;;;971:32794:6;;;16316:152;;971:32794;;15467:2537;971:32794;;;;;;;;;;;;;;;;;;;;4858:6;971:32794;;16997:30;971:32794;;;;;;;-1:-1:-1;971:32794:6;;;;4858:6;971:32794;-1:-1:-1;971:32794:6;4858:6;;971:32794;4858:6;;971:32794;;;;4858:6;;971:32794;;;4858:6;;;;;971:32794;;;;;;;;;;4858:6;;;971:32794;;;;;4858:6;;;971:32794;4858:6;;17490:93;;4858:6;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;-1:-1:-1;;;;;;;;;;;17064:138:6;4858:6;;17064:138;17530:24;4858:6;;;17530:24;:::i;:::-;17490:93;:::i;:::-;971:32794;;;;;;;:::i;:::-;;;;;;17654:72;;11031:15;971:32794;11031:15;971:32794;;;;17654:72;971:32794;;17654:72;;971:32794;;;;;;11336:22;971:32794;17654:72;;971:32794;;;;;;;;;;;-1:-1:-1;971:32794:6;11336:22;971:32794;;;-1:-1:-1;971:32794:6;;;4858:6;;;971:32794;;;;;4858:6;;;;;;;971:32794;4858:6;;;971:32794;4858:6;-1:-1:-1;;;;;;;4858:6:6;;-1:-1:-1;;;;;;;4858:6:6;;;;;971:32794;;;4858:6;;:::i;:::-;971:32794;;;;;;;;;4858:6;;;971:32794;;;;;4858:6;;;971:32794;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;-1:-1:-1;;;;;;;;;;;17064:138:6;4858:6;;17750:76;-1:-1:-1;;;;;971:32794:6;;;;-1:-1:-1;971:32794:6;;;;;;;;;;;;;;;;;;;;;;4858:6;;;971:32794;;;;;;4858:6;;;971:32794;;;;;;;;-1:-1:-1;;;;;;;;;;;17849:140:6;4858:6;;17849:140;971:32794;;4858:6;-1:-1:-1;;;971:32794:6;;;;;;;;14739:4359;4858:6;18142:84;;18513:229;18142:84;;;;;;;;;;;;;:::i;:::-;971:32794;;;;;;;;;;;;;;4858:6;971:32794;;;;;;;4858:6;;;;;;;18513:229;:::i;:::-;971:32794;;;;;;;;;;;:::i;:::-;;;;;11336:22;971:32794;18804:68;;11031:15;;;971:32794;;;;18804:68;;971:32794;;;;;;;18804:68;;971:32794;;;;;;;;;-1:-1:-1;971:32794:6;11336:22;971:32794;;;-1:-1:-1;971:32794:6;;;4858:6;;;971:32794;;;;;4858:6;;;;;;;971:32794;4858:6;;;971:32794;4858:6;-1:-1:-1;;;;;;;4858:6:6;;-1:-1:-1;;;;;;;4858:6:6;;;;;971:32794;;;4858:6;;:::i;:::-;971:32794;;;;;;;4858:6;;;971:32794;;;;;;4858:6;;;971:32794;-1:-1:-1;;;;;971:32794:6;;;;;;;;;-1:-1:-1;;;;;;;;;;;18892:78:6;4858:6;;18892:78;-1:-1:-1;;;;;971:32794:6;;;;-1:-1:-1;971:32794:6;;;;;;;;;;;;;;;;;;;;;;4858:6;;;971:32794;;;;;;4858:6;;;971:32794;;;;;;;;-1:-1:-1;;;;;;;;;;;18989:98:6;4858:6;;18989:98;971:32794;;14441:261;14567:22;;;;971:32794;14567:22;;14563:50;;14441:261;-1:-1:-1;;;14635:56:6;;971:32794;;;;14635:56;14563:50;14591:22;;14563:50;;4858:6;-1:-1:-1;;;971:32794:6;;;;;;;;14021:158;4858:6;14021:158;;12526:149;-1:-1:-1;;;12642:18:6;;971:32794;12936:18;12642;12397:714;971:32794;;12401:10;-1:-1:-1;;;;;971:32794:6;;;12695:32;971:32794;;;12837:72;971:32794;;;;;;;;12837:72;;;:::i;12691:420::-;-1:-1:-1;;;13085:15:6;;971:32794;13085:15;;971:32794;-1:-1:-1;;;971:32794:6;;;;;;;;12157:51;971:32794;12157:51;;;12042:48;-1:-1:-1;;;12072:18:6;;971:32794;12072:18;;11409:586;971:32794;;11460:28;971:32794;;-1:-1:-1;;;11515:17:6;;971:32794;11515:17;;11456:529;971:32794;;;11726:16;971:32794;;;;;;11688:32;11687:56;11553:432;;11456:529;;11409:586;;;;11553:432;971:32794;;;;;;;;;;;;;;;;;11031:15;971:32794;;11780:80;11776:161;;971:32794;11553:432;;;;11776:161;-1:-1:-1;;;11891:27:6;;971:32794;11891:27;;11100:77;-1:-1:-1;;;11159:18:6;;971:32794;11159:18;;11027:63;-1:-1:-1;;;11070:20:6;;971:32794;11070:20;;10972:45;-1:-1:-1;;;11002:15:6;;971:32794;11002:15;;971:32794;;;;;;;;;;;;;12478:70:3;;:::i;:::-;25304:21:6;;;;;25281:10;:49;;;;:::i;:::-;;25344:8;25340:37;;971:32794;;25340:37;-1:-1:-1;;;25361:16:6;;971:32794;;25361:16;971:32794;;;;;;;-1:-1:-1;;971:32794:6;;;;;;11745:5:4;;:::i;:::-;5250:3:6;28386:42;;28382:72;;971:32794;4858:6;28523:40;4858:6;28465:42;4858:6;971:32794;;;;;28523:40;971:32794;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;:::i;:::-;10695:219:4;;;;;971:32794:6;10695:219:4;;;;971:32794:6;;;;;;;-1:-1:-1;971:32794:6;;-1:-1:-1;;971:32794:6;;;;9762:12;971:32794;;:::i;:::-;;;9762:12;;:::i;971:32794::-;;;;;;;;;;9239:383:3;;;;;;7972:9;9132:15;971:32794:6;9239:383:3;;;;;;;;;971:32794:6;;;;;;;;;;;;;;;;;;5388:10;971:32794;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;;;:::i;:::-;;;10695:219:4;;;;;;;;;;11280:21;:30;971:32794:6;;;;;;;-1:-1:-1;971:32794:6;;-1:-1:-1;;971:32794:6;;;;;;:::i;:::-;12478:70:3;;:::i;:::-;3082:831:4;;;;;;;;971:32794:6;;3082:831:4;;;;;;;;;;;;;;971:32794:6;;;;;;;;;-1:-1:-1;;971:32794:6;;;;25877:37;971:32794;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;25877:37;:43;971:32794;;;;;;-1:-1:-1;971:32794:6;;;;;-1:-1:-1;971:32794:6;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5554:39;971:32794;;;;;;;;-1:-1:-1;971:32794:6;;-1:-1:-1;;971:32794:6;;;;4408:5:4;971:32794:6;;10211:10:4;4408:5;:::i;971:32794:6:-;;;;;;;-1:-1:-1;;971:32794:6;;;;11745:5:4;;:::i;:::-;971:32794:6;24976:7;-1:-1:-1;;;;;971:32794:6;24976:32;;;;;971:32794;;;24976:32;971:32794;;;;;;;;;24976:32;;971:32794;;;24976:32;;971:32794;;;;;;24976:32;;;;;;;;971:32794;;24976:32;;;;:::i;:::-;;;971:32794;;24976:32;971:32794;;;;;;;;;;;24976:32;971:32794;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;4606:437:4;;;;;;971:32794:6;17016:7:4;;971:32794:6;4606:437:4;;;;;;;21302:29:6;;;21298:63;;21377:13;21392:16;;;;;;971:32794;;;21410:3;971:32794;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21496:8;;;;;:::i;:::-;971:32794;-1:-1:-1;;;;;;;;;;;;971:32794:6;;33611:45;21519:63;;21664:15;971:32794;;;;21644:35;21640:66;;971:32794;;;;;;;;;;;;;21745:14;971:32794;;;;;;;;;;-1:-1:-1;21724:53:6;21720:67;;971:32794;;21745:14;971:32794;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;-1:-1:-1;;;971:32794:6;;;;;21377:13;971:32794;21377:13;;21720:67;21779:8;;;;;;21640:66;-1:-1:-1;;;21688:18:6;;971:32794;21688:18;;21519:63;-1:-1:-1;;;21561:21:6;;971:32794;21561:21;;971:32794;-1:-1:-1;;;971:32794:6;;;;;;;;21298:63;-1:-1:-1;;;21340:21:6;;971:32794;21340:21;;4606:437:4;;;;971:32794:6;4606:437:4;;971:32794:6;;;;;;;-1:-1:-1;;971:32794:6;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;971:32794:6;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;971:32794:6;;;;;;:::o;:::-;;;-1:-1:-1;;971:32794:6;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;:::o;:::-;;;;-1:-1:-1;971:32794:6;;;;;-1:-1:-1;971:32794:6;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;:::o;:::-;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;971:32794:6;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;971:32794:6;;;;;;;;-1:-1:-1;;971:32794:6;;;;;;;;;;;;;;20773:247;20877:1;20855:23;;20851:163;;20773:247;;;:::o;20851:163::-;971:32794;;-1:-1:-1;;;20908:32:6;;971:32794;20908:32;;;971:32794;;;20908:5;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;:::i;:::-;20908:32;;;;;;;;;;;;;;20851:163;20955:48;;;;;;971:32794;;;;;;;;;;;;;;;;;20955:48;;971:32794;20908:32;20955:48;;971:32794;;;;;;:::i;:::-;20955:48;;;;;;;;;;20773:247;;:::o;20955:48::-;;;;;:::i;:::-;20773:247;:::o;20908:32::-;;;971:32794;20908:32;;971:32794;20908:32;;;;;;971:32794;20908:32;;;:::i;:::-;;;971:32794;;;;;20908:32;;;;;;-1:-1:-1;20908:32:6;;;971:32794;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;-1:-1:-1;;971:32794:6;;;;;:::i;:::-;;;;-1:-1:-1;971:32794:6;;;;:::o;:::-;;;:::o;4858:6::-;;;;;;;:::o;:::-;971:32794;;;4858:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;971:32794::-;;-1:-1:-1;;;;;971:32794:6;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;:::o;4811:9::-;;971:32794;-1:-1:-1;;;;;971:32794:6;;;;;;4811:9::o;:::-;;;;;;;;;;971:32794;;;;;:::i;:::-;4811:9;;;;971:32794;;;;;;;4811:9;;;;;;;:::i;:::-;;;;;971:32794;4811:9;;;971:32794;;;;;;;;4811:9;;;;;;;971:32794;4811:9;;;:::o;:::-;971:32794;;4811:9;;;;;;;;;;;;:::o;4495:554:4:-;4606:437;;;;;;16066:7;4606:437;;;;;;;;4495:554::o;4606:437::-;;;;;;;4495:554;4606:437;;;;;;14716:7;4606:437;;;;;;;;4495:554::o;7292:355:3:-;-1:-1:-1;;7390:251:3;;;;;7292:355::o;27014:993:6:-;-1:-1:-1;971:32794:6;;;27133:11;971:32794;;;;;27173:22;;;;:28;971:32794;;;;;;;;;;;;;;;;27169:87;;27287:10;;;:::i;:::-;27452:17;971:32794;27440:9;4858:6;971:32794;;;;;;27508:7;971:32794;;;;;;27508:35;;;27133:11;27508:35;;971:32794;27508:35;;;;;;;;;;;;;;;;27014:993;-1:-1:-1;4811:9:6;-1:-1:-1;;;;;971:32794:6;;;;27691:10;:18;;;;:48;;27014:993;27687:83;;971:32794;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;27832:77;;971:32794;;;;27832:77;;971:32794;;;;27832:77;;;971:32794;;;27832:77;;;971:32794;;;;27832:77;;;971:32794;;;27781:138;;;;;971:32794;;-1:-1:-1;;;27781:138:6;;971:32794;;-1:-1:-1;;;;;971:32794:6;;;27133:11;27781:138;;971:32794;;;27508:35;971:32794;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27781:138;;971:32794;;27781:138;;;;;;;-1:-1:-1;;;;;27781:138:6;;;;;27014:993;971:32794;;;;;;;;27930:28;-1:-1:-1;971:32794:6;;;;-1:-1:-1;971:32794:6;4858:6;27014:993::o;27781:138::-;;;;;:::i;:::-;;;;971:32794;-1:-1:-1;;;971:32794:6;;;27133:11;971:32794;27508:35;971:32794;;27687:83;-1:-1:-1;;;27748:22:6;;27133:11;27748:22;;27691:48;27713:26;;;;27691:48;;27508:35;;;;;;;;;;;;;;;;;:::i;:::-;;;971:32794;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;4811:9;971:32794;;;4811:9;:::i;:::-;971:32794;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;-1:-1:-1;;;;;971:32794:6;;;;;;;;;;;;;;;;;;;;;;4811:9;971:32794;;;;27508:35;;;;;;-1:-1:-1;27508:35:6;;27169:87;-1:-1:-1;;;27229:16:6;;27133:11;27229:16;;30726:225;971:32794;;;;;;30822:15;:38;:78;;;;;30726:225;30818:127;;;30726:225::o;30818:127::-;30923:11;;;-1:-1:-1;30923:11:6;;-1:-1:-1;30923:11:6;30822:78;971:32794;;;;;;30822:15;30864:36;30822:78;;;6365:4213:5;971:32794:6;;6365:4213:5;;;;-1:-1:-1;;;;;6576:3996:5;;;;;6365:4213;;;;:::o;6576:3996::-;;;;;;;;;;971:32794:6;6576:3996:5;;;;;;;;;;;;;;;;;;971:32794:6;6576:3996:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6576:3996:5;;;;;;;;;;;;;;971:32794:6;6576:3996:5;;;;;;;;;;971:32794:6;6576:3996:5;;;;;;;;;;;;;;;;;971:32794:6;6576:3996:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;6576:3996:5;;;971:32794:6;6576:3996:5;971:32794:6;;6576:3996:5;;;;;;;;;;;;;;;;971:32794:6;6576:3996:5;;;;;;;;;;29460:562:6;-1:-1:-1;;;;;;971:32794:6;;-1:-1:-1;;;29552:45:6;971:32794;;;;29642:14;971:32794;;;;;;;;;;;:::i;:::-;;;;;4811:9;;971:32794;;;;;;;;;;4811:9;;;971:32794;;;;;;;;;;;;29719:26;;971:32794;;29719:26;971:32794;;;;;;29719:5;971:32794;29719:26;;;;;;;971:32794;29719:26;;;29548:468;29701:15;;971:32794;29701:15;;971:32794;;;;29681:64;29677:122;;29820:40;971:32794;;;;;;;;29820:40;;:::i;:::-;29813:47;:::o;29677:122::-;29772:12;;;971:32794;29772:12;29719:26;971:32794;29772:12;971:32794;;;;;;;29719:26;971:32794;;;;29719:26;;;971:32794;29719:26;;971:32794;29719:26;;;;;;971:32794;29719:26;;;:::i;:::-;;;971:32794;;;;;29719:26;;;;;;-1:-1:-1;29719:26:6;;;971:32794;;;;;;;;;29548:468;971:32794;;-1:-1:-1;;;29924:20:6;;;;;971:32794;;;;29924:20;971:32794;29924:20;971:32794;29924:5;-1:-1:-1;;;;;971:32794:6;29924:20;;;;;;971:32794;29924:20;;;29548:468;29965:40;971:32794;;;;;;;29994:10;;971:32794;;;29965:40;;:::i;29924:20::-;;;;;;;;;;;;;:::i;:::-;;;971:32794;29924:20;971:32794;;;;;;29965:40;971:32794;;;;:::i;:::-;29924:20;;;;;;;33669:94;33746:1;33741:6;;;33746:1;;33741:15;33669:94;:::o;33741:15::-;-1:-1:-1;;;971:32794:6;;;;;33669:94;:::o;971:32794::-;-1:-1:-1;;;971:32794:6;;;;;;;;30979:1889;4858:6;30979:1889;;;;4858:6;31234:49;;971:32794;;;;;;;31330:27;;971:32794;31330:52;;4923:9;31397:43;;4923:9;;;971:32794;;4923:9;971:32794;;4858:6;;;;971:32794;31393:1469;30979:1889::o;31393:1469::-;4992:10;-1:-1:-1;4992:10:6;;;971:32794;31935:7;971:32794;;4858:6;;;;971:32794;31723:1139;30979:1889::o;31723:1139::-;971:32794;;32302:7;971:32794;;4858:6;;;971:32794;4992:10;32370:30;971:32794;4858:6;;;32439:45;4992:10;32439:45;;;;;4858:6;;;;;31723:1139;30979:1889::o;32432:247::-;4858:6;;32603:4;4858:6;;;;;;;32432:247;;;31330:52;-1:-1:-1;;31379:2:6;31330:52;;971:32794;;;;;;;;;;;;30028:692;;971:32794;;;;;;-1:-1:-1;971:32794:6;30174:22;;;971:32794;;;-1:-1:-1;971:32794:6;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30260:11;;30256:50;;4858:6;30316:22;971:32794;30642:63;30316:22;30352;971:32794;;-1:-1:-1;971:32794:6;;;;;-1:-1:-1;971:32794:6;;;;30352:39;;30348:277;971:32794;;;-1:-1:-1;971:32794:6;;;30496:40;971:32794;-1:-1:-1;971:32794:6;;;;;;;:::i;:::-;;;;;;4811:9;;;;971:32794;;;;;30174:22;971:32794;;;;;;4811:9;971:32794;;;;;;30496:40;:::i;:::-;33469:27;33228:285;33440:25;;;971:32794;;;4858:6;;33469:27;;971:32794;;;4858:6;33228:285;;30642:63;971:32794;30028:692;:::o;30348:277::-;30585:29;;;;:::i;30256:50::-;30287:8;;;-1:-1:-1;30287:8:6;:::o;6145:1089:3:-;971:32794:6;;;;;6813:405:3;;4606:437:4;6813:405:3;;;-1:-1:-1;6813:405:3;;-1:-1:-1;;6813:405:3;6145:1089::o;2952:967:4:-;3082:831;;;971:32794:6;3082:831:4;;;;;;;;;;;;;;;;;;;971:32794:6;3082:831:4;;2952:967::o;32874:348:6:-;;-1:-1:-1;;971:32794:6;;;;32993:10;33000:3;;;971:32794;;33030:59;971:32794;33076:2;971:32794;;;;;;33053:2;971:32794;;;;33030:59;:::i;32989:217::-;971:32794;;33179:2;971:32794;;33158:2;971:32794;;;;4858:6;33128:63;:::o
Swarm Source
ipfs://4bd0c5a03a900e82ca61e3b0968be7ffbaee172c0d8d5625b735d0f6e047ac90
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
APE | Ape (APE) | 100.00% | $1.55 | 0.000000001 | <$0.000001 |
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.