Source Code
Overview
HYPE Balance
HYPE Value
Less Than $0.01 (@ $23.79/HYPE)Latest 25 from a total of 4,254 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Resolve Markets | 20028151 | 63 days ago | IN | 0 HYPE | 0.0001271 | ||||
| Resolve Markets | 20027379 | 63 days ago | IN | 0 HYPE | 0.00013614 | ||||
| Resolve Markets | 20026594 | 63 days ago | IN | 0 HYPE | 0.00011742 | ||||
| Resolve Markets | 20025967 | 63 days ago | IN | 0 HYPE | 0.00004714 | ||||
| Resolve Markets | 20025348 | 63 days ago | IN | 0 HYPE | 0.00012056 | ||||
| Resolve Markets | 20024401 | 63 days ago | IN | 0 HYPE | 0.00012386 | ||||
| Resolve Markets | 20023746 | 63 days ago | IN | 0 HYPE | 0.00012901 | ||||
| Resolve Markets | 20023083 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20022471 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20021859 | 63 days ago | IN | 0 HYPE | 0.0001238 | ||||
| Resolve Markets | 20021237 | 63 days ago | IN | 0 HYPE | 0.00007854 | ||||
| Resolve Markets | 20020618 | 63 days ago | IN | 0 HYPE | 0.00012862 | ||||
| Resolve Markets | 20020006 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20019394 | 63 days ago | IN | 0 HYPE | 0.00009294 | ||||
| Resolve Markets | 20018684 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20018071 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20017458 | 63 days ago | IN | 0 HYPE | 0.00012785 | ||||
| Resolve Markets | 20016831 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20016219 | 63 days ago | IN | 0 HYPE | 0.0001377 | ||||
| Resolve Markets | 20015341 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20014729 | 63 days ago | IN | 0 HYPE | 0.00012918 | ||||
| Resolve Markets | 20013907 | 63 days ago | IN | 0 HYPE | 0.00012174 | ||||
| Resolve Markets | 20013069 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20012456 | 63 days ago | IN | 0 HYPE | 0.00004603 | ||||
| Resolve Markets | 20011843 | 63 days ago | IN | 0 HYPE | 0.00004603 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MarketMakerAMM
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
No with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import "solady/src/utils/g/EnumerableSetLib.sol";
contract MarketMakerAMM {
using EnumerableSetLib for Uint256Set;
event MarketEnter(uint256 indexed MarketId, uint256 indexed RoundId, address indexed User, uint256 AmountIn, uint256 Side, uint256 AmountOut); //0xafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd9
event MarketExit(uint256 indexed MarketId, uint256 indexed RoundId, address indexed User, uint256 AmountInA, uint256 AmountInB, uint256 AmountOut); //0x4c686a53bc9329e91f0d0d94d821505fd2c0aef3c09a94ea360d98c0dfb9dee4
event MarketRedeem(uint256 indexed MarketId, uint256 indexed RoundId, address indexed User, uint256 Result, uint256 AmountOut); //0x3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac4839
event RoundResolvedBy(uint256 indexed RoundId, address indexed Resolver, uint256 Fees); //0xa4151f6c29291b1556b1872bc36e5304d55092b1703f6226eefdb53250765c71
error NotAuthorised();
error RoundExpired();
error AlreadyClaimed();
error RoundResolved();
error InvalidRound();
error InvalidTimestamp();
error InvalidInput();
error SlippageReached();
error RoundNotYetInitialised();
error InvalidOutput();
error OracleError();
error InvalidReserves();
address internal admin; // slot: 0
uint256 public fees; //slot1
uint256 public universalRound; // slot: 2
uint256 public roundStart; // slot: 3
mapping(uint256 marketId => mapping(uint256 round => uint256 yesReserves)) internal marketToRoundToYesReserves; // slot: 4
mapping(uint256 marketId => mapping(uint256 round => uint256 noReserves)) internal marketToRoundToNoReserves; // slot: 5
mapping(uint256 marketId => mapping(uint256 round => uint256 treasury)) internal marketToRoundToTreasury; // slot: 6
mapping(address user => mapping(uint256 marketId => mapping(uint256 round => uint256 yesReserves))) internal userToMarketToRoundToYesReserves; // slot: 7
mapping(address user => mapping(uint256 marketId => mapping(uint256 round => uint256 noReserves))) internal userToMarketToRoundToNoReserves; // slot: 8
mapping(uint256 marketId => mapping(uint256 round => uint256 price)) internal marketToRoundToPrice; // slot: 9
mapping(uint256 marketId => mapping(uint256 round => uint256 result)) internal marketToRoundToResult; // slot: 10
mapping(address user => mapping(uint256 marketId => uint256[] roundIds)) internal userToActiveRoundsPerMarket; // slot: 11
mapping(address user => mapping(uint256 marketId => mapping(uint256 roundId => uint256 registered))) internal userToRegisteredRound; // slot: 12
mapping(address user => mapping(uint256 marketId => mapping(uint256 roundId => uint256 redeemed))) internal userToRedeemedMarketRound; // slot: 13
mapping(uint256 marketId => mapping(uint256 round => uint256 outstandingYesShares)) internal marketToRoundToOutYesShares; // slot: 14
mapping(uint256 marketId => mapping(uint256 round => uint256 outstandingNoShares)) internal marketToRoundToOutNoShares; // slot: 15
mapping(uint256 roundId => uint256 resolverFees) internal roundIdToResolverFees; // slot: 16
mapping(uint256 marketId => uint256 delistRound) public marketToDelistingRound; // slot: 17
Uint256Set private availableMarkets;
Uint256Set private allMarkets;// slot: 19
struct MarketData {
uint256 marketId;
uint256 roundId;
uint256 roundStart;
uint256 marketTreasury;
uint256 yesReserves;
uint256 noReserves;
uint256 outYesReserves;
uint256 outNoReserves;
uint256 lastPrice;
uint256 currentPrice;
uint256 result;
}
struct MarketDataWithHistory {
uint256 marketId;
uint256 roundId;
uint256 roundStart;
uint256 marketTreasury;
uint256 yesReserves;
uint256 noReserves;
uint256 outYesReserves;
uint256 outNoReserves;
uint256 lastPrice;
uint256 currentPrice;
uint256 result;
uint256 delistingRound;
uint256[] history;
}
struct MarketHistory {
uint256 marketId;
uint256 roundId;
uint256 outYesReserves;
uint256 outNoReserves;
uint256 openPrice;
uint256 closePrice;
uint256 result;
}
struct UserData {
uint256 marketId;
uint256 roundId;
uint256 result;
uint256 outYesReserves;
uint256 outNoReserves;
uint256 userYesReserves;
uint256 userNoReserves;
uint256 treasury;
uint256 userRedeemed;
}
struct UserToRoundsPerMarket {
uint256 marketId;
uint256[] roundIds;
}
/**
* @notice Initializes the MarketMakerAMM contract with initial markets
* @dev Sets up initial reserves for rounds 1 and 2, fetches initial oracle prices
* @param initMarketIds Array of market IDs to initialize (e.g., [0, 1, 2] for BTC, HYPE, SOL)
*
* Initializes:
* - Round 1 as the current round
* - 425 HYPE initial reserves for YES and NO in rounds 1 and 2
* - Fetches and stores initial oracle price for round 0
* - Sets deployer as admin
*/
constructor(uint256[] memory initMarketIds, address _admin) {
uint len = initMarketIds.length;
for(uint i=0; i<len; i++) {
uint256 marketId = initMarketIds[i];
marketToRoundToPrice[marketId][0] = _oraclePx(marketId);
availableMarkets.add(marketId);
allMarkets.add(marketId);
marketToRoundToYesReserves[marketId][1] = 425 * 10**18;
marketToRoundToNoReserves[marketId][1] = 425 * 10**18;
marketToRoundToYesReserves[marketId][2] = 425 * 10**18;
marketToRoundToNoReserves[marketId][2] = 425 * 10**18;
}
universalRound++;
roundStart = block.timestamp;
admin = _admin;
}
/**
* @notice Registers a new market to the AMM
* @dev Only callable by admin. Market ID must not already exist
* @param index The market ID to register
*
* @custom:reverts NotAuthorised if caller is not admin
* @custom:reverts InvalidInput if market ID already exists
*/
function registerMarket(uint256 index) external {
if(msg.sender != admin) {
revert NotAuthorised();
}
marketToDelistingRound[index] = 0; //Clear delisting round on potential relisting
if(!availableMarkets.add(index)) revert InvalidInput();
allMarkets.add(index);
uint256 uRound = universalRound + 1;
marketToRoundToYesReserves[index][uRound] = 425 * 10**18;
marketToRoundToNoReserves[index][uRound] = 425 * 10**18;
}
/**
* @notice Puts the market Id in schedule for removal, after 5 rounds admin can remove the market Id.
* @dev Only callable by admin. Market ID must already exist
* @param index The market ID to remove
*
* @custom:reverts NotAuthorised if caller is not admin
* @custom:reverts InvalidInput if market ID doesn't exist
*/
function putMarketOnDelist(uint256 index) external {
if(msg.sender != admin) {
revert NotAuthorised();
}
if(!availableMarkets.contains(index)) revert InvalidInput();
marketToDelistingRound[index] = universalRound + 5;
}
/**
* @notice Removes an active market from the App
* @dev Only callable by admin. Market ID must already exist
* @dev Markets should be scheduled for delete using putMarketOnDelist() before calling this function
* @param index The market ID to remove
*
* @custom:reverts NotAuthorised if caller is not admin
* @custom:reverts InvalidInput if market ID doesn't exist
*/
function delistMarket(uint256 index) external {
if(msg.sender != admin) {
revert NotAuthorised();
}
if(marketToDelistingRound[index] == 0 || marketToDelistingRound[index] > universalRound) revert InvalidInput();
if(!availableMarkets.remove(index)) revert InvalidInput();
}
/**
* @notice Updates the admin
* @dev Only callable by admin
* @param newAdmin The newAdmin's address
*
* @custom:reverts NotAuthorised if caller is not admin
*/
function updateAdmin(address newAdmin) external {
if(msg.sender != admin) {
revert NotAuthorised();
}
admin = newAdmin;
}
/**
* @notice Buy YES or NO shares in a prediction market
* @dev Uses AMM formula to calculate shares. Deducts 0.3% fee (60% protocol, 40% resolver)
* @param minAmountOut Minimum shares expected (slippage protection)
* @param marketId Market identifier (0=BTC, 1=HYPE, etc.)
* @param roundId Round identifier (must be current round or next round in pre-market)
* @param side 0 for YES (price will increase), 1 for NO (price will decrease)
*
* Requirements:
* - msg.value > 0 (must send HYPE)
* - roundId must be universalRound or universalRound+1
* - If roundId == universalRound: must be within first 5 minutes
* - If roundId == universalRound+1: must be after 5 minutes (pre-market)
* - Previous round must have a price (for current round)
*
* Effects:
* - Registers user in round if first time
* - Updates market reserves
* - Updates user share balances
* - Distributes fees (60% protocol, 40% resolver)
*
* @custom:reverts InvalidInput if side > 1
* @custom:reverts InvalidRound if roundId is invalid or previous round has no price
* @custom:reverts RoundExpired if current round trading window has closed
* @custom:reverts RoundNotYetInitialised if trying to enter next round before pre-market
* @custom:reverts SlippageReached if calculated shares < minAmountOut
*/
function enterMarket(uint256 minAmountOut, uint256 marketId, uint256 roundId, uint256 side) external payable {
if (!availableMarkets.contains(marketId)) revert InvalidInput();
if(marketToDelistingRound[marketId] != 0 && marketToDelistingRound[marketId] <= roundId) revert InvalidInput();
assembly {
let rStart := sload(roundStart.slot)
if gt(side, 1) {
mstore(0x00, 0xb4fa3fb3) //InvalidInput()
revert(0x1c, 0x04)
}
let universalRoundId := sload(universalRound.slot)
// marketToRoundToPrice
mstore(0x00, marketId)
mstore(0x20, 9)
let hash := keccak256(0, 0x40)
mstore(0, sub(roundId, 1))
mstore(0x20, hash)
hash := keccak256(0, 0x40)
if and(eq(universalRoundId, roundId), eq(sload(hash), 0)) {
mstore(0x00, 0xa2b52a54) //InvalidRound()
revert(0x1c, 0x04)
}
if or(gt(roundId, add(universalRoundId, 1)), lt(roundId, universalRoundId)) {
mstore(0x00, 0xa2b52a54) //InvalidRound()
revert(0x1c, 0x04)
}
if and(eq(roundId, universalRoundId), lt(add(rStart, 300), timestamp())) {
mstore(0x00, 0x9e6d804f) //RoundExpired()
revert(0x1c, 0x04)
}
if and(eq(roundId, add(universalRoundId, 1)), lt(timestamp(), add(rStart, 300))) {
mstore(0x00, 0x5b903c71) //RoundNotYetInitialised()
revert(0x1c, 0x04)
}
let amount := div(mul(callvalue(), 997), 1000)
let totalFee := sub(callvalue(), amount)
sstore(fees.slot, add(sload(fees.slot), div(mul(totalFee, 600), 1000))) //Deduct resolver fees from total fees
// roundIdToResolverFees
mstore(0x00, roundId)
mstore(0x20, 16)
hash := keccak256(0, 0x40)
sstore(hash, add(sload(hash), sub(totalFee, div(mul(totalFee, 600), 1000))))
// marketToRoundToTreasury
mstore(0x00, marketId)
mstore(0x20, 6)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, add(sload(hash), amount))
// userToRegisteredRound
mstore(0x00, caller())
mstore(0x20, 12)
hash := keccak256(0x00, 0x40)
mstore(0x00, marketId)
mstore(0x20, hash)
hash := keccak256(0x00, 0x40)
mstore(0x00, roundId)
mstore(0x20, hash)
hash := keccak256(0x00, 0x40)
if eq(sload(hash), 0) {
sstore(hash, 1)
// userToActiveRoundsPerMarket
mstore(0x00, caller())
mstore(0x20, 11)
hash := keccak256(0, 0x40)
mstore(0x00, marketId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
let len := sload(hash)
sstore(hash, add(len, 1))
mstore(0x00, hash)
hash := keccak256(0, 0x20)
sstore(add(hash, len), roundId)
}
// marketToRoundToYesReserves
mstore(0x00, marketId)
mstore(0x20, 4)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
let yesReserves := sload(hash)
// marketToRoundToNoReserves
mstore(0x00, marketId)
mstore(0x20, 5)
let noHash := keccak256(0, 0x40)
mstore(0x20, noHash)
mstore(0, roundId)
noHash := keccak256(0, 0x40)
let noReserves := sload(noHash)
// _buyYes()
if eq(side, 0) {
let userPrimaryReserves := div(mul(amount, yesReserves), add(amount, noReserves))
if lt(add(userPrimaryReserves, amount), minAmountOut) {
mstore(0x00, 0xa6d7690f) //SlippageReached()
revert(0x1c, 0x04)
}
sstore(hash, sub(yesReserves, userPrimaryReserves))
sstore(noHash, add(noReserves, amount))
// userToMarketToRoundToYesReserves
mstore(0x00, caller())
mstore(0x20, 7)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, add(sload(hash), add(userPrimaryReserves, amount)))
// marketToRoundToOutYesShares
mstore(0x00, marketId)
mstore(0x20, 14)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, add(sload(hash), add(userPrimaryReserves, amount)))
mstore(0x00, callvalue())
mstore(0x20, side)
mstore(0x40, add(userPrimaryReserves, amount))
log4(0x00, 0x60, 0xafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd9, marketId, roundId, caller())
return(0,0)
}
// _buyNo()
let userSecondaryReserves := div(mul(amount, noReserves), add(amount, yesReserves))
if lt(add(userSecondaryReserves, amount), minAmountOut) {
mstore(0x00, 0xa6d7690f) //SlippageReached()
revert(0x1c, 0x04)
}
sstore(hash, add(yesReserves, amount))
sstore(noHash, sub(noReserves, userSecondaryReserves))
// userToMarketToRoundToNoReserves
mstore(0x00, caller())
mstore(0x20, 8)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, add(sload(hash), add(userSecondaryReserves, amount)))
// marketToRoundToOutNoShares
mstore(0x00, marketId)
mstore(0x20, 15)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, add(sload(hash), add(userSecondaryReserves, amount)))
mstore(0x00, callvalue())
mstore(0x20, side)
mstore(0x40, add(userSecondaryReserves, amount))
log4(0x00, 0x60, 0xafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd9, marketId, roundId, caller())
return(0,0)
}
}
/**
* @notice Exit a market position by selling YES and NO shares
* @dev Optionally swaps between YES/NO before redeeming. Deducts 0.3% exit fee
* @param minNativeAmountOut Minimum HYPE expected after exit (slippage protection)
* @param marketId Market identifier
* @param roundId Round identifier (must be current or next round)
* @param amountYes Amount of YES shares user wants to sell
* @param amountNo Amount of NO shares user wants to sell
* @param toBeExchanged Amount to swap between YES/NO to balance position before exit
*
* Process:
* 1. If toBeExchanged > 0: Swaps YES to NO or NO to YES (whichever is higher)
* 2. Redeems equal amounts of YES and NO shares for HYPE
* 3. Deducts 0.3% fee (60% protocol, 40% resolver)
* 4. Transfers remaining HYPE to user
*
* Requirements:
* - roundId must be current round or next round
* - If current round: must be within trading window (first 5 minutes)
* - If next round: must be within pre-market trading window (second 5 minutes of current round)
* - User must have sufficient YES and NO shares
*
* @custom:reverts InvalidRound if roundId is out of valid range
* @custom:reverts RoundExpired if current round trading window has closed
* @custom:reverts SlippageReached if HYPE received < minNativeAmountOut
* @custom:reverts InvalidOutput if HYPE transfer to user fails
*/
function exitMarket(uint256 minNativeAmountOut, uint256 marketId, uint256 roundId, uint256 amountYes, uint256 amountNo, uint256 toBeExchanged) external {
if(!availableMarkets.contains(marketId)) revert InvalidInput();
uint256 amountOut;
if (toBeExchanged > 0 ) {
if (amountYes < amountNo) {
amountOut = _sellNo(toBeExchanged, marketId, roundId);
amountNo -= toBeExchanged;
amountYes += amountOut;
} else {
amountOut = _sellYes(toBeExchanged,marketId, roundId);
amountYes -= toBeExchanged;
amountNo += amountOut;
}
}
amountOut = amountYes > amountNo ? amountNo : amountYes;
// @dev marketToRoundToYesReserves transient_slot 0
// @dev marketToRoundToNoReserves transient_slot 1
// @dev marketToRoundToTreasury transient_slot 2
// @dev userToMarketToRoundToYesReserves transient_slot 3
// @dev userToMarketToRoundToNoReserves transient_slot 4
// @dev marketToRoundToOutYesShares transient_slot 5
// @dev marketToRoundToOutNoShares transient_slot
assembly {
let localUniversalRound := sload(universalRound.slot)
if or(lt(roundId, localUniversalRound), gt(roundId, add(localUniversalRound, 1))) {
mstore(0x00, 0xa2b52a54) //InvalidRound()
revert(0x1c, 0x04)
}
if and(eq(roundId, localUniversalRound), lt(add(sload(roundStart.slot), 300), timestamp())) {
mstore(0x00, 0x9e6d804f) //RoundExpired()
revert(0x1c, 0x04)
}
switch gt(toBeExchanged, 0)
case 1 {
// marketToRoundToTreasury DONE
mstore(0x00, marketId)
mstore(0x20, 6)
let hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, sub(tload(2), amountOut))
tstore(2, 0)
// userToMarketToRoundToYesReserves DONE
mstore(0x00, caller())
mstore(0x20, 7)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
if lt(tload(3), amountOut) {
mstore(0x00, 0x7b9c8916) //InvalidReserves()
revert(0x1c, 0x04)
}
sstore(hash, sub(tload(3), amountOut))
tstore(3, 0)
// userToMarketToRoundToNoReserves DONE
mstore(0x00, caller())
mstore(0x20, 8)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
if lt(tload(4), amountOut) {
mstore(0x00, 0x7b9c8916) //InvalidReserves()
revert(0x1c, 0x04)
}
sstore(hash, sub(tload(4), amountOut))
tstore(4, 0)
// marketToRoundToOutYesShares DONE
mstore(0x00, marketId)
mstore(0x20, 14)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, sub(tload(5), amountOut))
tstore(5, 0)
// marketToRoundToOutNoShares DONE
mstore(0x00, marketId)
mstore(0x20, 15)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, sub(tload(6), amountOut))
tstore(6, 0)
}
case 0 {
// marketToRoundToTreasury DONE
mstore(0x00, marketId)
mstore(0x20, 6)
let hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, sub(sload(hash), amountOut))
// userToMarketToRoundToYesReserves DONE
mstore(0x00, caller())
mstore(0x20, 7)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
let state := sload(hash)
if lt(state, amountOut) {
mstore(0x00, 0x7b9c8916) //InvalidReserves()
revert(0x1c, 0x04)
}
sstore(hash, sub(state, amountOut))
// userToMarketToRoundToNoReserves DONE
mstore(0x00, caller())
mstore(0x20, 8)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
state := sload(hash)
if lt(state, amountOut) {
mstore(0x00, 0x7b9c8916) //InvalidReserves()
revert(0x1c, 0x04)
}
sstore(hash, sub(state, amountOut))
// marketToRoundToOutYesShares DONE
mstore(0x00, marketId)
mstore(0x20, 14)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, sub(sload(hash), amountOut))
// marketToRoundToOutNoShares DONE
mstore(0x00, marketId)
mstore(0x20, 15)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, roundId)
hash := keccak256(0, 0x40)
sstore(hash, sub(sload(hash), amountOut))
}
let amountOutAfterFee := div(mul(amountOut, 997), 1000)
let totalFee := sub(amountOut, amountOutAfterFee)
sstore(fees.slot, add(sload(fees.slot), div(mul(totalFee, 600), 1000))) //Deduct resolver fees from total fees
// roundIdToResolverFees
mstore(0x00, roundId)
mstore(0x20, 16)
let hash := keccak256(0, 0x40)
sstore(hash, add(sload(hash), sub(totalFee, div(mul(totalFee, 600), 1000))))
if lt(amountOutAfterFee, minNativeAmountOut) {
mstore(0x00, 0xa6d7690f) //SlippageReached()
revert(0x1c, 0x04)
}
mstore(0x00, amountYes)
mstore(0x20, amountNo)
mstore(0x40, amountOutAfterFee)
log4(0x00, 0x60, 0x4c686a53bc9329e91f0d0d94d821505fd2c0aef3c09a94ea360d98c0dfb9dee4, marketId, roundId, caller())
if iszero(
call(gas(), caller(), amountOutAfterFee, 0, 0, 0, 0)
) {
mstore(0x00, 0x98f73609) //InvalidOutput()
revert(0x1c, 0x04)
}
}
}
/**
* @notice Resolves all markets for the current round and starts a new round
* @dev Can be called by anyone after 10 minutes. Caller receives resolver fees as incentive
*
* Process:
* 1. Validates 10 minutes (600 seconds) have passed since round start
* 2. For each market:
* - Fetches current price from oracle
* - Compares with previous round's price
* - Sets result: 1 if price increased (YES wins), 2 if decreased (NO wins)
* - If no winners, adds treasury to protocol fees
* - Initializes reserves for round+2 (425 HYPE each)
* 3. Increments universalRound
* 4. Updates roundStart to current timestamp
* 5. Transfers accumulated resolver fees to caller
*
* Fee Distribution:
* - Resolver receives 40% of all trading fees from the round
* - Protocol receives 60% of all trading fees
*
* @custom:reverts InvalidTimestamp if called before 10 minutes elapsed
* @custom:reverts RoundResolved if round already resolved
* @custom:reverts OracleError if oracle price fetch fails
* @custom:reverts InvalidOutput if fee transfer to resolver fails
*/
function resolveMarkets() external {
assembly {
if lt(timestamp(), add(sload(roundStart.slot), 600)) {
mstore(0x00, 0xb7d09497) //InvalidTimestamp()
revert(0x1c, 0x04)
}
}
uint256 uRound = universalRound;
uint256 len = availableMarkets.length();
for(uint i=0; i<len; i++){
uint256 marketId = availableMarkets.at(i);
// get price from oracle
uint256 currentPrice = _oraclePx(marketId);
assembly {
// marketToRoundToResult
mstore(0x00, marketId)
mstore(0x20, 10)
let hash := keccak256(0x00, 0x40)
mstore(0x00, uRound)
mstore(0x20, hash)
let resultHash := keccak256(0x00, 0x40)
if gt(sload(resultHash), 0) {
mstore(0x00, 0xfd29af2c) //RoundResolved()
revert(0x1c, 0x04)
}
// marketToRoundToPrice currentRound -1
mstore(0x00, marketId)
mstore(0x20, 9)
hash := keccak256(0x00, 0x40)
mstore(0x00, sub(uRound, 1))
mstore(0x20, hash)
hash := keccak256(0x00, 0x40)
let lastPrice := sload(hash)
// marketToRoundToPrice currentRound
mstore(0x00, uRound)
hash := keccak256(0x00, 0x40)
sstore(hash, currentPrice)
if gt(lastPrice, 0) {
mstore(0x00, marketId)
mstore(0x20, 6)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, uRound)
hash := keccak256(0, 0x40)
let treasury := sload(hash)
switch gt(currentPrice, lastPrice)
case 1 {
sstore(resultHash, 1)
// If there are no winners then add market treasury to fees
mstore(0x00, marketId)
mstore(0x20, 14)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, uRound)
hash := keccak256(0, 0x40)
if eq(sload(hash), 0) {
sstore(fees.slot, add(sload(fees.slot), treasury))
}
}
case 0 {
sstore(resultHash, 2)
// If there are no winners then add market treasury to fees
mstore(0x00, marketId)
mstore(0x20, 15)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, uRound)
hash := keccak256(0, 0x40)
if eq(sload(hash), 0) {
sstore(fees.slot, add(sload(fees.slot), treasury))
}
}
}
// marketToRoundToYesReserves
mstore(0x00, marketId)
mstore(0x20, 4)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, add(uRound, 2))
hash := keccak256(0, 0x40)
sstore(hash, 425000000000000000000)
// marketToRoundToNoReserves
mstore(0x00, marketId)
mstore(0x20, 5)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, add(uRound, 2))
hash := keccak256(0, 0x40)
sstore(hash, 425000000000000000000)
}
}
assembly {
mstore(0x00, sload(universalRound.slot))
mstore(0x20, 16)
let hash := keccak256(0, 0x40)
let roundFees := sload(hash)
sstore(universalRound.slot, add(uRound, 1))
sstore(roundStart.slot, timestamp())
if iszero(
call(gas(), caller(), roundFees, 0, 0, 0, 0)
) {
mstore(0x00, 0x98f73609) //InvalidOutput()
revert(0x1c, 0x04)
}
mstore(0x00, roundFees)
log3(0x00, 0x20, 0xa4151f6c29291b1556b1872bc36e5304d55092b1703f6226eefdb53250765c71, uRound, caller())
}
}
/**
* @notice Claims winnings from resolved rounds for a specific market (max 25 rounds)
* @dev Processes up to 25 rounds per call to avoid gas limits. Call multiple times if needed
* @param marketId Market identifier to claim winnings from
* @dev Unresolved RoundIds will deterministically be placed on either roundIds storage slot 0, 1 or total_len-1, total_len-2 after an iteration
*
* Process:
* 1. Retrieves user's pending rounds for the market
* 2. Processes up to 25 rounds:
* - Checks if round is resolved
* - Calculates user's share of treasury based on winning shares
* - Transfers winnings to user
* - Marks round as redeemed
* - Removes from pending list if resolved
* 3. Reorganizes pending rounds array
*
* Payout Formula:
* - userPayout = (userWinningShares * marketTreasury) / totalWinningShares
*
* @custom:reverts AlreadyClaimed if user already claimed winnings for a round
* @custom:reverts InvalidOutput if HYPE transfer fails
*/
function redeemRoundsPerMarketIdCapped(uint256 marketId) external {
assembly {
mstore(0x00, caller())
mstore(0x20, 11)
let hash := keccak256(0, 0x40)
mstore(0x00, marketId)
mstore(0x20, hash)
let roundHashLen := keccak256(0, 0x40)
let totalLen := sload(roundHashLen)
let len := totalLen
mstore(0x00, roundHashLen)
let itemHash := keccak256(0, 0x20)
if gt(len, 25) {
len := 25
}
for {let i := 0} lt(i, len) {i := add(i, 1)} {
let roundId := sload(add(itemHash, i))
sstore(add(itemHash, i), 0) //clear roundId
// userToRedeemedMarketRound
mstore(0x00, caller())
mstore(0x20, 13)
hash := keccak256(0, 0x40)
mstore(0, marketId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
let resultHash := keccak256(0, 0x40)
if gt(sload(resultHash), 0) {
mstore(0x00, 0x646cf558) // AlreadyClaimed()
revert(0x1c, 0x04)
}
// marketToRoundToResult
mstore(0x00, marketId)
mstore(0x20, 10)
hash := keccak256(0x00, 0x40)
mstore(0x00, roundId)
mstore(0x20, hash)
hash := keccak256(0x00, 0x40)
let userBet := 0
let winningBets := 1
let result := sload(hash)
switch result
case 1 {
// userToRedeemedMarketRound
sstore(resultHash, 1)
// userToMarketToRoundToYesReserves
mstore(0x00, caller())
mstore(0x20, 7)
hash := keccak256(0, 0x40)
mstore(0, marketId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
userBet := sload(hash)
// marketToRoundToOutYesShares
mstore(0x00, marketId)
mstore(0x20, 14)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
winningBets := sload(hash)
}
case 2 {
// userToRedeemedMarketRound
sstore(resultHash, 1)
// userToMarketToRoundToNoReserves
mstore(0x00, caller())
mstore(0x20, 8)
hash := keccak256(0, 0x40)
mstore(0, marketId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
userBet := sload(hash)
// marketToRoundToOutNoShares
mstore(0x00, marketId)
mstore(0x20, 15)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
winningBets := sload(hash)
}
default {
tstore(i, roundId)
}
if gt(sload(resultHash), 0) {
// marketToRoundToTreasury
mstore(0x00, marketId)
mstore(0x20, 6)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
let amountOut := div(mul(userBet, sload(hash)), winningBets)
mstore(0x00, result)
mstore(0x20, amountOut)
log4(0x00, 0x40, 0x3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac4839, marketId, roundId, caller())
if iszero(call(gas(), caller(), amountOut, 0, 0, 0, 0)) {
mstore(0x00, 0x98f73609) //InvalidOutput()
revert(0x1c, 0x04)
}
}
}
let movingLen := sub(totalLen, len)
if gt(movingLen, 25) {
movingLen := 25
}
let newLen := sub(totalLen, len)
for {let i := 0} lt(i, movingLen) {i := add(i, 1)} {
sstore(add(itemHash, i), sload(add(itemHash, sub(totalLen, add(i, 1)))))
if gt(tload(i), 0) {
sstore(add(itemHash, newLen), tload(i))
tstore(i, 0)
newLen := add(newLen, 1)
}
}
if eq(movingLen, 0 ) {
//fallback if we need to index the whole window when processed assets are less than the page
for {let i := 0} lt(i, 25) {i := add(i, 1)} {
if gt(tload(i), 0) {
sstore(add(itemHash, newLen), tload(i))
tstore(i, 0)
newLen := add(newLen, 1)
}
}
}
sstore(roundHashLen, newLen)
}
}
/**
* @notice Claims winnings from ALL pending rounds for a specific market (unbounded)
* @dev WARNING: May run out of gas if user has many pending rounds. Use capped version for safety
* @param marketId Market identifier to claim winnings from
* @dev Unresolved RoundIds will deterministically be on either transient slot 0, 1 or total_len-1, total_len-2
*
* Process:
* - Same as redeemRoundsPerMarketIdCapped but processes ALL pending rounds
* - No 25-round limit
*
* Gas Considerations:
* - Each round costs ~60k gas
* - Block gas limit is ~2M
* - Safe to process ~25 rounds per call
* - Use capped version if unsure
*
* @custom:reverts AlreadyClaimed if user already claimed winnings for a round
* @custom:reverts InvalidOutput if HYPE transfer fails
*/
function redeemPendingRoundsPerMarketId(uint256 marketId) external {
assembly {
mstore(0x00, caller())
mstore(0x20, 11)
let hash := keccak256(0, 0x40)
mstore(0x00, marketId)
mstore(0x20, hash)
let roundHashLen := keccak256(0, 0x40)
let len := sload(roundHashLen)
mstore(0x00, roundHashLen)
let itemHash := keccak256(0, 0x20)
for {let i := 0} lt(i, len) {i := add(i, 1)} {
let roundId := sload(add(itemHash, i))
sstore(add(itemHash, i), 0) //clear roundId
// userToRedeemedMarketRound
mstore(0x00, caller())
mstore(0x20, 13)
hash := keccak256(0, 0x40)
mstore(0, marketId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
let resultHash := keccak256(0, 0x40)
if gt(sload(resultHash), 0) {
mstore(0x00, 0x646cf558) // AlreadyClaimed()
revert(0x1c, 0x04)
}
// marketToRoundToResult
mstore(0x00, marketId)
mstore(0x20, 10)
hash := keccak256(0x00, 0x40)
mstore(0x00, roundId)
mstore(0x20, hash)
hash := keccak256(0x00, 0x40)
let userBet := 0
let winningBets := 1
let result := sload(hash)
switch result
case 1 {
// userToRedeemedMarketRound
sstore(resultHash, 1)
// userToMarketToRoundToYesReserves
mstore(0x00, caller())
mstore(0x20, 7)
hash := keccak256(0, 0x40)
mstore(0, marketId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
userBet := sload(hash)
// marketToRoundToOutYesShares
mstore(0x00, marketId)
mstore(0x20, 14)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
winningBets := sload(hash)
}
case 2 {
// userToRedeemedMarketRound
sstore(resultHash, 1)
// userToMarketToRoundToNoReserves
mstore(0x00, caller())
mstore(0x20, 8)
hash := keccak256(0, 0x40)
mstore(0, marketId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
userBet := sload(hash)
// marketToRoundToOutNoShares
mstore(0x00, marketId)
mstore(0x20, 15)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
winningBets := sload(hash)
}
default {
tstore(i, roundId)
}
if gt(sload(resultHash), 0) {
// marketToRoundToTreasury
mstore(0x00, marketId)
mstore(0x20, 6)
hash := keccak256(0, 0x40)
mstore(0, roundId)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
let amountOut := div(mul(userBet, sload(hash)), winningBets)
mstore(0x00, result)
mstore(0x20, amountOut)
log4(0x00, 0x40, 0x3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac4839, marketId, roundId, caller())
if iszero(
call(gas(), caller(), amountOut, 0, 0, 0, 0)
) {
mstore(0x00, 0x98f73609) //InvalidOutput()
revert(0x1c, 0x04)
}
}
}
let newLen := 0
if gt(tload(0), 0) {
sstore(add(itemHash, newLen), tload(0))
tstore(0, 0)
newLen := add(newLen, 1)
}
if gt(tload(1), 0) {
sstore(add(itemHash, newLen), tload(1))
tstore(1, 0)
newLen := add(newLen, 1)
}
if and(gt(tload(sub(len, 1)), 0), gt(len, 0)) {
sstore(add(itemHash, newLen), tload(sub(len, 1)))
tstore(sub(len, 1), 0)
newLen := add(newLen, 1)
}
if and(gt(tload(sub(len, 2)), 0), gt(len, 1)) {
sstore(add(itemHash, newLen), tload(sub(len, 2)))
tstore(sub(len, 2), 0)
newLen := add(newLen, 1)
}
sstore(roundHashLen, newLen)
}
}
/**
* @notice Withdraws accumulated protocol fees to admin
* @dev Only admin can call. Transfers all accumulated fees and resets to 0
*
* Fee Sources:
* - 60% of all entry fees (0.3% of entry amount)
* - 60% of all exit fees (0.3% of exit amount)
* - Treasury from rounds with no winners
*
* @custom:reverts Require fails if HYPE transfer to admin fails
*/
function claimFees() external {
uint256 feesToClaim = fees;
fees = 0;
require(payable(admin).send(feesToClaim));
}
// Internal functions
/**
* @notice Fetches current price from oracle for a given market
* @dev Calls precompiled oracle contract at address 0x807
* @param index Market index to fetch price for
* @return price Current oracle price for the market
*
* @custom:reverts OracleError if oracle call fails
*/
function _oraclePx(uint256 index) internal view returns (uint256 price) {
address oracle = 0x0000000000000000000000000000000000000807;
assembly {
mstore(0, index)
if iszero(staticcall(gas(), oracle, 0x00, 0x20, 0x00, 0x20)) {
mstore(0x00, 0xb41b6cb1) // OracleError()
revert(0x1c, 0x04)
}
price := mload(0)
}
}
/**
* @notice Internal function to sell YES shares for NO shares
* @dev Uses AMM formula: s = p_amount * S / (P + p_amount)
* @param amount Amount of YES shares to sell
* @param marketId Market identifier
* @param currentRound Round identifier
* @return userSecondaryReserves Amount of NO shares received
*
* Effects:
* - Increases YES reserves by amount
* - Decreases NO reserves by userSecondaryReserves
* - Updates user balances in transient storage
* - Updates outstanding shares in transient storage
*/
function _sellYes(uint256 amount, uint256 marketId, uint256 currentRound) internal returns(uint256 userSecondaryReserves) {
assembly {
// marketToRoundToYesReserves DONE
mstore(0x00, marketId)
mstore(0x20, 4)
let hash := keccak256(0, 0x40)
mstore(0, currentRound)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
let yesReserves := sload(hash)
sstore(hash, add(yesReserves, amount))
// marketToRoundToNoReserves DONE
mstore(0x00, marketId)
mstore(0x20, 5)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
let noReserves := sload(hash)
// s = p_amount * S / (P + p_amount)
userSecondaryReserves := div(mul(amount, noReserves), add(amount, yesReserves))
sstore(hash, sub(noReserves, userSecondaryReserves))
// marketToRoundToTreasury DONE
mstore(0x00, marketId)
mstore(0x20, 6)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
tstore(2, sload(hash))
// userToMarketToRoundToYesReserves DONE
mstore(0x00, caller())
mstore(0x20, 7)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
let state := sload(hash)
if lt(state, amount) {
mstore(0x00, 0x7b9c8916) //InvalidReserves()
revert(0x1c, 0x04)
}
tstore(3, sub(state, amount))
// userToMarketToRoundToNoReserves DONE
mstore(0x00, caller())
mstore(0x20, 8)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
tstore(4, add(sload(hash), userSecondaryReserves))
// marketToRoundToOutYesShares DONE
mstore(0x00, marketId)
mstore(0x20, 14)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
tstore(5, sub(sload(hash), amount))
// marketToRoundToOutNoShares DONE
mstore(0x00, marketId)
mstore(0x20, 15)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
tstore(6, add(sload(hash), userSecondaryReserves))
}
}
/**
* @notice Internal function to sell NO shares for YES shares
* @dev Uses AMM formula: p = s_amount * P / (S + s_amount)
* @param amount Amount of NO shares to sell
* @param marketId Market identifier
* @param currentRound Round identifier
* @return userPrimaryReserves Amount of YES shares received
*
* Effects:
* - Increases NO reserves by amount
* - Decreases YES reserves by userPrimaryReserves
* - Updates user balances in transient storage
* - Updates outstanding shares in transient storage
*/
function _sellNo(uint256 amount, uint256 marketId, uint256 currentRound) internal returns(uint256 userPrimaryReserves) {
assembly {
// marketToRoundToNoReserves DONE
mstore(0x00, marketId)
mstore(0x20, 5)
let hash := keccak256(0, 0x40)
mstore(0, currentRound)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
let noReserves := sload(hash)
sstore(hash, add(noReserves, amount))
// marketToRoundToYesReserves DONE
mstore(0x00, marketId)
mstore(0x20, 4)
hash := keccak256(0, 0x40)
mstore(0, currentRound)
mstore(0x20, hash)
hash := keccak256(0, 0x40)
let yesReserves := sload(hash)
// p = s_amount * P / (S + s_amount)
userPrimaryReserves := div(mul(amount, yesReserves), add(amount, noReserves))
sstore(hash, sub(yesReserves, userPrimaryReserves))
// marketToRoundToTreasury DONE
mstore(0x00, marketId)
mstore(0x20, 6)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
tstore(2, sload(hash))
// userToMarketToRoundToYesReserves DONE
mstore(0x00, caller())
mstore(0x20, 7)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
tstore(3, add(sload(hash), userPrimaryReserves))
// userToMarketToRoundToNoReserves DONE
mstore(0x00, caller())
mstore(0x20, 8)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, marketId)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
let state := sload(hash)
if lt(state, amount) {
mstore(0x00, 0x7b9c8916) //InvalidReserves()
revert(0x1c, 0x04)
}
tstore(4, sub(state, amount))
// marketToRoundToOutYesShares DONE
mstore(0x00, marketId)
mstore(0x20, 14)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
tstore(5, add(sload(hash), userPrimaryReserves))
// marketToRoundToOutNoShares DONE
mstore(0x00, marketId)
mstore(0x20, 15)
hash := keccak256(0, 0x40)
mstore(0x20, hash)
mstore(0, currentRound)
hash := keccak256(0, 0x40)
tstore(6, sub(sload(hash), amount))
}
}
//MARKET INFO VIEW FUNCTIONS
/**
* @notice Get market data for all markets in the current round
* @return marketData Array of MarketData structs for all available markets
*/
function currentRoundInfo() external view returns(MarketData[] memory marketData) {
uint256 len = availableMarkets.length();
marketData = new MarketData[](len);
uint256 roundId = universalRound;
uint256 currentRoundStart = roundStart;
for(uint i=0; i<len; i++) {
uint256 marketId = availableMarkets.at(i);
uint256 currentPrice = _oraclePx(marketId);
marketData[i] = MarketData({
marketId: marketId,
roundId: roundId,
roundStart: currentRoundStart,
yesReserves: marketToRoundToYesReserves[marketId][roundId],
noReserves: marketToRoundToNoReserves[marketId][roundId],
marketTreasury: marketToRoundToTreasury[marketId][roundId],
lastPrice: marketToRoundToPrice[marketId][roundId-1],
currentPrice: currentPrice,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId]
});
}
}
//MARKET INFO VIEW FUNCTIONS
/**
* @notice Get market data for all markets in the current and next round
* @return roundId Current round's number
* @return marketDataCurrent Array of MarketData structs for all available markets for active round
* @return marketDataFuture Array of MarketData structs for all available markets for next round
*/
function currentAndFutureRoundInfo() external view returns(uint256 roundId, MarketDataWithHistory[] memory marketDataCurrent, MarketDataWithHistory[] memory marketDataFuture) {
uint256 len = availableMarkets.length();
roundId = universalRound;
uint256 historyLen = roundId > 10 ? 10 : roundId-1;
marketDataCurrent = new MarketDataWithHistory[](len);
marketDataFuture = new MarketDataWithHistory[](len);
uint256 futureRound = roundId + 1;
uint256 currentRoundStart = roundStart;
for(uint i=0; i<len; i++) {
uint256[] memory history = new uint256[](historyLen);
uint256 marketId = availableMarkets.at(i);
uint256 currentPrice = _oraclePx(marketId);
for(uint j=0; j<historyLen; j++) {
history[j] = marketToRoundToResult[marketId][roundId-j-1];
}
marketDataCurrent[i] = MarketDataWithHistory({
marketId: marketId,
roundId: roundId,
roundStart: currentRoundStart,
yesReserves: marketToRoundToYesReserves[marketId][roundId],
noReserves: marketToRoundToNoReserves[marketId][roundId],
marketTreasury: marketToRoundToTreasury[marketId][roundId],
lastPrice: marketToRoundToPrice[marketId][roundId-1],
currentPrice: currentPrice,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
delistingRound: marketToDelistingRound[marketId],
history: history
});
marketDataFuture[i] = MarketDataWithHistory({
marketId: marketId,
roundId: futureRound,
roundStart: currentRoundStart,
yesReserves: marketToRoundToYesReserves[marketId][futureRound],
noReserves: marketToRoundToNoReserves[marketId][futureRound],
marketTreasury: marketToRoundToTreasury[marketId][futureRound],
lastPrice: marketToRoundToPrice[marketId][roundId],
currentPrice: currentPrice,
result: marketToRoundToResult[marketId][futureRound],
outYesReserves: marketToRoundToOutYesShares[marketId][futureRound],
outNoReserves: marketToRoundToOutNoShares[marketId][futureRound],
delistingRound: marketToDelistingRound[marketId],
history: history
});
delete history;
}
}
/**
* @notice Get market data for all markets in a specific round
* @param roundId Round identifier to query
* @return marketData Array of MarketData structs for all markets in the round
*/
function inputRoundInfo(uint256 roundId) external view returns(MarketData[] memory marketData) {
uint256 len = availableMarkets.length();
marketData = new MarketData[](len);
uint256 currentRoundStart = roundStart;
for(uint i=0; i<len; i++) {
uint256 marketId = availableMarkets.at(i);
uint256 cPrice = marketToRoundToPrice[marketId][roundId];
uint256 currentPrice = cPrice == 0 ? _oraclePx(marketId): cPrice;
marketData[i] = MarketData({
marketId: marketId,
roundId: roundId,
roundStart: currentRoundStart,
yesReserves: marketToRoundToYesReserves[marketId][roundId],
noReserves: marketToRoundToNoReserves[marketId][roundId],
marketTreasury: marketToRoundToTreasury[marketId][roundId],
lastPrice: marketToRoundToPrice[marketId][roundId-1],
currentPrice: currentPrice,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId]
});
}
}
/**
* @notice Get market data for a specific market in the current round
* @param marketId Market identifier to query
* @return marketData MarketData struct for the specified market
*/
function currentSingleMarketRoundInfo(uint256 marketId) external view returns(MarketData memory marketData) {
uint256 roundId = universalRound;
uint256 currentRoundStart = roundStart;
uint256 currentPrice = _oraclePx(marketId);
marketData = MarketData({
marketId: marketId,
roundId: roundId,
roundStart: currentRoundStart,
yesReserves: marketToRoundToYesReserves[marketId][roundId],
noReserves: marketToRoundToNoReserves[marketId][roundId],
marketTreasury: marketToRoundToTreasury[marketId][roundId],
lastPrice: marketToRoundToPrice[marketId][roundId-1],
currentPrice: currentPrice,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId]
});
}
/**
* @notice Get market data for a specific market in a specific round
* @param marketId Market identifier to query
* @param roundId Round identifier to query
* @return marketData MarketData struct for the specified market and round
*/
function inputSingleMarketRoundInfo(uint256 marketId, uint256 roundId) external view returns(MarketDataWithHistory memory marketData) {
uint256 currentRoundStart = roundStart;
uint256 cPrice = marketToRoundToPrice[marketId][roundId];
uint256 currentPrice = cPrice == 0 ? _oraclePx(marketId): cPrice;
uint256 historyLen = roundId > 10 ? 10 : roundId-1;
uint256[] memory history = new uint256[](historyLen);
for(uint j=0; j<historyLen; j++) {
history[j] = marketToRoundToResult[marketId][roundId-j-1];
}
marketData = MarketDataWithHistory({
marketId: marketId,
roundId: roundId,
roundStart: currentRoundStart,
yesReserves: marketToRoundToYesReserves[marketId][roundId],
noReserves: marketToRoundToNoReserves[marketId][roundId],
marketTreasury: marketToRoundToTreasury[marketId][roundId],
lastPrice: marketToRoundToPrice[marketId][roundId-1],
currentPrice: currentPrice,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
delistingRound: marketToDelistingRound[marketId],
history: history
});
}
/**
* @notice Get market history for a specific market
* @param marketId Market identifier to query
* @return marketData MarketData struct for the specified market and round
*/
function inputMarketRoundHistory(uint256 marketId) external view returns(MarketHistory[] memory marketData) {
uint256 roundId = universalRound;
uint256 historyLen = roundId > 150 ? 150 : roundId-1;
uint256 index = roundId-historyLen;
marketData = new MarketHistory[](historyLen);
for(uint j=0; j<historyLen; j++) {
marketData[j] = MarketHistory({
marketId: marketId,
roundId: index + j,
openPrice: marketToRoundToPrice[marketId][index - 1+j],
closePrice: marketToRoundToPrice[marketId][index + j],
result: marketToRoundToResult[marketId][index + j],
outYesReserves: marketToRoundToOutYesShares[marketId][index+j],
outNoReserves: marketToRoundToOutNoShares[marketId][index+j]
});
}
}
/**
* @notice Check if current round can be resolved and get resolver fees
* @return isResolvable True if 10 minutes have passed and round can be resolved
* @return secondsLeft Seconds remaining until round can be resolved (0 if resolvable)
* @return currentRoundFees Accumulated resolver fees for current round (40% of trading fees)
*/
function checkResolutionStatus() external view returns(bool isResolvable, uint256 secondsLeft, uint256 currentRoundFees) {
isResolvable = block.timestamp >= roundStart + 600;
secondsLeft = block.timestamp < roundStart + 600 ? roundStart + 600 - block.timestamp : 0;
currentRoundFees = roundIdToResolverFees[universalRound];
}
//USER INFO VIEW FUNCTIONS
/**
* @notice Get all unclaimed round IDs for a user in a specific market
* @param user User address to query
* @param marketId Market identifier
* @return roundIds Array of round IDs where user has unclaimed positions
*/
function userUnclaimedRoundsPerMarketId(address user, uint256 marketId) external view returns (uint256[] memory roundIds) {
return userToActiveRoundsPerMarket[user][marketId];
}
/**
* @notice Get unclaimed round IDs with pagination (500 per page)
* @param user User address to query
* @param marketId Market identifier
* @param page Page number (0-indexed)
* @return total Total number of unclaimed rounds
* @return roundIds Array of round IDs for the requested page (max 500)
*/
function userUnclaimedRoundsPerMarketIdWithPage(address user, uint256 marketId, uint256 page) external view returns (uint256 total, uint256[] memory roundIds) {
total = userToActiveRoundsPerMarket[user][marketId].length;
uint256 pageSize = 500;
uint256 startIndex = page * pageSize;
if (startIndex >= total) {
roundIds = new uint256[](0);
return (total, roundIds);
}
uint256 remaining = total - startIndex;
uint256 length = remaining < pageSize ? remaining : pageSize;
roundIds = new uint256[](length);
for (uint256 i = 0; i < length; i++) {
roundIds[i] = userToActiveRoundsPerMarket[user][marketId][startIndex + i];
}
return (total, roundIds);
}
/**
* @notice Get detailed data for unclaimed rounds with pagination (100 per page)
* @param user User address to query
* @param marketId Market identifier
* @param page Page number (0-indexed)
* @return total Total number of unclaimed rounds
* @return userData Array of UserData structs for the requested page (max 100)
*/
function userUnclaimedRoundsDataPerMarketId(address user, uint256 marketId, uint256 page) external view returns(uint256 total, UserData[] memory userData){
total = userToActiveRoundsPerMarket[user][marketId].length;
uint256 pageSize = 100;
uint256 startIndex = page * pageSize;
if (startIndex >= total) {
userData = new UserData[](0);
return (total, userData);
}
uint256 remaining = total - startIndex;
uint256 length = remaining < pageSize ? remaining : pageSize;
userData = new UserData[](length);
for(uint i=0; i<length;i++) {
uint256 roundId = userToActiveRoundsPerMarket[user][marketId][startIndex + i];
userData[i] = UserData({
marketId: marketId,
roundId: roundId,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
treasury: marketToRoundToTreasury[marketId][roundId],
userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
});
}
}
/**
* @notice Get unclaimed rounds across all markets for a user
* @param user User address to query
* @return roundsPerMarket Array of UserToRoundsPerMarket structs for all markets
*/
function userToUnclaimedRounds(address user) external view returns(UserToRoundsPerMarket[] memory roundsPerMarket) {
uint256 len = availableMarkets.length();
roundsPerMarket = new UserToRoundsPerMarket[](len);
for(uint i=0; i<len;i++) {
uint256 marketId = availableMarkets.at(i);
roundsPerMarket[i] = UserToRoundsPerMarket({
marketId: marketId,
roundIds: userToActiveRoundsPerMarket[user][marketId]
});
}
}
/**
* @notice Get user data for all markets in the current round
* @param user User address to query
* @return userData Array of UserData structs for all markets in current round
*/
function userDataPerCurrentRoundId(address user) external view returns(UserData[] memory userData){
uint256 len = availableMarkets.length();
userData = new UserData[](len);
uint256 roundId = universalRound;
for(uint i=0; i<len;i++) {
uint256 marketId = availableMarkets.at(i);
userData[i] = UserData({
marketId: marketId,
roundId: roundId,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
treasury: marketToRoundToTreasury[marketId][roundId],
userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
});
}
}
/**
* @notice Get user data for a specific market in the current round
* @param user User address to query
* @param marketId Market identifier
* @return userData UserData struct for the specified market in current round
*/
function userDataPerMarketAndCurrentRoundId(address user, uint256 marketId) external view returns(UserData memory userData){
uint256 roundId = universalRound;
userData = UserData({
marketId: marketId,
roundId: roundId,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
treasury: marketToRoundToTreasury[marketId][roundId],
userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
});
}
/**
* @notice Get user data for all markets in a specific round
* @param user User address to query
* @param roundId Round identifier
* @return userData Array of UserData structs for all markets in the round
*/
function userDataPerRoundId(address user, uint256 roundId) external view returns(UserData[] memory userData){
uint256 len = availableMarkets.length();
userData = new UserData[](len);
for(uint i=0; i<len;i++) {
uint256 marketId = availableMarkets.at(i);
userData[i] = UserData({
marketId: marketId,
roundId: roundId,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
treasury: marketToRoundToTreasury[marketId][roundId],
userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
});
}
}
/**
* @notice Get user data for a specific market and round
* @param user User address to query
* @param marketId Market identifier
* @param roundId Round identifier
* @return userData UserData struct for the specified market and round
*/
function userDataPerMarketIdAndRoundId(address user, uint256 marketId, uint256 roundId) external view returns(UserData memory userData){
userData = UserData({
marketId: marketId,
roundId: roundId,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
treasury: marketToRoundToTreasury[marketId][roundId],
userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
});
}
/**
* @notice Get user data for a specific market across multiple rounds
* @param user User address to query
* @param marketId Market identifier
* @param roundIds Array of round identifiers
* @return userData Array of UserData structs for the specified rounds
*/
function userDataPerMarketIdAndRoundIds(address user, uint256 marketId, uint256[] memory roundIds) external view returns(UserData[] memory userData){
uint256 len = roundIds.length;
userData = new UserData[](len);
for(uint i=0; i<len;i++) {
uint256 roundId = roundIds[i];
userData[i] = UserData({
marketId: marketId,
roundId: roundId,
result: marketToRoundToResult[marketId][roundId],
outYesReserves: marketToRoundToOutYesShares[marketId][roundId],
outNoReserves: marketToRoundToOutNoShares[marketId][roundId],
userYesReserves: userToMarketToRoundToYesReserves[user][marketId][roundId],
userNoReserves: userToMarketToRoundToNoReserves[user][marketId][roundId],
treasury: marketToRoundToTreasury[marketId][roundId],
userRedeemed: userToRedeemedMarketRound[user][marketId][roundId]
});
}
}
/**
* @notice Calculate expected shares for a given input amount
* @dev Applies 0.3% fee before calculation. Used for price quotes
* @param amountIn Amount of HYPE to spend
* @param marketId Market identifier
* @param roundId Round identifier
* @param side 0 for YES, 1 for NO
* @return amountOut Expected shares to receive (after fee)
*
* Formula:
* - amountAfterFee = amountIn * 997 / 1000
* - If YES: amountOut = (amountAfterFee * yesReserves) / (amountAfterFee + noReserves) + amountAfterFee
* - If NO: amountOut = (amountAfterFee * noReserves) / (amountAfterFee + yesReserves) + amountAfterFee
*/
function getAmountOut(uint256 amountIn, uint256 marketId, uint256 roundId, uint256 side) external view returns(uint256 amountOut) {
uint256 yesShares = marketToRoundToYesReserves[marketId][roundId];
uint256 noShares = marketToRoundToNoReserves[marketId][roundId];
amountIn = amountIn * 997/1000;
if (side == 0) {
amountOut = ((amountIn * yesShares) / (amountIn + noShares)) + amountIn;
} else {
amountOut = ((amountIn * noShares) / (amountIn + yesShares)) + amountIn;
}
}
function getAllAvailableMarkets() external view returns(uint256[] memory) {
return availableMarkets.values();
}
function getAllMarkets() external view returns(uint256[] memory) {
return allMarkets.values();
}
function getBothMarkets() external view returns(uint256[] memory, uint256[] memory) {
return (availableMarkets.values(), allMarkets.values());
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
// This file is auto-generated.
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STRUCTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev An enumerable address set in storage.
struct AddressSet {
uint256 _spacer;
}
/// @dev An enumerable bytes32 set in storage.
struct Bytes32Set {
uint256 _spacer;
}
/// @dev An enumerable uint256 set in storage.
struct Uint256Set {
uint256 _spacer;
}
/// @dev An enumerable int256 set in storage.
struct Int256Set {
uint256 _spacer;
}
/// @dev An enumerable uint8 set in storage. Useful for enums.
struct Uint8Set {
uint256 data;
}
using EnumerableSetLib for AddressSet global;
using EnumerableSetLib for Bytes32Set global;
using EnumerableSetLib for Uint256Set global;
using EnumerableSetLib for Int256Set global;
using EnumerableSetLib for Uint8Set global;
/// @notice Library for managing enumerable sets in storage.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/g/EnumerableSetLib.sol)
///
/// @dev Note:
/// In many applications, the number of elements in an enumerable set is small.
/// This enumerable set implementation avoids storing the length and indices
/// for up to 3 elements. Once the length exceeds 3 for the first time, the length
/// and indices will be initialized. The amortized cost of adding elements is O(1).
///
/// The AddressSet implementation packs the length with the 0th entry.
///
/// All enumerable sets except Uint8Set use a pop and swap mechanism to remove elements.
/// This means that the iteration order of elements can change between element removals.
library EnumerableSetLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The index must be less than the length.
error IndexOutOfBounds();
/// @dev The value cannot be the zero sentinel.
error ValueIsZeroSentinel();
/// @dev Cannot accommodate a new unique value with the capacity.
error ExceedsCapacity();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The index to represent a value that does not exist.
uint256 internal constant NOT_FOUND = type(uint256).max;
/// @dev A sentinel value to denote the zero value in storage.
/// No elements can be equal to this value.
/// `uint72(bytes9(keccak256(bytes("_ZERO_SENTINEL"))))`.
uint256 private constant _ZERO_SENTINEL = 0xfbb67fda52d4bfb8bf;
/// @dev The storage layout is given by:
/// ```
/// mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
/// mstore(0x00, set.slot)
/// let rootSlot := keccak256(0x00, 0x24)
/// mstore(0x20, rootSlot)
/// mstore(0x00, shr(96, shl(96, value)))
/// let positionSlot := keccak256(0x00, 0x40)
/// let valueSlot := add(rootSlot, sload(positionSlot))
/// let valueInStorage := shr(96, sload(valueSlot))
/// let lazyLength := shr(160, shl(160, sload(rootSlot)))
/// ```
uint256 private constant _ENUMERABLE_ADDRESS_SET_SLOT_SEED = 0x978aab92;
/// @dev The storage layout is given by:
/// ```
/// mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
/// mstore(0x00, set.slot)
/// let rootSlot := keccak256(0x00, 0x24)
/// mstore(0x20, rootSlot)
/// mstore(0x00, value)
/// let positionSlot := keccak256(0x00, 0x40)
/// let valueSlot := add(rootSlot, sload(positionSlot))
/// let valueInStorage := sload(valueSlot)
/// let lazyLength := sload(not(rootSlot))
/// ```
uint256 private constant _ENUMERABLE_WORD_SET_SLOT_SEED = 0x18fb5864;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* GETTERS / SETTERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the number of elements in the set.
function length(AddressSet storage set) internal view returns (uint256 result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
let rootPacked := sload(rootSlot)
let n := shr(160, shl(160, rootPacked))
result := shr(1, n)
for {} iszero(or(iszero(shr(96, rootPacked)), n)) {} {
result := 1
if iszero(sload(add(rootSlot, result))) { break }
result := 2
if iszero(sload(add(rootSlot, result))) { break }
result := 3
break
}
}
}
/// @dev Returns the number of elements in the set.
function length(Bytes32Set storage set) internal view returns (uint256 result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
let n := sload(not(rootSlot))
result := shr(1, n)
for {} iszero(n) {} {
result := 0
if iszero(sload(add(rootSlot, result))) { break }
result := 1
if iszero(sload(add(rootSlot, result))) { break }
result := 2
if iszero(sload(add(rootSlot, result))) { break }
result := 3
break
}
}
}
/// @dev Returns the number of elements in the set.
function length(Uint256Set storage set) internal view returns (uint256 result) {
result = length(_toBytes32Set(set));
}
/// @dev Returns the number of elements in the set.
function length(Int256Set storage set) internal view returns (uint256 result) {
result = length(_toBytes32Set(set));
}
/// @dev Returns the number of elements in the set.
function length(Uint8Set storage set) internal view returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
for { let packed := sload(set.slot) } packed { result := add(1, result) } {
packed := xor(packed, and(packed, add(1, not(packed))))
}
}
}
/// @dev Returns whether `value` is in the set.
function contains(AddressSet storage set, address value) internal view returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
value := shr(96, shl(96, value))
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
let rootPacked := sload(rootSlot)
for {} 1 {} {
if iszero(shr(160, shl(160, rootPacked))) {
result := 1
if eq(shr(96, rootPacked), value) { break }
if eq(shr(96, sload(add(rootSlot, 1))), value) { break }
if eq(shr(96, sload(add(rootSlot, 2))), value) { break }
result := 0
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
result := iszero(iszero(sload(keccak256(0x00, 0x40))))
break
}
}
}
/// @dev Returns whether `value` is in the set.
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
for {} 1 {} {
if iszero(sload(not(rootSlot))) {
result := 1
if eq(sload(rootSlot), value) { break }
if eq(sload(add(rootSlot, 1)), value) { break }
if eq(sload(add(rootSlot, 2)), value) { break }
result := 0
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
result := iszero(iszero(sload(keccak256(0x00, 0x40))))
break
}
}
}
/// @dev Returns whether `value` is in the set.
function contains(Uint256Set storage set, uint256 value) internal view returns (bool result) {
result = contains(_toBytes32Set(set), bytes32(value));
}
/// @dev Returns whether `value` is in the set.
function contains(Int256Set storage set, int256 value) internal view returns (bool result) {
result = contains(_toBytes32Set(set), bytes32(uint256(value)));
}
/// @dev Returns whether `value` is in the set.
function contains(Uint8Set storage set, uint8 value) internal view returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := and(1, shr(and(0xff, value), sload(set.slot)))
}
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(AddressSet storage set, address value) internal returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
value := shr(96, shl(96, value))
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
let rootPacked := sload(rootSlot)
for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
mstore(0x20, rootSlot)
if iszero(n) {
let v0 := shr(96, rootPacked)
if iszero(v0) {
sstore(rootSlot, shl(96, value))
result := 1
break
}
if eq(v0, value) { break }
let v1 := shr(96, sload(add(rootSlot, 1)))
if iszero(v1) {
sstore(add(rootSlot, 1), shl(96, value))
result := 1
break
}
if eq(v1, value) { break }
let v2 := shr(96, sload(add(rootSlot, 2)))
if iszero(v2) {
sstore(add(rootSlot, 2), shl(96, value))
result := 1
break
}
if eq(v2, value) { break }
mstore(0x00, v0)
sstore(keccak256(0x00, 0x40), 1)
mstore(0x00, v1)
sstore(keccak256(0x00, 0x40), 2)
mstore(0x00, v2)
sstore(keccak256(0x00, 0x40), 3)
rootPacked := or(rootPacked, 7)
n := 7
}
mstore(0x00, value)
let p := keccak256(0x00, 0x40)
if iszero(sload(p)) {
n := shr(1, n)
result := 1
sstore(p, add(1, n))
if iszero(n) {
sstore(rootSlot, or(3, shl(96, value)))
break
}
sstore(add(rootSlot, n), shl(96, value))
sstore(rootSlot, add(2, rootPacked))
break
}
break
}
}
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
for { let n := sload(not(rootSlot)) } 1 {} {
mstore(0x20, rootSlot)
if iszero(n) {
let v0 := sload(rootSlot)
if iszero(v0) {
sstore(rootSlot, value)
result := 1
break
}
if eq(v0, value) { break }
let v1 := sload(add(rootSlot, 1))
if iszero(v1) {
sstore(add(rootSlot, 1), value)
result := 1
break
}
if eq(v1, value) { break }
let v2 := sload(add(rootSlot, 2))
if iszero(v2) {
sstore(add(rootSlot, 2), value)
result := 1
break
}
if eq(v2, value) { break }
mstore(0x00, v0)
sstore(keccak256(0x00, 0x40), 1)
mstore(0x00, v1)
sstore(keccak256(0x00, 0x40), 2)
mstore(0x00, v2)
sstore(keccak256(0x00, 0x40), 3)
n := 7
}
mstore(0x00, value)
let p := keccak256(0x00, 0x40)
if iszero(sload(p)) {
n := shr(1, n)
sstore(add(rootSlot, n), value)
sstore(p, add(1, n))
sstore(not(rootSlot), or(1, shl(1, add(1, n))))
result := 1
break
}
break
}
}
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(Uint256Set storage set, uint256 value) internal returns (bool result) {
result = add(_toBytes32Set(set), bytes32(value));
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(Int256Set storage set, int256 value) internal returns (bool result) {
result = add(_toBytes32Set(set), bytes32(uint256(value)));
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(Uint8Set storage set, uint8 value) internal returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(set.slot)
let mask := shl(and(0xff, value), 1)
sstore(set.slot, or(result, mask))
result := iszero(and(result, mask))
}
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
/// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
function add(AddressSet storage set, address value, uint256 cap)
internal
returns (bool result)
{
if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
/// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
function add(Bytes32Set storage set, bytes32 value, uint256 cap)
internal
returns (bool result)
{
if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
/// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
function add(Uint256Set storage set, uint256 value, uint256 cap)
internal
returns (bool result)
{
if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
/// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
function add(Int256Set storage set, int256 value, uint256 cap) internal returns (bool result) {
if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
/// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
function add(Uint8Set storage set, uint8 value, uint256 cap) internal returns (bool result) {
if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(AddressSet storage set, address value) internal returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
value := shr(96, shl(96, value))
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
let rootPacked := sload(rootSlot)
for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
if iszero(n) {
result := 1
if eq(shr(96, rootPacked), value) {
sstore(rootSlot, sload(add(rootSlot, 1)))
sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
sstore(add(rootSlot, 2), 0)
break
}
if eq(shr(96, sload(add(rootSlot, 1))), value) {
sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
sstore(add(rootSlot, 2), 0)
break
}
if eq(shr(96, sload(add(rootSlot, 2))), value) {
sstore(add(rootSlot, 2), 0)
break
}
result := 0
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
let p := keccak256(0x00, 0x40)
let position := sload(p)
if iszero(position) { break }
n := sub(shr(1, n), 1)
if iszero(eq(sub(position, 1), n)) {
let lastValue := shr(96, sload(add(rootSlot, n)))
sstore(add(rootSlot, sub(position, 1)), shl(96, lastValue))
mstore(0x00, lastValue)
sstore(keccak256(0x00, 0x40), position)
}
sstore(rootSlot, or(shl(96, shr(96, sload(rootSlot))), or(shl(1, n), 1)))
sstore(p, 0)
result := 1
break
}
}
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
for { let n := sload(not(rootSlot)) } 1 {} {
if iszero(n) {
result := 1
if eq(sload(rootSlot), value) {
sstore(rootSlot, sload(add(rootSlot, 1)))
sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
sstore(add(rootSlot, 2), 0)
break
}
if eq(sload(add(rootSlot, 1)), value) {
sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
sstore(add(rootSlot, 2), 0)
break
}
if eq(sload(add(rootSlot, 2)), value) {
sstore(add(rootSlot, 2), 0)
break
}
result := 0
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
let p := keccak256(0x00, 0x40)
let position := sload(p)
if iszero(position) { break }
n := sub(shr(1, n), 1)
if iszero(eq(sub(position, 1), n)) {
let lastValue := sload(add(rootSlot, n))
sstore(add(rootSlot, sub(position, 1)), lastValue)
mstore(0x00, lastValue)
sstore(keccak256(0x00, 0x40), position)
}
sstore(not(rootSlot), or(shl(1, n), 1))
sstore(p, 0)
result := 1
break
}
}
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(Uint256Set storage set, uint256 value) internal returns (bool result) {
result = remove(_toBytes32Set(set), bytes32(value));
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(Int256Set storage set, int256 value) internal returns (bool result) {
result = remove(_toBytes32Set(set), bytes32(uint256(value)));
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(Uint8Set storage set, uint8 value) internal returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(set.slot)
let mask := shl(and(0xff, value), 1)
sstore(set.slot, and(result, not(mask)))
result := iszero(iszero(and(result, mask)))
}
}
/// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
function update(AddressSet storage set, address value, bool isAdd, uint256 cap)
internal
returns (bool)
{
return isAdd ? add(set, value, cap) : remove(set, value);
}
/// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
function update(Bytes32Set storage set, bytes32 value, bool isAdd, uint256 cap)
internal
returns (bool)
{
return isAdd ? add(set, value, cap) : remove(set, value);
}
/// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
function update(Uint256Set storage set, uint256 value, bool isAdd, uint256 cap)
internal
returns (bool)
{
return isAdd ? add(set, value, cap) : remove(set, value);
}
/// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
function update(Int256Set storage set, int256 value, bool isAdd, uint256 cap)
internal
returns (bool)
{
return isAdd ? add(set, value, cap) : remove(set, value);
}
/// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
function update(Uint8Set storage set, uint8 value, bool isAdd, uint256 cap)
internal
returns (bool)
{
return isAdd ? add(set, value, cap) : remove(set, value);
}
/// @dev Returns all of the values in the set.
/// Note: This can consume more gas than the block gas limit for large sets.
function values(AddressSet storage set) internal view returns (address[] memory result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
let zs := _ZERO_SENTINEL
let rootPacked := sload(rootSlot)
let n := shr(160, shl(160, rootPacked))
result := mload(0x40)
let o := add(0x20, result)
let v := shr(96, rootPacked)
mstore(o, mul(v, iszero(eq(v, zs))))
for {} 1 {} {
if iszero(n) {
if v {
n := 1
v := shr(96, sload(add(rootSlot, n)))
if v {
n := 2
mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
v := shr(96, sload(add(rootSlot, n)))
if v {
n := 3
mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
}
}
}
break
}
n := shr(1, n)
for { let i := 1 } lt(i, n) { i := add(i, 1) } {
v := shr(96, sload(add(rootSlot, i)))
mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
}
break
}
mstore(result, n)
mstore(0x40, add(o, shl(5, n)))
}
}
/// @dev Returns all of the values in the set.
/// Note: This can consume more gas than the block gas limit for large sets.
function values(Bytes32Set storage set) internal view returns (bytes32[] memory result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
let zs := _ZERO_SENTINEL
let n := sload(not(rootSlot))
result := mload(0x40)
let o := add(0x20, result)
for {} 1 {} {
if iszero(n) {
let v := sload(rootSlot)
if v {
n := 1
mstore(o, mul(v, iszero(eq(v, zs))))
v := sload(add(rootSlot, n))
if v {
n := 2
mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
v := sload(add(rootSlot, n))
if v {
n := 3
mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
}
}
}
break
}
n := shr(1, n)
for { let i := 0 } lt(i, n) { i := add(i, 1) } {
let v := sload(add(rootSlot, i))
mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
}
break
}
mstore(result, n)
mstore(0x40, add(o, shl(5, n)))
}
}
/// @dev Returns all of the values in the set.
/// Note: This can consume more gas than the block gas limit for large sets.
function values(Uint256Set storage set) internal view returns (uint256[] memory result) {
result = _toUints(values(_toBytes32Set(set)));
}
/// @dev Returns all of the values in the set.
/// Note: This can consume more gas than the block gas limit for large sets.
function values(Int256Set storage set) internal view returns (int256[] memory result) {
result = _toInts(values(_toBytes32Set(set)));
}
/// @dev Returns all of the values in the set.
function values(Uint8Set storage set) internal view returns (uint8[] memory result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(0x40)
let ptr := add(result, 0x20)
let o := 0
for { let packed := sload(set.slot) } packed {} {
if iszero(and(packed, 0xffff)) {
o := add(o, 16)
packed := shr(16, packed)
continue
}
mstore(ptr, o)
ptr := add(ptr, shl(5, and(packed, 1)))
o := add(o, 1)
packed := shr(1, packed)
}
mstore(result, shr(5, sub(ptr, add(result, 0x20))))
mstore(0x40, ptr)
}
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(AddressSet storage set, uint256 i) internal view returns (address result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
result := shr(96, sload(add(rootSlot, i)))
result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
}
if (i >= length(set)) revert IndexOutOfBounds();
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(Bytes32Set storage set, uint256 i) internal view returns (bytes32 result) {
result = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
result := sload(add(result, i))
result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
}
if (i >= length(set)) revert IndexOutOfBounds();
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(Uint256Set storage set, uint256 i) internal view returns (uint256 result) {
result = uint256(at(_toBytes32Set(set), i));
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(Int256Set storage set, uint256 i) internal view returns (int256 result) {
result = int256(uint256(at(_toBytes32Set(set), i)));
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(Uint8Set storage set, uint256 i) internal view returns (uint8 result) {
/// @solidity memory-safe-assembly
assembly {
let packed := sload(set.slot)
for {} 1 {
mstore(0x00, 0x4e23d035) // `IndexOutOfBounds()`.
revert(0x1c, 0x04)
} {
if iszero(lt(i, 256)) { continue }
for { let j := 0 } iszero(eq(i, j)) {} {
packed := xor(packed, and(packed, add(1, not(packed))))
j := add(j, 1)
}
if iszero(packed) { continue }
break
}
// Find first set subroutine, optimized for smaller bytecode size.
let x := and(packed, add(1, not(packed)))
let r := shl(7, iszero(iszero(shr(128, x))))
r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
// For the lower 5 bits of the result, use a De Bruijn lookup.
// forgefmt: disable-next-item
result := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),
0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
}
}
/// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
function indexOf(AddressSet storage set, address value)
internal
view
returns (uint256 result)
{
result = NOT_FOUND;
if (uint160(value) == _ZERO_SENTINEL) return result;
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
if iszero(value) { value := _ZERO_SENTINEL }
result := not(0)
let rootPacked := sload(rootSlot)
for {} 1 {} {
if iszero(shr(160, shl(160, rootPacked))) {
if eq(shr(96, rootPacked), value) {
result := 0
break
}
if eq(shr(96, sload(add(rootSlot, 1))), value) {
result := 1
break
}
if eq(shr(96, sload(add(rootSlot, 2))), value) {
result := 2
break
}
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
result := sub(sload(keccak256(0x00, 0x40)), 1)
break
}
}
}
/// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
function indexOf(Bytes32Set storage set, bytes32 value)
internal
view
returns (uint256 result)
{
result = NOT_FOUND;
if (uint256(value) == _ZERO_SENTINEL) return result;
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
if iszero(value) { value := _ZERO_SENTINEL }
for {} 1 {} {
if iszero(sload(not(rootSlot))) {
if eq(sload(rootSlot), value) {
result := 0
break
}
if eq(sload(add(rootSlot, 1)), value) {
result := 1
break
}
if eq(sload(add(rootSlot, 2)), value) {
result := 2
break
}
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
result := sub(sload(keccak256(0x00, 0x40)), 1)
break
}
}
}
/// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
function indexOf(Uint256Set storage set, uint256 i) internal view returns (uint256 result) {
result = indexOf(_toBytes32Set(set), bytes32(i));
}
/// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
function indexOf(Int256Set storage set, int256 i) internal view returns (uint256 result) {
result = indexOf(_toBytes32Set(set), bytes32(uint256(i)));
}
/// @dev Returns the index of `value`. Returns `NOT_FOUND` if the value does not exist.
function indexOf(Uint8Set storage set, uint8 value) internal view returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
result := not(0)
let packed := sload(set.slot)
let m := shl(and(0xff, value), 1)
if and(packed, m) {
result := 0
for { let p := and(packed, sub(m, 1)) } p {} {
p := xor(p, and(p, add(1, not(p))))
result := add(result, 1)
}
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PRIVATE HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the root slot.
function _rootSlot(AddressSet storage s) private pure returns (bytes32 r) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
mstore(0x00, s.slot)
r := keccak256(0x00, 0x24)
}
}
/// @dev Returns the root slot.
function _rootSlot(Bytes32Set storage s) private pure returns (bytes32 r) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
mstore(0x00, s.slot)
r := keccak256(0x00, 0x24)
}
}
/// @dev Casts to a Bytes32Set.
function _toBytes32Set(Uint256Set storage s) private pure returns (Bytes32Set storage c) {
/// @solidity memory-safe-assembly
assembly {
c.slot := s.slot
}
}
/// @dev Casts to a Bytes32Set.
function _toBytes32Set(Int256Set storage s) private pure returns (Bytes32Set storage c) {
/// @solidity memory-safe-assembly
assembly {
c.slot := s.slot
}
}
/// @dev Casts to a uint256 array.
function _toUints(bytes32[] memory a) private pure returns (uint256[] memory c) {
/// @solidity memory-safe-assembly
assembly {
c := a
}
}
/// @dev Casts to a int256 array.
function _toInts(bytes32[] memory a) private pure returns (int256[] memory c) {
/// @solidity memory-safe-assembly
assembly {
c := a
}
}
}{
"evmVersion": "cancun",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"project/:solady/=npm/[email protected]/"
]
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256[]","name":"initMarketIds","type":"uint256[]"},{"internalType":"address","name":"_admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidOutput","type":"error"},{"inputs":[],"name":"InvalidReserves","type":"error"},{"inputs":[],"name":"InvalidRound","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"NotAuthorised","type":"error"},{"inputs":[],"name":"OracleError","type":"error"},{"inputs":[],"name":"RoundExpired","type":"error"},{"inputs":[],"name":"RoundNotYetInitialised","type":"error"},{"inputs":[],"name":"RoundResolved","type":"error"},{"inputs":[],"name":"SlippageReached","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"MarketId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"RoundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"User","type":"address"},{"indexed":false,"internalType":"uint256","name":"AmountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"Side","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AmountOut","type":"uint256"}],"name":"MarketEnter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"MarketId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"RoundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"User","type":"address"},{"indexed":false,"internalType":"uint256","name":"AmountInA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AmountInB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AmountOut","type":"uint256"}],"name":"MarketExit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"MarketId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"RoundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"User","type":"address"},{"indexed":false,"internalType":"uint256","name":"Result","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AmountOut","type":"uint256"}],"name":"MarketRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"RoundId","type":"uint256"},{"indexed":true,"internalType":"address","name":"Resolver","type":"address"},{"indexed":false,"internalType":"uint256","name":"Fees","type":"uint256"}],"name":"RoundResolvedBy","type":"event"},{"inputs":[],"name":"checkResolutionStatus","outputs":[{"internalType":"bool","name":"isResolvable","type":"bool"},{"internalType":"uint256","name":"secondsLeft","type":"uint256"},{"internalType":"uint256","name":"currentRoundFees","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentAndFutureRoundInfo","outputs":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"delistingRound","type":"uint256"},{"internalType":"uint256[]","name":"history","type":"uint256[]"}],"internalType":"struct MarketMakerAMM.MarketDataWithHistory[]","name":"marketDataCurrent","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"delistingRound","type":"uint256"},{"internalType":"uint256[]","name":"history","type":"uint256[]"}],"internalType":"struct MarketMakerAMM.MarketDataWithHistory[]","name":"marketDataFuture","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"}],"internalType":"struct MarketMakerAMM.MarketData[]","name":"marketData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"currentSingleMarketRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"}],"internalType":"struct MarketMakerAMM.MarketData","name":"marketData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"delistMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"side","type":"uint256"}],"name":"enterMarket","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minNativeAmountOut","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"amountYes","type":"uint256"},{"internalType":"uint256","name":"amountNo","type":"uint256"},{"internalType":"uint256","name":"toBeExchanged","type":"uint256"}],"name":"exitMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllAvailableMarkets","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllMarkets","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"side","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBothMarkets","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"inputMarketRoundHistory","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"openPrice","type":"uint256"},{"internalType":"uint256","name":"closePrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"}],"internalType":"struct MarketMakerAMM.MarketHistory[]","name":"marketData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"inputRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"}],"internalType":"struct MarketMakerAMM.MarketData[]","name":"marketData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"inputSingleMarketRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"roundStart","type":"uint256"},{"internalType":"uint256","name":"marketTreasury","type":"uint256"},{"internalType":"uint256","name":"yesReserves","type":"uint256"},{"internalType":"uint256","name":"noReserves","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"delistingRound","type":"uint256"},{"internalType":"uint256[]","name":"history","type":"uint256[]"}],"internalType":"struct MarketMakerAMM.MarketDataWithHistory","name":"marketData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"marketToDelistingRound","outputs":[{"internalType":"uint256","name":"delistRound","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"putMarketOnDelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"redeemPendingRoundsPerMarketId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"redeemRoundsPerMarketIdCapped","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"registerMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resolveMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"roundStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"universalRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"updateAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userDataPerCurrentRoundId","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"userDataPerMarketAndCurrentRoundId","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData","name":"userData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"userDataPerMarketIdAndRoundId","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData","name":"userData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"name":"userDataPerMarketIdAndRoundIds","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"userDataPerRoundId","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userToUnclaimedRounds","outputs":[{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"internalType":"struct MarketMakerAMM.UserToRoundsPerMarket[]","name":"roundsPerMarket","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"page","type":"uint256"}],"name":"userUnclaimedRoundsDataPerMarketId","outputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"components":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"result","type":"uint256"},{"internalType":"uint256","name":"outYesReserves","type":"uint256"},{"internalType":"uint256","name":"outNoReserves","type":"uint256"},{"internalType":"uint256","name":"userYesReserves","type":"uint256"},{"internalType":"uint256","name":"userNoReserves","type":"uint256"},{"internalType":"uint256","name":"treasury","type":"uint256"},{"internalType":"uint256","name":"userRedeemed","type":"uint256"}],"internalType":"struct MarketMakerAMM.UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"userUnclaimedRoundsPerMarketId","outputs":[{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"page","type":"uint256"}],"name":"userUnclaimedRoundsPerMarketIdWithPage","outputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256[]","name":"roundIds","type":"uint256[]"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561000f575f5ffd5b506040516161f93803806161f983398181016040528101906100319190610582565b5f825190505f5f90505b81811015610188575f848281518110610057576100566105dc565b5b60200260200101519050610070816101ee60201b60201c565b60095f8381526020019081526020015f205f5f81526020019081526020015f20819055506100a881601261021c60201b90919060201c565b506100bd81601361021c60201b90919060201c565b5068170a0f5040e504000060045f8381526020019081526020015f205f600181526020019081526020015f208190555068170a0f5040e504000060055f8381526020019081526020015f205f600181526020019081526020015f208190555068170a0f5040e504000060045f8381526020019081526020015f205f600281526020019081526020015f208190555068170a0f5040e504000060055f8381526020019081526020015f205f600281526020019081526020015f208190555050808060010191505061003b565b5060025f81548092919061019b90610636565b919050555042600381905550815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505061067d565b5f5f6108079050825f5260205f60205f845afa6102125763b41b6cb15f526004601cfd5b5f51915050919050565b5f61023d61022f8461024560201b60201c565b835f1b61024e60201b60201c565b905092915050565b5f819050919050565b5f5f61025f8461037d60201b60201c565b905068fbb67fda52d4bfb8bf830361027e5763f5a267f15f526004601cfd5b826102905768fbb67fda52d4bfb8bf92505b80195460011561037557816020528061033e578154806102b7578483556001935050610375565b8481036102c45750610375565b6001830154806102df57856001850155600194505050610375565b8581036102ed575050610375565b6002840154806103095786600286015560019550505050610375565b86810361031857505050610375565b825f52600160405f2055815f52600260405f2055805f52600360405f2055600793505050505b835f5260405f208054610373578160011c915084828401558160010181558160010160011b6001178319556001935050610375565b505b505092915050565b5f6318fb5864600452815f5260245f209050919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6103ef826103a9565b810181811067ffffffffffffffff8211171561040e5761040d6103b9565b5b80604052505050565b5f610420610394565b905061042c82826103e6565b919050565b5f67ffffffffffffffff82111561044b5761044a6103b9565b5b602082029050602081019050919050565b5f5ffd5b5f819050919050565b61047281610460565b811461047c575f5ffd5b50565b5f8151905061048d81610469565b92915050565b5f6104a56104a084610431565b610417565b905080838252602082019050602084028301858111156104c8576104c761045c565b5b835b818110156104f157806104dd888261047f565b8452602084019350506020810190506104ca565b5050509392505050565b5f82601f83011261050f5761050e6103a5565b5b815161051f848260208601610493565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61055182610528565b9050919050565b61056181610547565b811461056b575f5ffd5b50565b5f8151905061057c81610558565b92915050565b5f5f604083850312156105985761059761039d565b5b5f83015167ffffffffffffffff8111156105b5576105b46103a1565b5b6105c1858286016104fb565b92505060206105d28582860161056e565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61064082610460565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361067257610671610609565b5b600182019050919050565b615b6f8061068a5f395ff3fe6080604052600436106101f7575f3560e01c80636fd981fe1161010c578063cd1031161161009f578063e512bb601161006e578063e512bb601461076e578063eba83e8d146107aa578063ed9e4ab4146107e6578063edaa019f1461080e578063f22cc0fd14610836576101f7565b8063cd103116146106c7578063d294f093146106f3578063df95b5da14610709578063e2f273bd14610746576101f7565b8063b7445245116100db578063b7445245146105fb578063c2c34cae14610626578063c37524651461064e578063c6b8a8d91461068a576101f7565b80636fd981fe146105555780639af1d35a1461056b578063a624a0dc14610595578063b0772d0b146105d1576101f7565b806340435c081161018f57806357473f0b1161015e57806357473f0b146104515780635769132c1461048d57806357ae4da4146104c95780635c9519e5146104f15780635f71acf41461052d576101f7565b806340435c081461037157806344fd7a49146103ad57806349390388146103d957806352707d8c14610415576101f7565b80632fbdb49a116101cb5780632fbdb49a146102c557806334e9f0ae146102ef5780633f33529e1461032b5780634036585214610347576101f7565b80628f8b35146101fb57806311067eb014610225578063168ffc5f14610261578063193fb23414610289575b5f5ffd5b348015610206575f5ffd5b5061020f610860565b60405161021c9190614a26565b60405180910390f35b348015610230575f5ffd5b5061024b60048036038101906102469190614a81565b610a6d565b6040516102589190614be0565b60405180910390f35b34801561026c575f5ffd5b5061028760048036038101906102829190614a81565b610c5c565b005b348015610294575f5ffd5b506102af60048036038101906102aa9190614c5a565b610ed2565b6040516102bc9190614d40565b60405180910390f35b3480156102d0575f5ffd5b506102d9610f75565b6040516102e69190614d40565b60405180910390f35b3480156102fa575f5ffd5b5061031560048036038101906103109190614d60565b610f86565b6040516103229190614f20565b60405180910390f35b61034560048036038101906103409190614f40565b611212565b005b348015610352575f5ffd5b5061035b6115d9565b6040516103689190614fb3565b60405180910390f35b34801561037c575f5ffd5b506103976004803603810190610392919061511c565b6115df565b6040516103a491906152e6565b60405180910390f35b3480156103b8575f5ffd5b506103c161186d565b6040516103d093929190615320565b60405180910390f35b3480156103e4575f5ffd5b506103ff60048036038101906103fa9190614c5a565b6118da565b60405161040c919061540a565b60405180910390f35b348015610420575f5ffd5b5061043b60048036038101906104369190614f40565b611ac2565b6040516104489190614fb3565b60405180910390f35b34801561045c575f5ffd5b5061047760048036038101906104729190614a81565b611b9d565b6040516104849190614a26565b60405180910390f35b348015610498575f5ffd5b506104b360048036038101906104ae9190614a81565b611dd8565b6040516104c09190614fb3565b60405180910390f35b3480156104d4575f5ffd5b506104ef60048036038101906104ea9190614a81565b611ded565b005b3480156104fc575f5ffd5b5061051760048036038101906105129190615424565b611ee3565b6040516105249190615544565b60405180910390f35b348015610538575f5ffd5b50610553600480360381019061054e9190614a81565b61204c565b005b348015610560575f5ffd5b506105696121b8565b005b348015610576575f5ffd5b5061057f6123df565b60405161058c9190614fb3565b60405180910390f35b3480156105a0575f5ffd5b506105bb60048036038101906105b69190614c5a565b6123e5565b6040516105c891906152e6565b60405180910390f35b3480156105dc575f5ffd5b506105e5612673565b6040516105f29190614d40565b60405180910390f35b348015610606575f5ffd5b5061060f612684565b60405161061d929190615564565b60405180910390f35b348015610631575f5ffd5b5061064c60048036038101906106479190614a81565b6126a3565b005b348015610659575f5ffd5b50610674600480360381019061066f9190615424565b6127dd565b60405161068191906152e6565b60405180910390f35b348015610695575f5ffd5b506106b060048036038101906106ab9190615599565b612a71565b6040516106be9291906155e9565b60405180910390f35b3480156106d2575f5ffd5b506106db612c59565b6040516106ea939291906157e8565b60405180910390f35b3480156106fe575f5ffd5b50610707613137565b005b348015610714575f5ffd5b5061072f600480360381019061072a9190615599565b6131a3565b60405161073d92919061582b565b60405180910390f35b348015610751575f5ffd5b5061076c60048036038101906107679190615424565b613574565b005b348015610779575f5ffd5b50610794600480360381019061078f9190614a81565b61363b565b6040516107a19190615938565b60405180910390f35b3480156107b5575f5ffd5b506107d060048036038101906107cb9190615599565b61379d565b6040516107dd919061540a565b60405180910390f35b3480156107f1575f5ffd5b5061080c60048036038101906108079190614a81565b61397f565b005b348015610819575f5ffd5b50610834600480360381019061082f9190615952565b613bdf565b005b348015610841575f5ffd5b5061084a613f98565b6040516108579190614fb3565b60405180910390f35b60605f61086d6012613f9e565b90508067ffffffffffffffff81111561088957610888614fe0565b5b6040519080825280602002602001820160405280156108c257816020015b6108af614749565b8152602001906001900390816108a75790505b5091505f60025490505f60035490505f5f90505b83811015610a66575f6108f3826012613fb790919063ffffffff16565b90505f6108ff82613fd4565b905060405180610160016040528083815260200186815260200185815260200160065f8581526020019081526020015f205f8881526020019081526020015f2054815260200160045f8581526020019081526020015f205f8881526020019081526020015f2054815260200160055f8581526020019081526020015f205f8881526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8881526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8881526020019081526020015f2054815260200160095f8581526020019081526020015f205f6001896109fc9190615a08565b81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8881526020019081526020015f2054815250878481518110610a4c57610a4b615a3b565b5b6020026020010181905250505080806001019150506108d6565b5050505090565b60605f60025490505f60968211610a9057600182610a8b9190615a08565b610a93565b60965b90505f8183610aa29190615a08565b90508167ffffffffffffffff811115610abe57610abd614fe0565b5b604051908082528060200260200182016040528015610af757816020015b610ae4614798565b815260200190600190039081610adc5790505b5093505f5f90505b82811015610c53576040518060e001604052808781526020018284610b249190615a68565b8152602001600e5f8981526020019081526020015f205f8486610b479190615a68565b81526020019081526020015f20548152602001600f5f8981526020019081526020015f205f8486610b789190615a68565b81526020019081526020015f2054815260200160095f8981526020019081526020015f205f84600187610bab9190615a08565b610bb59190615a68565b81526020019081526020015f2054815260200160095f8981526020019081526020015f205f8486610be69190615a68565b81526020019081526020015f20548152602001600a5f8981526020019081526020015f205f8486610c179190615a68565b81526020019081526020015f2054815250858281518110610c3b57610c3a615a3b565b5b60200260200101819052508080600101915050610aff565b50505050919050565b335f52600b60205260405f20815f528060205260405f20805480825f5260205f206019821115610c8b57601991505b5f5b82811015610e3c57808201545f82840155335f52600d60205260405f209650875f528660205260405f209650805f528660205260405f205f81541115610cda5763646cf5585f526004601cfd5b885f52600a60205260405f209750815f528760205260405f2097505f600189548060018114610d135760028114610d675785875d610db7565b60018555335f52600760205260405f209b508c5f528b60205260405f209b50855f528b60205260405f209b508b5493508c5f52600e60205260405f209b50855f528b60205260405f209b508b549250610db7565b60018555335f52600860205260405f209b508c5f528b60205260405f209b50855f528b60205260405f209b508b5493508c5f52600f60205260405f209b50855f528b60205260405f209b508b5492505b505f84541115610e2c578b5f52600660205260405f209a50845f528a60205260405f209a50818b54840204815f528060205233868e7f3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac483960405fa45f5f5f5f84335af1610e2a576398f736095f526004601cfd5b505b5050505050600181019050610c8d565b508183036019811115610e4e57601990505b8284035f5b82811015610e8c57600181018603840154818501555f815c1115610e8157805c828501555f815d6001820191505b600181019050610e53565b505f8203610ec5575f5b6019811015610ec3575f815c1115610eb857805c828501555f815d6001820191505b600181019050610e96565b505b8086555050505050505050565b6060600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20805480602002602001604051908101604052809291908181526020018280548015610f6857602002820191905f5260205f20905b815481526020019060010190808311610f54575b5050505050905092915050565b6060610f816012614002565b905090565b610f8e6147ce565b5f60035490505f60095f8681526020019081526020015f205f8581526020019081526020015f205490505f5f8214610fc65781610fd0565b610fcf86613fd4565b5b90505f600a8611610fed57600186610fe89190615a08565b610ff0565b600a5b90505f8167ffffffffffffffff81111561100d5761100c614fe0565b5b60405190808252806020026020018201604052801561103b5781602001602082028036833780820191505090505b5090505f5f90505b828110156110af57600a5f8a81526020019081526020015f205f6001838b61106b9190615a08565b6110759190615a08565b81526020019081526020015f205482828151811061109657611095615a3b565b5b6020026020010181815250508080600101915050611043565b50604051806101a0016040528089815260200188815260200186815260200160065f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160045f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160055f8b81526020019081526020015f205f8a81526020019081526020015f20548152602001600e5f8b81526020019081526020015f205f8a81526020019081526020015f20548152602001600f5f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160095f8b81526020019081526020015f205f60018b6111ab9190615a08565b81526020019081526020015f20548152602001848152602001600a5f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160115f8b81526020019081526020015f20548152602001828152509550505050505092915050565b61122683601261402490919063ffffffff16565b61125c576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8581526020019081526020015f20541415801561128e57508160115f8581526020019081526020015f205411155b156112c5576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035460018211156112de5763b4fa3fb35f526004601cfd5b600254845f52600960205260405f20600185035f528060205260405f2090505f81541485831416156113175763a2b52a545f526004601cfd5b81851060018301861117156113335763a2b52a545f526004601cfd5b4261012c840110828614161561135057639e6d804f5f526004601cfd5b61012c83014210600183018614161561137057635b903c715f526004601cfd5b6103e86103e53402048034036103e861025882020460015401600155865f52601060205260405f2092506103e861025882020481038354018355875f52600660205260405f20925082602052865f5260405f209250818354018355335f52600c60205260405f209250875f528260205260405f209250865f528260205260405f2092505f8354036114325760018355335f52600b60205260405f209250875f528260205260405f2092508254600181018455835f5260205f2093508781850155505b875f52600460205260405f20925082602052865f5260405f2092508254885f52600560205260405f2080602052885f5260405f20905080545f890361152557808501838602048c868201101561148f5763a6d7690f5f526004601cfd5b80840387558582018355335f52600760205260405f209650866020528b5f5260405f209650866020528a5f5260405f20965085810187540187558b5f52600e60205260405f209650866020528a5f5260405f2096508581018754018755345f5289602052858101604052338b8d7fafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd960605fa45f5ff35b828501818602048c86820110156115435763a6d7690f5f526004601cfd5b85840187558082038355335f52600860205260405f209650866020528b5f5260405f209650866020528a5f5260405f20965085810187540187558b5f52600f60205260405f209650866020528a5f5260405f2096508581018754018755345f5289602052858101604052338b8d7fafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd960605fa45f5ff35b60035481565b60605f825190508067ffffffffffffffff811115611600576115ff614fe0565b5b60405190808252806020026020018201604052801561163957816020015b61162661482a565b81526020019060019003908161161e5790505b5091505f5f90505b81811015611864575f84828151811061165d5761165c615a3b565b5b60200260200101519050604051806101200160405280878152602001828152602001600a5f8981526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8981526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8981526020019081526020015f205f8481526020019081526020015f2054815260200160075f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f2054815260200160085f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f2054815260200160065f8981526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f205481525084838151811061184b5761184a615a3b565b5b6020026020010181905250508080600101915050611641565b50509392505050565b5f5f5f6102586003546118809190615a68565b42101592506102586003546118959190615a68565b42106118a1575f6118bd565b426102586003546118b29190615a68565b6118bc9190615a08565b5b915060105f60025481526020019081526020015f20549050909192565b6118e261482a565b5f6002549050604051806101200160405280848152602001828152602001600a5f8681526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8481526020019081526020015f2054815260200160075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f2054815260200160085f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f2054815260200160065f8681526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f205481525091505092915050565b5f5f60045f8681526020019081526020015f205f8581526020019081526020015f205490505f60055f8781526020019081526020015f205f8681526020019081526020015f205490506103e86103e588611b1c9190615a9b565b611b269190615b09565b96505f8403611b6357868188611b3c9190615a68565b8389611b489190615a9b565b611b529190615b09565b611b5c9190615a68565b9250611b93565b868288611b709190615a68565b8289611b7c9190615a9b565b611b869190615b09565b611b909190615a68565b92505b5050949350505050565b60605f611baa6012613f9e565b90508067ffffffffffffffff811115611bc657611bc5614fe0565b5b604051908082528060200260200182016040528015611bff57816020015b611bec614749565b815260200190600190039081611be45790505b5091505f60035490505f5f90505b82811015611dd0575f611c2a826012613fb790919063ffffffff16565b90505f60095f8381526020019081526020015f205f8881526020019081526020015f205490505f5f8214611c5e5781611c68565b611c6783613fd4565b5b905060405180610160016040528084815260200189815260200186815260200160065f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160045f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160055f8681526020019081526020015f205f8b81526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8b81526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160095f8681526020019081526020015f205f60018c611d659190615a08565b81526020019081526020015f20548152602001828152602001600a5f8681526020019081526020015f205f8b81526020019081526020015f2054815250878581518110611db557611db4615a3b565b5b60200260200101819052505050508080600101915050611c0d565b505050919050565b6011602052805f5260405f205f915090505481565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e72576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e8681601261402490919063ffffffff16565b611ebc576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005600254611ecb9190615a68565b60115f8381526020019081526020015f208190555050565b60605f611ef06012613f9e565b90508067ffffffffffffffff811115611f0c57611f0b614fe0565b5b604051908082528060200260200182016040528015611f4557816020015b611f3261486d565b815260200190600190039081611f2a5790505b5091505f5f90505b81811015612045575f611f6a826012613fb790919063ffffffff16565b90506040518060400160405280828152602001600b5f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2080548060200260200160405190810160405280929190818152602001828054801561201157602002820191905f5260205f20905b815481526020019060010190808311611ffd575b505050505081525084838151811061202c5761202b615a3b565b5b6020026020010181905250508080600101915050611f4d565b5050919050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146120d1576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8381526020019081526020015f20819055506120fb81601261404190919063ffffffff16565b612131576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61214581601361404190919063ffffffff16565b505f60016002546121569190615a68565b905068170a0f5040e504000060045f8481526020019081526020015f205f8381526020019081526020015f208190555068170a0f5040e504000060055f8481526020019081526020015f205f8381526020019081526020015f20819055505050565b610258600354014210156121d35763b7d094975f526004601cfd5b5f60025490505f6121e46012613f9e565b90505f5f90505b8181101561237a575f612208826012613fb790919063ffffffff16565b90505f61221482613fd4565b9050815f52600a60205260405f20855f528060205260405f205f815411156122435763fd29af2c5f526004601cfd5b835f52600960205260405f209150600187035f528160205260405f2091508154875f5260405f2092508383555f81111561231457845f52600660205260405f20925082602052875f5260405f2092508254818511600181146122ab575f81146122e057612311565b60018455865f52600e60205260405f20945084602052895f5260405f2094505f8554036122db5781600154016001555b612311565b60028455865f52600f60205260405f20945084602052895f5260405f2094505f8554036123105781600154016001555b5b50505b845f52600460205260405f20925082602052600288015f5260405f20925068170a0f5040e50400008355845f52600560205260405f20925082602052600288015f5260405f20925068170a0f5040e50400008355505050505080806001019150506121eb565b506002545f52601060205260405f20805460018401600255426003555f5f5f5f84335af16123af576398f736095f526004601cfd5b805f5233847fa4151f6c29291b1556b1872bc36e5304d55092b1703f6226eefdb53250765c7160205fa350505050565b60015481565b60605f6123f26012613f9e565b90508067ffffffffffffffff81111561240e5761240d614fe0565b5b60405190808252806020026020018201604052801561244757816020015b61243461482a565b81526020019060019003908161242c5790505b5091505f5f90505b8181101561266b575f61246c826012613fb790919063ffffffff16565b9050604051806101200160405280828152602001868152602001600a5f8481526020019081526020015f205f8881526020019081526020015f20548152602001600e5f8481526020019081526020015f205f8881526020019081526020015f20548152602001600f5f8481526020019081526020015f205f8881526020019081526020015f2054815260200160075f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f2054815260200160085f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f2054815260200160065f8481526020019081526020015f205f8881526020019081526020015f20548152602001600d5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f205481525084838151811061265257612651615a3b565b5b602002602001018190525050808060010191505061244f565b505092915050565b606061267f6013614002565b905090565b6060806126916012614002565b61269b6013614002565b915091509091565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612728576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8381526020019081526020015f20541480612759575060025460115f8381526020019081526020015f2054115b15612790576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127a481601261405e90919063ffffffff16565b6127da576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60605f6127ea6012613f9e565b90508067ffffffffffffffff81111561280657612805614fe0565b5b60405190808252806020026020018201604052801561283f57816020015b61282c61482a565b8152602001906001900390816128245790505b5091505f60025490505f5f90505b82811015612a69575f61286a826012613fb790919063ffffffff16565b9050604051806101200160405280828152602001848152602001600a5f8481526020019081526020015f205f8681526020019081526020015f20548152602001600e5f8481526020019081526020015f205f8681526020019081526020015f20548152602001600f5f8481526020019081526020015f205f8681526020019081526020015f2054815260200160075f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815260200160085f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815260200160065f8481526020019081526020015f205f8681526020019081526020015f20548152602001600d5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815250858381518110612a5057612a4f615a3b565b5b602002602001018190525050808060010191505061284d565b505050919050565b5f6060600b5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208054905091505f6101f490505f8185612ad99190615a9b565b9050838110612b34575f67ffffffffffffffff811115612afc57612afb614fe0565b5b604051908082528060200260200182016040528015612b2a5781602001602082028036833780820191505090505b5092505050612c51565b5f8185612b419190615a08565b90505f838210612b515783612b53565b815b90508067ffffffffffffffff811115612b6f57612b6e614fe0565b5b604051908082528060200260200182016040528015612b9d5781602001602082028036833780820191505090505b5094505f5f90505b81811015612c4b57600b5f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8a81526020019081526020015f208185612c059190615a68565b81548110612c1657612c15615a3b565b5b905f5260205f200154868281518110612c3257612c31615a3b565b5b6020026020010181815250508080600101915050612ba5565b50505050505b935093915050565b5f6060805f612c686012613f9e565b905060025493505f600a8511612c8a57600185612c859190615a08565b612c8d565b600a5b90508167ffffffffffffffff811115612ca957612ca8614fe0565b5b604051908082528060200260200182016040528015612ce257816020015b612ccf6147ce565b815260200190600190039081612cc75790505b5093508167ffffffffffffffff811115612cff57612cfe614fe0565b5b604051908082528060200260200182016040528015612d3857816020015b612d256147ce565b815260200190600190039081612d1d5790505b5092505f600186612d499190615a68565b90505f60035490505f5f90505b8481101561312d575f8467ffffffffffffffff811115612d7957612d78614fe0565b5b604051908082528060200260200182016040528015612da75781602001602082028036833780820191505090505b5090505f612dbf836012613fb790919063ffffffff16565b90505f612dcb82613fd4565b90505f5f90505b87811015612e3e57600a5f8481526020019081526020015f205f6001838f612dfa9190615a08565b612e049190615a08565b81526020019081526020015f2054848281518110612e2557612e24615a3b565b5b6020026020010181815250508080600101915050612dd2565b50604051806101a001604052808381526020018c815260200186815260200160065f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160045f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160055f8581526020019081526020015f205f8e81526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8e81526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160095f8581526020019081526020015f205f60018f612f3a9190615a08565b81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160115f8581526020019081526020015f20548152602001848152508a8581518110612fa757612fa6615a3b565b5b6020026020010181905250604051806101a0016040528083815260200187815260200186815260200160065f8581526020019081526020015f205f8981526020019081526020015f2054815260200160045f8581526020019081526020015f205f8981526020019081526020015f2054815260200160055f8581526020019081526020015f205f8981526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8981526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8981526020019081526020015f2054815260200160095f8581526020019081526020015f205f8e81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8981526020019081526020015f2054815260200160115f8581526020019081526020015f205481526020018481525089858151811061310e5761310d615a3b565b5b6020026020010181905250606092505050508080600101915050612d56565b5050505050909192565b5f60015490505f6001819055505f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f193505050506131a0575f5ffd5b50565b5f6060600b5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208054905091505f606490505f818561320a9190615a9b565b9050838110613270575f67ffffffffffffffff81111561322d5761322c614fe0565b5b60405190808252806020026020018201604052801561326657816020015b61325361482a565b81526020019060019003908161324b5790505b509250505061356c565b5f818561327d9190615a08565b90505f83821061328d578361328f565b815b90508067ffffffffffffffff8111156132ab576132aa614fe0565b5b6040519080825280602002602001820160405280156132e457816020015b6132d161482a565b8152602001906001900390816132c95790505b5094505f5f90505b81811015613566575f600b5f8c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8b81526020019081526020015f20828661334d9190615a68565b8154811061335e5761335d615a3b565b5b905f5260205f20015490506040518061012001604052808b8152602001828152602001600a5f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160075f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160085f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160065f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f205481525087838151811061354d5761354c615a3b565b5b60200260200101819052505080806001019150506132ec565b50505050505b935093915050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146135f9576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b613643614749565b5f60025490505f60035490505f61365985613fd4565b905060405180610160016040528086815260200184815260200183815260200160065f8881526020019081526020015f205f8681526020019081526020015f2054815260200160045f8881526020019081526020015f205f8681526020019081526020015f2054815260200160055f8881526020019081526020015f205f8681526020019081526020015f20548152602001600e5f8881526020019081526020015f205f8681526020019081526020015f20548152602001600f5f8881526020019081526020015f205f8681526020019081526020015f2054815260200160095f8881526020019081526020015f205f6001876137569190615a08565b81526020019081526020015f20548152602001828152602001600a5f8881526020019081526020015f205f8681526020019081526020015f20548152509350505050919050565b6137a561482a565b604051806101200160405280848152602001838152602001600a5f8681526020019081526020015f205f8581526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8581526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8581526020019081526020015f2054815260200160075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f2054815260200160085f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f2054815260200160065f8681526020019081526020015f205f8581526020019081526020015f20548152602001600d5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f205481525090509392505050565b335f52600b60205260405f20815f528060205260405f208054815f5260205f205f5b82811015613b5057808201545f82840155335f52600d60205260405f209550865f528560205260405f209550805f528560205260405f205f815411156139ee5763646cf5585f526004601cfd5b875f52600a60205260405f209650815f528660205260405f2096505f600188548060018114613a275760028114613a7b5785875d613acb565b60018555335f52600760205260405f209a508b5f528a60205260405f209a50855f528a60205260405f209a508a5493508b5f52600e60205260405f209a50855f528a60205260405f209a508a549250613acb565b60018555335f52600860205260405f209a508b5f528a60205260405f209a50855f528a60205260405f209a508a5493508b5f52600f60205260405f209a50855f528a60205260405f209a508a5492505b505f84541115613b40578a5f52600660205260405f209950845f528960205260405f209950818a54840204815f528060205233868d7f3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac483960405fa45f5f5f5f84335af1613b3e576398f736095f526004601cfd5b505b50505050506001810190506139a1565b505f5f5f5c1115613b6b575f5c818301555f5f5d6001810190505b5f60015c1115613b875760015c818301555f60015d6001810190505b5f83115f600185035c111615613bad57600183035c818301555f600184035d6001810190505b600183115f600285035c111615613bd457600283035c818301555f600284035d6001810190505b808455505050505050565b613bf385601261402490919063ffffffff16565b613c29576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f821115613c935782841015613c6857613c4582878761407b565b90508183613c539190615a08565b92508084613c619190615a68565b9350613c92565b613c738287876141aa565b90508184613c819190615a08565b93508083613c8f9190615a68565b92505b5b828411613ca05783613ca2565b825b90506002546001810186118187101715613cc35763a2b52a545f526004601cfd5b4261012c60035401108187141615613ce257639e6d804f5f526004601cfd5b5f831160018114613cf9575f8114613e0357613ef1565b875f52600660205260405f2080602052875f5260405f2090508360025c0381555f60025d335f52600760205260405f20905080602052885f5260405f20905080602052875f5260405f2090508360035c1015613d5c57637b9c89165f526004601cfd5b8360035c0381555f60035d335f52600860205260405f20905080602052885f5260405f20905080602052875f5260405f2090508360045c1015613da657637b9c89165f526004601cfd5b8360045c0381555f60045d885f52600e60205260405f20905080602052875f5260405f2090508360055c0381555f60055d885f52600f60205260405f20905080602052875f5260405f2090508360065c0381555f60065d50613ef1565b875f52600660205260405f2080602052875f5260405f209050838154038155335f52600760205260405f20905080602052885f5260405f20905080602052875f5260405f209050805484811015613e6157637b9c89165f526004601cfd5b8481038255335f52600860205260405f20915081602052895f5260405f20915081602052885f5260405f2091508154905084811015613ea757637b9c89165f526004601cfd5b8481038255895f52600e60205260405f20915081602052885f5260405f209150848254038255895f52600f60205260405f20915081602052885f5260405f20915084825403825550505b506103e86103e58302048083036103e861025882020460015401600155875f52601060205260405f206103e8610258830204820381540181558a831015613f3f5763a6d7690f5f526004601cfd5b875f52866020528260405233898b7f4c686a53bc9329e91f0d0d94d821505fd2c0aef3c09a94ea360d98c0dfb9dee460605fa45f5f5f5f86335af1613f8b576398f736095f526004601cfd5b5050505050505050505050565b60025481565b5f613fb0613fab836142d9565b6142e2565b9050919050565b5f613fca613fc4846142d9565b8361432f565b5f1c905092915050565b5f5f6108079050825f5260205f60205f845afa613ff85763b41b6cb15f526004601cfd5b5f51915050919050565b606061401d614018614013846142d9565b614399565b614460565b9050919050565b5f614039614031846142d9565b835f1b61446a565b905092915050565b5f61405661404e846142d9565b835f1b6144f9565b905092915050565b5f61407361406b846142d9565b835f1b614622565b905092915050565b5f825f52600560205260405f20825f528060205260405f20905080548581018255845f52600460205260405f209150835f528160205260405f20915081548187018188020493508381038355855f52600660205260405f20925082602052845f5260405f209250825460025d335f52600760205260405f20925082602052855f5260405f20925082602052845f5260405f2092508383540160035d335f52600860205260405f20925082602052855f5260405f20925082602052845f5260405f20925082548781101561415557637b9c89165f526004601cfd5b87810360045d865f52600e60205260405f20935083602052855f5260405f2093508484540160055d865f52600f60205260405f20935083602052855f5260405f2093508784540360065d505050509392505050565b5f825f52600460205260405f20825f528060205260405f20905080548581018255845f52600560205260405f20915081602052835f5260405f20915081548187018188020493508381038355855f52600660205260405f20925082602052845f5260405f209250825460025d335f52600760205260405f20925082602052855f5260405f20925082602052845f5260405f20925082548781101561425557637b9c89165f526004601cfd5b87810360035d335f52600860205260405f20935083602052865f5260405f20935083602052855f5260405f2093508484540160045d865f52600e60205260405f20935083602052855f5260405f2093508784540360055d865f52600f60205260405f20935083602052855f5260405f2093508484540160065d505050509392505050565b5f819050919050565b5f5f6142ed83614732565b90508019548060011c925080614328575f92508282015415614328576001925082820154156143285760029250828201541561432857600392505b5050919050565b5f61433983614732565b905081810154905068fbb67fda52d4bfb8bf8114158102905061435b836142e2565b8210614393576040517f4e23d03500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b92915050565b60605f6143a583614732565b905068fbb67fda52d4bfb8bf81195460405193508360200160011561444b578161441c5783548015614416576001925083811415810282528285015490508015614415576002925083811415810260208301528285015490508015614414576003925083811415810260408301525b5b5b5061444b565b8160011c91505f5b8281101561444957808501548481141581028260051b84015250600181019050614424565b505b8185528160051b810160405250505050919050565b6060819050919050565b5f5f61447584614732565b905068fbb67fda52d4bfb8bf83036144945763f5a267f15f526004601cfd5b826144a65768fbb67fda52d4bfb8bf92505b6001156144f2578019546144e1576001915082815403156144f25782600182015403156144f25782600282015403156144f2575f91506144f2565b80602052825f5260405f2054151591505b5092915050565b5f5f61450484614732565b905068fbb67fda52d4bfb8bf83036145235763f5a267f15f526004601cfd5b826145355768fbb67fda52d4bfb8bf92505b80195460011561461a5781602052806145e35781548061455c57848355600193505061461a565b848103614569575061461a565b6001830154806145845785600185015560019450505061461a565b85810361459257505061461a565b6002840154806145ae578660028601556001955050505061461a565b8681036145bd5750505061461a565b825f52600160405f2055815f52600260405f2055805f52600360405f2055600793505050505b835f5260405f208054614618578160011c915084828401558160010181558160010160011b600117831955600193505061461a565b505b505092915050565b5f5f61462d84614732565b905068fbb67fda52d4bfb8bf830361464c5763f5a267f15f526004601cfd5b8261465e5768fbb67fda52d4bfb8bf92505b80195460011561472a57806146d35760019250838254036146955760018201548255600282015460018301555f600283015561472a565b836001830154036146b557600282015460018301555f600283015561472a565b836002830154036146cb575f600283015561472a565b5f925061472a565b81602052835f5260405f208054806146ec57505061472a565b60018360011c03925082600182031461471657828401548060018303860155805f528160405f2055505b60018360011b178419555f82556001945050505b505092915050565b5f6318fb5864600452815f5260245f209050919050565b6040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001606081525090565b6040518061012001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b60405180604001604052805f8152602001606081525090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b6148c1816148af565b82525050565b61016082015f8201516148dc5f8501826148b8565b5060208201516148ef60208501826148b8565b50604082015161490260408501826148b8565b50606082015161491560608501826148b8565b50608082015161492860808501826148b8565b5060a082015161493b60a08501826148b8565b5060c082015161494e60c08501826148b8565b5060e082015161496160e08501826148b8565b506101008201516149766101008501826148b8565b5061012082015161498b6101208501826148b8565b506101408201516149a06101408501826148b8565b50505050565b5f6149b183836148c7565b6101608301905092915050565b5f602082019050919050565b5f6149d482614886565b6149de8185614890565b93506149e9836148a0565b805f5b83811015614a19578151614a0088826149a6565b9750614a0b836149be565b9250506001810190506149ec565b5085935050505092915050565b5f6020820190508181035f830152614a3e81846149ca565b905092915050565b5f604051905090565b5f5ffd5b5f5ffd5b614a60816148af565b8114614a6a575f5ffd5b50565b5f81359050614a7b81614a57565b92915050565b5f60208284031215614a9657614a95614a4f565b5b5f614aa384828501614a6d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b60e082015f820151614ae95f8501826148b8565b506020820151614afc60208501826148b8565b506040820151614b0f60408501826148b8565b506060820151614b2260608501826148b8565b506080820151614b3560808501826148b8565b5060a0820151614b4860a08501826148b8565b5060c0820151614b5b60c08501826148b8565b50505050565b5f614b6c8383614ad5565b60e08301905092915050565b5f602082019050919050565b5f614b8e82614aac565b614b988185614ab6565b9350614ba383614ac6565b805f5b83811015614bd3578151614bba8882614b61565b9750614bc583614b78565b925050600181019050614ba6565b5085935050505092915050565b5f6020820190508181035f830152614bf88184614b84565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f614c2982614c00565b9050919050565b614c3981614c1f565b8114614c43575f5ffd5b50565b5f81359050614c5481614c30565b92915050565b5f5f60408385031215614c7057614c6f614a4f565b5b5f614c7d85828601614c46565b9250506020614c8e85828601614a6d565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f614ccc83836148b8565b60208301905092915050565b5f602082019050919050565b5f614cee82614c98565b614cf88185614ca2565b9350614d0383614cb2565b805f5b83811015614d33578151614d1a8882614cc1565b9750614d2583614cd8565b925050600181019050614d06565b5085935050505092915050565b5f6020820190508181035f830152614d588184614ce4565b905092915050565b5f5f60408385031215614d7657614d75614a4f565b5b5f614d8385828601614a6d565b9250506020614d9485828601614a6d565b9150509250929050565b5f82825260208201905092915050565b5f614db882614c98565b614dc28185614d9e565b9350614dcd83614cb2565b805f5b83811015614dfd578151614de48882614cc1565b9750614def83614cd8565b925050600181019050614dd0565b5085935050505092915050565b5f6101a083015f830151614e205f8601826148b8565b506020830151614e3360208601826148b8565b506040830151614e4660408601826148b8565b506060830151614e5960608601826148b8565b506080830151614e6c60808601826148b8565b5060a0830151614e7f60a08601826148b8565b5060c0830151614e9260c08601826148b8565b5060e0830151614ea560e08601826148b8565b50610100830151614eba6101008601826148b8565b50610120830151614ecf6101208601826148b8565b50610140830151614ee46101408601826148b8565b50610160830151614ef96101608601826148b8565b50610180830151848203610180860152614f138282614dae565b9150508091505092915050565b5f6020820190508181035f830152614f388184614e0a565b905092915050565b5f5f5f5f60808587031215614f5857614f57614a4f565b5b5f614f6587828801614a6d565b9450506020614f7687828801614a6d565b9350506040614f8787828801614a6d565b9250506060614f9887828801614a6d565b91505092959194509250565b614fad816148af565b82525050565b5f602082019050614fc65f830184614fa4565b92915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61501682614fd0565b810181811067ffffffffffffffff8211171561503557615034614fe0565b5b80604052505050565b5f615047614a46565b9050615053828261500d565b919050565b5f67ffffffffffffffff82111561507257615071614fe0565b5b602082029050602081019050919050565b5f5ffd5b5f61509961509484615058565b61503e565b905080838252602082019050602084028301858111156150bc576150bb615083565b5b835b818110156150e557806150d18882614a6d565b8452602084019350506020810190506150be565b5050509392505050565b5f82601f83011261510357615102614fcc565b5b8135615113848260208601615087565b91505092915050565b5f5f5f6060848603121561513357615132614a4f565b5b5f61514086828701614c46565b935050602061515186828701614a6d565b925050604084013567ffffffffffffffff81111561517257615171614a53565b5b61517e868287016150ef565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61012082015f8201516151c65f8501826148b8565b5060208201516151d960208501826148b8565b5060408201516151ec60408501826148b8565b5060608201516151ff60608501826148b8565b50608082015161521260808501826148b8565b5060a082015161522560a08501826148b8565b5060c082015161523860c08501826148b8565b5060e082015161524b60e08501826148b8565b506101008201516152606101008501826148b8565b50505050565b5f61527183836151b1565b6101208301905092915050565b5f602082019050919050565b5f61529482615188565b61529e8185615192565b93506152a9836151a2565b805f5b838110156152d95781516152c08882615266565b97506152cb8361527e565b9250506001810190506152ac565b5085935050505092915050565b5f6020820190508181035f8301526152fe818461528a565b905092915050565b5f8115159050919050565b61531a81615306565b82525050565b5f6060820190506153335f830186615311565b6153406020830185614fa4565b61534d6040830184614fa4565b949350505050565b61012082015f82015161536a5f8501826148b8565b50602082015161537d60208501826148b8565b50604082015161539060408501826148b8565b5060608201516153a360608501826148b8565b5060808201516153b660808501826148b8565b5060a08201516153c960a08501826148b8565b5060c08201516153dc60c08501826148b8565b5060e08201516153ef60e08501826148b8565b506101008201516154046101008501826148b8565b50505050565b5f6101208201905061541e5f830184615355565b92915050565b5f6020828403121561543957615438614a4f565b5b5f61544684828501614c46565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f604083015f83015161548d5f8601826148b8565b50602083015184820360208601526154a58282614dae565b9150508091505092915050565b5f6154bd8383615478565b905092915050565b5f602082019050919050565b5f6154db8261544f565b6154e58185615459565b9350836020820285016154f785615469565b805f5b85811015615532578484038952815161551385826154b2565b945061551e836154c5565b925060208a019950506001810190506154fa565b50829750879550505050505092915050565b5f6020820190508181035f83015261555c81846154d1565b905092915050565b5f6040820190508181035f83015261557c8185614ce4565b905081810360208301526155908184614ce4565b90509392505050565b5f5f5f606084860312156155b0576155af614a4f565b5b5f6155bd86828701614c46565b93505060206155ce86828701614a6d565b92505060406155df86828701614a6d565b9150509250925092565b5f6040820190506155fc5f830185614fa4565b818103602083015261560e8184614ce4565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f6101a083015f8301516156565f8601826148b8565b50602083015161566960208601826148b8565b50604083015161567c60408601826148b8565b50606083015161568f60608601826148b8565b5060808301516156a260808601826148b8565b5060a08301516156b560a08601826148b8565b5060c08301516156c860c08601826148b8565b5060e08301516156db60e08601826148b8565b506101008301516156f06101008601826148b8565b506101208301516157056101208601826148b8565b5061014083015161571a6101408601826148b8565b5061016083015161572f6101608601826148b8565b506101808301518482036101808601526157498282614dae565b9150508091505092915050565b5f6157618383615640565b905092915050565b5f602082019050919050565b5f61577f82615617565b6157898185615621565b93508360208202850161579b85615631565b805f5b858110156157d657848403895281516157b78582615756565b94506157c283615769565b925060208a0199505060018101905061579e565b50829750879550505050505092915050565b5f6060820190506157fb5f830186614fa4565b818103602083015261580d8185615775565b905081810360408301526158218184615775565b9050949350505050565b5f60408201905061583e5f830185614fa4565b8181036020830152615850818461528a565b90509392505050565b61016082015f82015161586e5f8501826148b8565b50602082015161588160208501826148b8565b50604082015161589460408501826148b8565b5060608201516158a760608501826148b8565b5060808201516158ba60808501826148b8565b5060a08201516158cd60a08501826148b8565b5060c08201516158e060c08501826148b8565b5060e08201516158f360e08501826148b8565b506101008201516159086101008501826148b8565b5061012082015161591d6101208501826148b8565b506101408201516159326101408501826148b8565b50505050565b5f6101608201905061594c5f830184615859565b92915050565b5f5f5f5f5f5f60c0878903121561596c5761596b614a4f565b5b5f61597989828a01614a6d565b965050602061598a89828a01614a6d565b955050604061599b89828a01614a6d565b94505060606159ac89828a01614a6d565b93505060806159bd89828a01614a6d565b92505060a06159ce89828a01614a6d565b9150509295509295509295565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f615a12826148af565b9150615a1d836148af565b9250828203905081811115615a3557615a346159db565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f615a72826148af565b9150615a7d836148af565b9250828201905080821115615a9557615a946159db565b5b92915050565b5f615aa5826148af565b9150615ab0836148af565b9250828202615abe816148af565b91508282048414831517615ad557615ad46159db565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f615b13826148af565b9150615b1e836148af565b925082615b2e57615b2d615adc565b5b82820490509291505056fea2646970667358221220137ad95f047d8f6117acaa283c77bac9e6c7dfbcf68da0151429aa2025d06b5164736f6c634300081c003300000000000000000000000000000000000000000000000000000000000000400000000000000000000000002a007eb889ddf2be3f3bda225734c1873bf1ea420000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000009f
Deployed Bytecode
0x6080604052600436106101f7575f3560e01c80636fd981fe1161010c578063cd1031161161009f578063e512bb601161006e578063e512bb601461076e578063eba83e8d146107aa578063ed9e4ab4146107e6578063edaa019f1461080e578063f22cc0fd14610836576101f7565b8063cd103116146106c7578063d294f093146106f3578063df95b5da14610709578063e2f273bd14610746576101f7565b8063b7445245116100db578063b7445245146105fb578063c2c34cae14610626578063c37524651461064e578063c6b8a8d91461068a576101f7565b80636fd981fe146105555780639af1d35a1461056b578063a624a0dc14610595578063b0772d0b146105d1576101f7565b806340435c081161018f57806357473f0b1161015e57806357473f0b146104515780635769132c1461048d57806357ae4da4146104c95780635c9519e5146104f15780635f71acf41461052d576101f7565b806340435c081461037157806344fd7a49146103ad57806349390388146103d957806352707d8c14610415576101f7565b80632fbdb49a116101cb5780632fbdb49a146102c557806334e9f0ae146102ef5780633f33529e1461032b5780634036585214610347576101f7565b80628f8b35146101fb57806311067eb014610225578063168ffc5f14610261578063193fb23414610289575b5f5ffd5b348015610206575f5ffd5b5061020f610860565b60405161021c9190614a26565b60405180910390f35b348015610230575f5ffd5b5061024b60048036038101906102469190614a81565b610a6d565b6040516102589190614be0565b60405180910390f35b34801561026c575f5ffd5b5061028760048036038101906102829190614a81565b610c5c565b005b348015610294575f5ffd5b506102af60048036038101906102aa9190614c5a565b610ed2565b6040516102bc9190614d40565b60405180910390f35b3480156102d0575f5ffd5b506102d9610f75565b6040516102e69190614d40565b60405180910390f35b3480156102fa575f5ffd5b5061031560048036038101906103109190614d60565b610f86565b6040516103229190614f20565b60405180910390f35b61034560048036038101906103409190614f40565b611212565b005b348015610352575f5ffd5b5061035b6115d9565b6040516103689190614fb3565b60405180910390f35b34801561037c575f5ffd5b506103976004803603810190610392919061511c565b6115df565b6040516103a491906152e6565b60405180910390f35b3480156103b8575f5ffd5b506103c161186d565b6040516103d093929190615320565b60405180910390f35b3480156103e4575f5ffd5b506103ff60048036038101906103fa9190614c5a565b6118da565b60405161040c919061540a565b60405180910390f35b348015610420575f5ffd5b5061043b60048036038101906104369190614f40565b611ac2565b6040516104489190614fb3565b60405180910390f35b34801561045c575f5ffd5b5061047760048036038101906104729190614a81565b611b9d565b6040516104849190614a26565b60405180910390f35b348015610498575f5ffd5b506104b360048036038101906104ae9190614a81565b611dd8565b6040516104c09190614fb3565b60405180910390f35b3480156104d4575f5ffd5b506104ef60048036038101906104ea9190614a81565b611ded565b005b3480156104fc575f5ffd5b5061051760048036038101906105129190615424565b611ee3565b6040516105249190615544565b60405180910390f35b348015610538575f5ffd5b50610553600480360381019061054e9190614a81565b61204c565b005b348015610560575f5ffd5b506105696121b8565b005b348015610576575f5ffd5b5061057f6123df565b60405161058c9190614fb3565b60405180910390f35b3480156105a0575f5ffd5b506105bb60048036038101906105b69190614c5a565b6123e5565b6040516105c891906152e6565b60405180910390f35b3480156105dc575f5ffd5b506105e5612673565b6040516105f29190614d40565b60405180910390f35b348015610606575f5ffd5b5061060f612684565b60405161061d929190615564565b60405180910390f35b348015610631575f5ffd5b5061064c60048036038101906106479190614a81565b6126a3565b005b348015610659575f5ffd5b50610674600480360381019061066f9190615424565b6127dd565b60405161068191906152e6565b60405180910390f35b348015610695575f5ffd5b506106b060048036038101906106ab9190615599565b612a71565b6040516106be9291906155e9565b60405180910390f35b3480156106d2575f5ffd5b506106db612c59565b6040516106ea939291906157e8565b60405180910390f35b3480156106fe575f5ffd5b50610707613137565b005b348015610714575f5ffd5b5061072f600480360381019061072a9190615599565b6131a3565b60405161073d92919061582b565b60405180910390f35b348015610751575f5ffd5b5061076c60048036038101906107679190615424565b613574565b005b348015610779575f5ffd5b50610794600480360381019061078f9190614a81565b61363b565b6040516107a19190615938565b60405180910390f35b3480156107b5575f5ffd5b506107d060048036038101906107cb9190615599565b61379d565b6040516107dd919061540a565b60405180910390f35b3480156107f1575f5ffd5b5061080c60048036038101906108079190614a81565b61397f565b005b348015610819575f5ffd5b50610834600480360381019061082f9190615952565b613bdf565b005b348015610841575f5ffd5b5061084a613f98565b6040516108579190614fb3565b60405180910390f35b60605f61086d6012613f9e565b90508067ffffffffffffffff81111561088957610888614fe0565b5b6040519080825280602002602001820160405280156108c257816020015b6108af614749565b8152602001906001900390816108a75790505b5091505f60025490505f60035490505f5f90505b83811015610a66575f6108f3826012613fb790919063ffffffff16565b90505f6108ff82613fd4565b905060405180610160016040528083815260200186815260200185815260200160065f8581526020019081526020015f205f8881526020019081526020015f2054815260200160045f8581526020019081526020015f205f8881526020019081526020015f2054815260200160055f8581526020019081526020015f205f8881526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8881526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8881526020019081526020015f2054815260200160095f8581526020019081526020015f205f6001896109fc9190615a08565b81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8881526020019081526020015f2054815250878481518110610a4c57610a4b615a3b565b5b6020026020010181905250505080806001019150506108d6565b5050505090565b60605f60025490505f60968211610a9057600182610a8b9190615a08565b610a93565b60965b90505f8183610aa29190615a08565b90508167ffffffffffffffff811115610abe57610abd614fe0565b5b604051908082528060200260200182016040528015610af757816020015b610ae4614798565b815260200190600190039081610adc5790505b5093505f5f90505b82811015610c53576040518060e001604052808781526020018284610b249190615a68565b8152602001600e5f8981526020019081526020015f205f8486610b479190615a68565b81526020019081526020015f20548152602001600f5f8981526020019081526020015f205f8486610b789190615a68565b81526020019081526020015f2054815260200160095f8981526020019081526020015f205f84600187610bab9190615a08565b610bb59190615a68565b81526020019081526020015f2054815260200160095f8981526020019081526020015f205f8486610be69190615a68565b81526020019081526020015f20548152602001600a5f8981526020019081526020015f205f8486610c179190615a68565b81526020019081526020015f2054815250858281518110610c3b57610c3a615a3b565b5b60200260200101819052508080600101915050610aff565b50505050919050565b335f52600b60205260405f20815f528060205260405f20805480825f5260205f206019821115610c8b57601991505b5f5b82811015610e3c57808201545f82840155335f52600d60205260405f209650875f528660205260405f209650805f528660205260405f205f81541115610cda5763646cf5585f526004601cfd5b885f52600a60205260405f209750815f528760205260405f2097505f600189548060018114610d135760028114610d675785875d610db7565b60018555335f52600760205260405f209b508c5f528b60205260405f209b50855f528b60205260405f209b508b5493508c5f52600e60205260405f209b50855f528b60205260405f209b508b549250610db7565b60018555335f52600860205260405f209b508c5f528b60205260405f209b50855f528b60205260405f209b508b5493508c5f52600f60205260405f209b50855f528b60205260405f209b508b5492505b505f84541115610e2c578b5f52600660205260405f209a50845f528a60205260405f209a50818b54840204815f528060205233868e7f3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac483960405fa45f5f5f5f84335af1610e2a576398f736095f526004601cfd5b505b5050505050600181019050610c8d565b508183036019811115610e4e57601990505b8284035f5b82811015610e8c57600181018603840154818501555f815c1115610e8157805c828501555f815d6001820191505b600181019050610e53565b505f8203610ec5575f5b6019811015610ec3575f815c1115610eb857805c828501555f815d6001820191505b600181019050610e96565b505b8086555050505050505050565b6060600b5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f20805480602002602001604051908101604052809291908181526020018280548015610f6857602002820191905f5260205f20905b815481526020019060010190808311610f54575b5050505050905092915050565b6060610f816012614002565b905090565b610f8e6147ce565b5f60035490505f60095f8681526020019081526020015f205f8581526020019081526020015f205490505f5f8214610fc65781610fd0565b610fcf86613fd4565b5b90505f600a8611610fed57600186610fe89190615a08565b610ff0565b600a5b90505f8167ffffffffffffffff81111561100d5761100c614fe0565b5b60405190808252806020026020018201604052801561103b5781602001602082028036833780820191505090505b5090505f5f90505b828110156110af57600a5f8a81526020019081526020015f205f6001838b61106b9190615a08565b6110759190615a08565b81526020019081526020015f205482828151811061109657611095615a3b565b5b6020026020010181815250508080600101915050611043565b50604051806101a0016040528089815260200188815260200186815260200160065f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160045f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160055f8b81526020019081526020015f205f8a81526020019081526020015f20548152602001600e5f8b81526020019081526020015f205f8a81526020019081526020015f20548152602001600f5f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160095f8b81526020019081526020015f205f60018b6111ab9190615a08565b81526020019081526020015f20548152602001848152602001600a5f8b81526020019081526020015f205f8a81526020019081526020015f2054815260200160115f8b81526020019081526020015f20548152602001828152509550505050505092915050565b61122683601261402490919063ffffffff16565b61125c576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8581526020019081526020015f20541415801561128e57508160115f8581526020019081526020015f205411155b156112c5576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035460018211156112de5763b4fa3fb35f526004601cfd5b600254845f52600960205260405f20600185035f528060205260405f2090505f81541485831416156113175763a2b52a545f526004601cfd5b81851060018301861117156113335763a2b52a545f526004601cfd5b4261012c840110828614161561135057639e6d804f5f526004601cfd5b61012c83014210600183018614161561137057635b903c715f526004601cfd5b6103e86103e53402048034036103e861025882020460015401600155865f52601060205260405f2092506103e861025882020481038354018355875f52600660205260405f20925082602052865f5260405f209250818354018355335f52600c60205260405f209250875f528260205260405f209250865f528260205260405f2092505f8354036114325760018355335f52600b60205260405f209250875f528260205260405f2092508254600181018455835f5260205f2093508781850155505b875f52600460205260405f20925082602052865f5260405f2092508254885f52600560205260405f2080602052885f5260405f20905080545f890361152557808501838602048c868201101561148f5763a6d7690f5f526004601cfd5b80840387558582018355335f52600760205260405f209650866020528b5f5260405f209650866020528a5f5260405f20965085810187540187558b5f52600e60205260405f209650866020528a5f5260405f2096508581018754018755345f5289602052858101604052338b8d7fafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd960605fa45f5ff35b828501818602048c86820110156115435763a6d7690f5f526004601cfd5b85840187558082038355335f52600860205260405f209650866020528b5f5260405f209650866020528a5f5260405f20965085810187540187558b5f52600f60205260405f209650866020528a5f5260405f2096508581018754018755345f5289602052858101604052338b8d7fafdcf9101f4dab5c3b6e53a3ec30d3e897f17b974edceb117d3c12d2d83b0fd960605fa45f5ff35b60035481565b60605f825190508067ffffffffffffffff811115611600576115ff614fe0565b5b60405190808252806020026020018201604052801561163957816020015b61162661482a565b81526020019060019003908161161e5790505b5091505f5f90505b81811015611864575f84828151811061165d5761165c615a3b565b5b60200260200101519050604051806101200160405280878152602001828152602001600a5f8981526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8981526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8981526020019081526020015f205f8481526020019081526020015f2054815260200160075f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f2054815260200160085f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f2054815260200160065f8981526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8981526020019081526020015f205f8481526020019081526020015f205481525084838151811061184b5761184a615a3b565b5b6020026020010181905250508080600101915050611641565b50509392505050565b5f5f5f6102586003546118809190615a68565b42101592506102586003546118959190615a68565b42106118a1575f6118bd565b426102586003546118b29190615a68565b6118bc9190615a08565b5b915060105f60025481526020019081526020015f20549050909192565b6118e261482a565b5f6002549050604051806101200160405280848152602001828152602001600a5f8681526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8481526020019081526020015f2054815260200160075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f2054815260200160085f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f2054815260200160065f8681526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8481526020019081526020015f205481525091505092915050565b5f5f60045f8681526020019081526020015f205f8581526020019081526020015f205490505f60055f8781526020019081526020015f205f8681526020019081526020015f205490506103e86103e588611b1c9190615a9b565b611b269190615b09565b96505f8403611b6357868188611b3c9190615a68565b8389611b489190615a9b565b611b529190615b09565b611b5c9190615a68565b9250611b93565b868288611b709190615a68565b8289611b7c9190615a9b565b611b869190615b09565b611b909190615a68565b92505b5050949350505050565b60605f611baa6012613f9e565b90508067ffffffffffffffff811115611bc657611bc5614fe0565b5b604051908082528060200260200182016040528015611bff57816020015b611bec614749565b815260200190600190039081611be45790505b5091505f60035490505f5f90505b82811015611dd0575f611c2a826012613fb790919063ffffffff16565b90505f60095f8381526020019081526020015f205f8881526020019081526020015f205490505f5f8214611c5e5781611c68565b611c6783613fd4565b5b905060405180610160016040528084815260200189815260200186815260200160065f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160045f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160055f8681526020019081526020015f205f8b81526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8b81526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8b81526020019081526020015f2054815260200160095f8681526020019081526020015f205f60018c611d659190615a08565b81526020019081526020015f20548152602001828152602001600a5f8681526020019081526020015f205f8b81526020019081526020015f2054815250878581518110611db557611db4615a3b565b5b60200260200101819052505050508080600101915050611c0d565b505050919050565b6011602052805f5260405f205f915090505481565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e72576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e8681601261402490919063ffffffff16565b611ebc576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005600254611ecb9190615a68565b60115f8381526020019081526020015f208190555050565b60605f611ef06012613f9e565b90508067ffffffffffffffff811115611f0c57611f0b614fe0565b5b604051908082528060200260200182016040528015611f4557816020015b611f3261486d565b815260200190600190039081611f2a5790505b5091505f5f90505b81811015612045575f611f6a826012613fb790919063ffffffff16565b90506040518060400160405280828152602001600b5f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2080548060200260200160405190810160405280929190818152602001828054801561201157602002820191905f5260205f20905b815481526020019060010190808311611ffd575b505050505081525084838151811061202c5761202b615a3b565b5b6020026020010181905250508080600101915050611f4d565b5050919050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146120d1576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8381526020019081526020015f20819055506120fb81601261404190919063ffffffff16565b612131576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61214581601361404190919063ffffffff16565b505f60016002546121569190615a68565b905068170a0f5040e504000060045f8481526020019081526020015f205f8381526020019081526020015f208190555068170a0f5040e504000060055f8481526020019081526020015f205f8381526020019081526020015f20819055505050565b610258600354014210156121d35763b7d094975f526004601cfd5b5f60025490505f6121e46012613f9e565b90505f5f90505b8181101561237a575f612208826012613fb790919063ffffffff16565b90505f61221482613fd4565b9050815f52600a60205260405f20855f528060205260405f205f815411156122435763fd29af2c5f526004601cfd5b835f52600960205260405f209150600187035f528160205260405f2091508154875f5260405f2092508383555f81111561231457845f52600660205260405f20925082602052875f5260405f2092508254818511600181146122ab575f81146122e057612311565b60018455865f52600e60205260405f20945084602052895f5260405f2094505f8554036122db5781600154016001555b612311565b60028455865f52600f60205260405f20945084602052895f5260405f2094505f8554036123105781600154016001555b5b50505b845f52600460205260405f20925082602052600288015f5260405f20925068170a0f5040e50400008355845f52600560205260405f20925082602052600288015f5260405f20925068170a0f5040e50400008355505050505080806001019150506121eb565b506002545f52601060205260405f20805460018401600255426003555f5f5f5f84335af16123af576398f736095f526004601cfd5b805f5233847fa4151f6c29291b1556b1872bc36e5304d55092b1703f6226eefdb53250765c7160205fa350505050565b60015481565b60605f6123f26012613f9e565b90508067ffffffffffffffff81111561240e5761240d614fe0565b5b60405190808252806020026020018201604052801561244757816020015b61243461482a565b81526020019060019003908161242c5790505b5091505f5f90505b8181101561266b575f61246c826012613fb790919063ffffffff16565b9050604051806101200160405280828152602001868152602001600a5f8481526020019081526020015f205f8881526020019081526020015f20548152602001600e5f8481526020019081526020015f205f8881526020019081526020015f20548152602001600f5f8481526020019081526020015f205f8881526020019081526020015f2054815260200160075f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f2054815260200160085f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f2054815260200160065f8481526020019081526020015f205f8881526020019081526020015f20548152602001600d5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8881526020019081526020015f205481525084838151811061265257612651615a3b565b5b602002602001018190525050808060010191505061244f565b505092915050565b606061267f6013614002565b905090565b6060806126916012614002565b61269b6013614002565b915091509091565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612728576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60115f8381526020019081526020015f20541480612759575060025460115f8381526020019081526020015f2054115b15612790576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127a481601261405e90919063ffffffff16565b6127da576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60605f6127ea6012613f9e565b90508067ffffffffffffffff81111561280657612805614fe0565b5b60405190808252806020026020018201604052801561283f57816020015b61282c61482a565b8152602001906001900390816128245790505b5091505f60025490505f5f90505b82811015612a69575f61286a826012613fb790919063ffffffff16565b9050604051806101200160405280828152602001848152602001600a5f8481526020019081526020015f205f8681526020019081526020015f20548152602001600e5f8481526020019081526020015f205f8681526020019081526020015f20548152602001600f5f8481526020019081526020015f205f8681526020019081526020015f2054815260200160075f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815260200160085f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815260200160065f8481526020019081526020015f205f8681526020019081526020015f20548152602001600d5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f8681526020019081526020015f2054815250858381518110612a5057612a4f615a3b565b5b602002602001018190525050808060010191505061284d565b505050919050565b5f6060600b5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208054905091505f6101f490505f8185612ad99190615a9b565b9050838110612b34575f67ffffffffffffffff811115612afc57612afb614fe0565b5b604051908082528060200260200182016040528015612b2a5781602001602082028036833780820191505090505b5092505050612c51565b5f8185612b419190615a08565b90505f838210612b515783612b53565b815b90508067ffffffffffffffff811115612b6f57612b6e614fe0565b5b604051908082528060200260200182016040528015612b9d5781602001602082028036833780820191505090505b5094505f5f90505b81811015612c4b57600b5f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8a81526020019081526020015f208185612c059190615a68565b81548110612c1657612c15615a3b565b5b905f5260205f200154868281518110612c3257612c31615a3b565b5b6020026020010181815250508080600101915050612ba5565b50505050505b935093915050565b5f6060805f612c686012613f9e565b905060025493505f600a8511612c8a57600185612c859190615a08565b612c8d565b600a5b90508167ffffffffffffffff811115612ca957612ca8614fe0565b5b604051908082528060200260200182016040528015612ce257816020015b612ccf6147ce565b815260200190600190039081612cc75790505b5093508167ffffffffffffffff811115612cff57612cfe614fe0565b5b604051908082528060200260200182016040528015612d3857816020015b612d256147ce565b815260200190600190039081612d1d5790505b5092505f600186612d499190615a68565b90505f60035490505f5f90505b8481101561312d575f8467ffffffffffffffff811115612d7957612d78614fe0565b5b604051908082528060200260200182016040528015612da75781602001602082028036833780820191505090505b5090505f612dbf836012613fb790919063ffffffff16565b90505f612dcb82613fd4565b90505f5f90505b87811015612e3e57600a5f8481526020019081526020015f205f6001838f612dfa9190615a08565b612e049190615a08565b81526020019081526020015f2054848281518110612e2557612e24615a3b565b5b6020026020010181815250508080600101915050612dd2565b50604051806101a001604052808381526020018c815260200186815260200160065f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160045f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160055f8581526020019081526020015f205f8e81526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8e81526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160095f8581526020019081526020015f205f60018f612f3a9190615a08565b81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8e81526020019081526020015f2054815260200160115f8581526020019081526020015f20548152602001848152508a8581518110612fa757612fa6615a3b565b5b6020026020010181905250604051806101a0016040528083815260200187815260200186815260200160065f8581526020019081526020015f205f8981526020019081526020015f2054815260200160045f8581526020019081526020015f205f8981526020019081526020015f2054815260200160055f8581526020019081526020015f205f8981526020019081526020015f20548152602001600e5f8581526020019081526020015f205f8981526020019081526020015f20548152602001600f5f8581526020019081526020015f205f8981526020019081526020015f2054815260200160095f8581526020019081526020015f205f8e81526020019081526020015f20548152602001828152602001600a5f8581526020019081526020015f205f8981526020019081526020015f2054815260200160115f8581526020019081526020015f205481526020018481525089858151811061310e5761310d615a3b565b5b6020026020010181905250606092505050508080600101915050612d56565b5050505050909192565b5f60015490505f6001819055505f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f193505050506131a0575f5ffd5b50565b5f6060600b5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208054905091505f606490505f818561320a9190615a9b565b9050838110613270575f67ffffffffffffffff81111561322d5761322c614fe0565b5b60405190808252806020026020018201604052801561326657816020015b61325361482a565b81526020019060019003908161324b5790505b509250505061356c565b5f818561327d9190615a08565b90505f83821061328d578361328f565b815b90508067ffffffffffffffff8111156132ab576132aa614fe0565b5b6040519080825280602002602001820160405280156132e457816020015b6132d161482a565b8152602001906001900390816132c95790505b5094505f5f90505b81811015613566575f600b5f8c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8b81526020019081526020015f20828661334d9190615a68565b8154811061335e5761335d615a3b565b5b905f5260205f20015490506040518061012001604052808b8152602001828152602001600a5f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600e5f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600f5f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160075f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160085f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f2054815260200160065f8d81526020019081526020015f205f8481526020019081526020015f20548152602001600d5f8e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8d81526020019081526020015f205f8481526020019081526020015f205481525087838151811061354d5761354c615a3b565b5b60200260200101819052505080806001019150506132ec565b50505050505b935093915050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146135f9576040517f1648fd0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b613643614749565b5f60025490505f60035490505f61365985613fd4565b905060405180610160016040528086815260200184815260200183815260200160065f8881526020019081526020015f205f8681526020019081526020015f2054815260200160045f8881526020019081526020015f205f8681526020019081526020015f2054815260200160055f8881526020019081526020015f205f8681526020019081526020015f20548152602001600e5f8881526020019081526020015f205f8681526020019081526020015f20548152602001600f5f8881526020019081526020015f205f8681526020019081526020015f2054815260200160095f8881526020019081526020015f205f6001876137569190615a08565b81526020019081526020015f20548152602001828152602001600a5f8881526020019081526020015f205f8681526020019081526020015f20548152509350505050919050565b6137a561482a565b604051806101200160405280848152602001838152602001600a5f8681526020019081526020015f205f8581526020019081526020015f20548152602001600e5f8681526020019081526020015f205f8581526020019081526020015f20548152602001600f5f8681526020019081526020015f205f8581526020019081526020015f2054815260200160075f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f2054815260200160085f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f2054815260200160065f8681526020019081526020015f205f8581526020019081526020015f20548152602001600d5f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205f8581526020019081526020015f205481525090509392505050565b335f52600b60205260405f20815f528060205260405f208054815f5260205f205f5b82811015613b5057808201545f82840155335f52600d60205260405f209550865f528560205260405f209550805f528560205260405f205f815411156139ee5763646cf5585f526004601cfd5b875f52600a60205260405f209650815f528660205260405f2096505f600188548060018114613a275760028114613a7b5785875d613acb565b60018555335f52600760205260405f209a508b5f528a60205260405f209a50855f528a60205260405f209a508a5493508b5f52600e60205260405f209a50855f528a60205260405f209a508a549250613acb565b60018555335f52600860205260405f209a508b5f528a60205260405f209a50855f528a60205260405f209a508a5493508b5f52600f60205260405f209a50855f528a60205260405f209a508a5492505b505f84541115613b40578a5f52600660205260405f209950845f528960205260405f209950818a54840204815f528060205233868d7f3f63856e2d8c431941e15ac15a28d4201c2838a61987308f61a9d5d01aac483960405fa45f5f5f5f84335af1613b3e576398f736095f526004601cfd5b505b50505050506001810190506139a1565b505f5f5f5c1115613b6b575f5c818301555f5f5d6001810190505b5f60015c1115613b875760015c818301555f60015d6001810190505b5f83115f600185035c111615613bad57600183035c818301555f600184035d6001810190505b600183115f600285035c111615613bd457600283035c818301555f600284035d6001810190505b808455505050505050565b613bf385601261402490919063ffffffff16565b613c29576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f821115613c935782841015613c6857613c4582878761407b565b90508183613c539190615a08565b92508084613c619190615a68565b9350613c92565b613c738287876141aa565b90508184613c819190615a08565b93508083613c8f9190615a68565b92505b5b828411613ca05783613ca2565b825b90506002546001810186118187101715613cc35763a2b52a545f526004601cfd5b4261012c60035401108187141615613ce257639e6d804f5f526004601cfd5b5f831160018114613cf9575f8114613e0357613ef1565b875f52600660205260405f2080602052875f5260405f2090508360025c0381555f60025d335f52600760205260405f20905080602052885f5260405f20905080602052875f5260405f2090508360035c1015613d5c57637b9c89165f526004601cfd5b8360035c0381555f60035d335f52600860205260405f20905080602052885f5260405f20905080602052875f5260405f2090508360045c1015613da657637b9c89165f526004601cfd5b8360045c0381555f60045d885f52600e60205260405f20905080602052875f5260405f2090508360055c0381555f60055d885f52600f60205260405f20905080602052875f5260405f2090508360065c0381555f60065d50613ef1565b875f52600660205260405f2080602052875f5260405f209050838154038155335f52600760205260405f20905080602052885f5260405f20905080602052875f5260405f209050805484811015613e6157637b9c89165f526004601cfd5b8481038255335f52600860205260405f20915081602052895f5260405f20915081602052885f5260405f2091508154905084811015613ea757637b9c89165f526004601cfd5b8481038255895f52600e60205260405f20915081602052885f5260405f209150848254038255895f52600f60205260405f20915081602052885f5260405f20915084825403825550505b506103e86103e58302048083036103e861025882020460015401600155875f52601060205260405f206103e8610258830204820381540181558a831015613f3f5763a6d7690f5f526004601cfd5b875f52866020528260405233898b7f4c686a53bc9329e91f0d0d94d821505fd2c0aef3c09a94ea360d98c0dfb9dee460605fa45f5f5f5f86335af1613f8b576398f736095f526004601cfd5b5050505050505050505050565b60025481565b5f613fb0613fab836142d9565b6142e2565b9050919050565b5f613fca613fc4846142d9565b8361432f565b5f1c905092915050565b5f5f6108079050825f5260205f60205f845afa613ff85763b41b6cb15f526004601cfd5b5f51915050919050565b606061401d614018614013846142d9565b614399565b614460565b9050919050565b5f614039614031846142d9565b835f1b61446a565b905092915050565b5f61405661404e846142d9565b835f1b6144f9565b905092915050565b5f61407361406b846142d9565b835f1b614622565b905092915050565b5f825f52600560205260405f20825f528060205260405f20905080548581018255845f52600460205260405f209150835f528160205260405f20915081548187018188020493508381038355855f52600660205260405f20925082602052845f5260405f209250825460025d335f52600760205260405f20925082602052855f5260405f20925082602052845f5260405f2092508383540160035d335f52600860205260405f20925082602052855f5260405f20925082602052845f5260405f20925082548781101561415557637b9c89165f526004601cfd5b87810360045d865f52600e60205260405f20935083602052855f5260405f2093508484540160055d865f52600f60205260405f20935083602052855f5260405f2093508784540360065d505050509392505050565b5f825f52600460205260405f20825f528060205260405f20905080548581018255845f52600560205260405f20915081602052835f5260405f20915081548187018188020493508381038355855f52600660205260405f20925082602052845f5260405f209250825460025d335f52600760205260405f20925082602052855f5260405f20925082602052845f5260405f20925082548781101561425557637b9c89165f526004601cfd5b87810360035d335f52600860205260405f20935083602052865f5260405f20935083602052855f5260405f2093508484540160045d865f52600e60205260405f20935083602052855f5260405f2093508784540360055d865f52600f60205260405f20935083602052855f5260405f2093508484540160065d505050509392505050565b5f819050919050565b5f5f6142ed83614732565b90508019548060011c925080614328575f92508282015415614328576001925082820154156143285760029250828201541561432857600392505b5050919050565b5f61433983614732565b905081810154905068fbb67fda52d4bfb8bf8114158102905061435b836142e2565b8210614393576040517f4e23d03500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b92915050565b60605f6143a583614732565b905068fbb67fda52d4bfb8bf81195460405193508360200160011561444b578161441c5783548015614416576001925083811415810282528285015490508015614415576002925083811415810260208301528285015490508015614414576003925083811415810260408301525b5b5b5061444b565b8160011c91505f5b8281101561444957808501548481141581028260051b84015250600181019050614424565b505b8185528160051b810160405250505050919050565b6060819050919050565b5f5f61447584614732565b905068fbb67fda52d4bfb8bf83036144945763f5a267f15f526004601cfd5b826144a65768fbb67fda52d4bfb8bf92505b6001156144f2578019546144e1576001915082815403156144f25782600182015403156144f25782600282015403156144f2575f91506144f2565b80602052825f5260405f2054151591505b5092915050565b5f5f61450484614732565b905068fbb67fda52d4bfb8bf83036145235763f5a267f15f526004601cfd5b826145355768fbb67fda52d4bfb8bf92505b80195460011561461a5781602052806145e35781548061455c57848355600193505061461a565b848103614569575061461a565b6001830154806145845785600185015560019450505061461a565b85810361459257505061461a565b6002840154806145ae578660028601556001955050505061461a565b8681036145bd5750505061461a565b825f52600160405f2055815f52600260405f2055805f52600360405f2055600793505050505b835f5260405f208054614618578160011c915084828401558160010181558160010160011b600117831955600193505061461a565b505b505092915050565b5f5f61462d84614732565b905068fbb67fda52d4bfb8bf830361464c5763f5a267f15f526004601cfd5b8261465e5768fbb67fda52d4bfb8bf92505b80195460011561472a57806146d35760019250838254036146955760018201548255600282015460018301555f600283015561472a565b836001830154036146b557600282015460018301555f600283015561472a565b836002830154036146cb575f600283015561472a565b5f925061472a565b81602052835f5260405f208054806146ec57505061472a565b60018360011c03925082600182031461471657828401548060018303860155805f528160405f2055505b60018360011b178419555f82556001945050505b505092915050565b5f6318fb5864600452815f5260245f209050919050565b6040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001606081525090565b6040518061012001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b60405180604001604052805f8152602001606081525090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f819050919050565b6148c1816148af565b82525050565b61016082015f8201516148dc5f8501826148b8565b5060208201516148ef60208501826148b8565b50604082015161490260408501826148b8565b50606082015161491560608501826148b8565b50608082015161492860808501826148b8565b5060a082015161493b60a08501826148b8565b5060c082015161494e60c08501826148b8565b5060e082015161496160e08501826148b8565b506101008201516149766101008501826148b8565b5061012082015161498b6101208501826148b8565b506101408201516149a06101408501826148b8565b50505050565b5f6149b183836148c7565b6101608301905092915050565b5f602082019050919050565b5f6149d482614886565b6149de8185614890565b93506149e9836148a0565b805f5b83811015614a19578151614a0088826149a6565b9750614a0b836149be565b9250506001810190506149ec565b5085935050505092915050565b5f6020820190508181035f830152614a3e81846149ca565b905092915050565b5f604051905090565b5f5ffd5b5f5ffd5b614a60816148af565b8114614a6a575f5ffd5b50565b5f81359050614a7b81614a57565b92915050565b5f60208284031215614a9657614a95614a4f565b5b5f614aa384828501614a6d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b60e082015f820151614ae95f8501826148b8565b506020820151614afc60208501826148b8565b506040820151614b0f60408501826148b8565b506060820151614b2260608501826148b8565b506080820151614b3560808501826148b8565b5060a0820151614b4860a08501826148b8565b5060c0820151614b5b60c08501826148b8565b50505050565b5f614b6c8383614ad5565b60e08301905092915050565b5f602082019050919050565b5f614b8e82614aac565b614b988185614ab6565b9350614ba383614ac6565b805f5b83811015614bd3578151614bba8882614b61565b9750614bc583614b78565b925050600181019050614ba6565b5085935050505092915050565b5f6020820190508181035f830152614bf88184614b84565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f614c2982614c00565b9050919050565b614c3981614c1f565b8114614c43575f5ffd5b50565b5f81359050614c5481614c30565b92915050565b5f5f60408385031215614c7057614c6f614a4f565b5b5f614c7d85828601614c46565b9250506020614c8e85828601614a6d565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f614ccc83836148b8565b60208301905092915050565b5f602082019050919050565b5f614cee82614c98565b614cf88185614ca2565b9350614d0383614cb2565b805f5b83811015614d33578151614d1a8882614cc1565b9750614d2583614cd8565b925050600181019050614d06565b5085935050505092915050565b5f6020820190508181035f830152614d588184614ce4565b905092915050565b5f5f60408385031215614d7657614d75614a4f565b5b5f614d8385828601614a6d565b9250506020614d9485828601614a6d565b9150509250929050565b5f82825260208201905092915050565b5f614db882614c98565b614dc28185614d9e565b9350614dcd83614cb2565b805f5b83811015614dfd578151614de48882614cc1565b9750614def83614cd8565b925050600181019050614dd0565b5085935050505092915050565b5f6101a083015f830151614e205f8601826148b8565b506020830151614e3360208601826148b8565b506040830151614e4660408601826148b8565b506060830151614e5960608601826148b8565b506080830151614e6c60808601826148b8565b5060a0830151614e7f60a08601826148b8565b5060c0830151614e9260c08601826148b8565b5060e0830151614ea560e08601826148b8565b50610100830151614eba6101008601826148b8565b50610120830151614ecf6101208601826148b8565b50610140830151614ee46101408601826148b8565b50610160830151614ef96101608601826148b8565b50610180830151848203610180860152614f138282614dae565b9150508091505092915050565b5f6020820190508181035f830152614f388184614e0a565b905092915050565b5f5f5f5f60808587031215614f5857614f57614a4f565b5b5f614f6587828801614a6d565b9450506020614f7687828801614a6d565b9350506040614f8787828801614a6d565b9250506060614f9887828801614a6d565b91505092959194509250565b614fad816148af565b82525050565b5f602082019050614fc65f830184614fa4565b92915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61501682614fd0565b810181811067ffffffffffffffff8211171561503557615034614fe0565b5b80604052505050565b5f615047614a46565b9050615053828261500d565b919050565b5f67ffffffffffffffff82111561507257615071614fe0565b5b602082029050602081019050919050565b5f5ffd5b5f61509961509484615058565b61503e565b905080838252602082019050602084028301858111156150bc576150bb615083565b5b835b818110156150e557806150d18882614a6d565b8452602084019350506020810190506150be565b5050509392505050565b5f82601f83011261510357615102614fcc565b5b8135615113848260208601615087565b91505092915050565b5f5f5f6060848603121561513357615132614a4f565b5b5f61514086828701614c46565b935050602061515186828701614a6d565b925050604084013567ffffffffffffffff81111561517257615171614a53565b5b61517e868287016150ef565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61012082015f8201516151c65f8501826148b8565b5060208201516151d960208501826148b8565b5060408201516151ec60408501826148b8565b5060608201516151ff60608501826148b8565b50608082015161521260808501826148b8565b5060a082015161522560a08501826148b8565b5060c082015161523860c08501826148b8565b5060e082015161524b60e08501826148b8565b506101008201516152606101008501826148b8565b50505050565b5f61527183836151b1565b6101208301905092915050565b5f602082019050919050565b5f61529482615188565b61529e8185615192565b93506152a9836151a2565b805f5b838110156152d95781516152c08882615266565b97506152cb8361527e565b9250506001810190506152ac565b5085935050505092915050565b5f6020820190508181035f8301526152fe818461528a565b905092915050565b5f8115159050919050565b61531a81615306565b82525050565b5f6060820190506153335f830186615311565b6153406020830185614fa4565b61534d6040830184614fa4565b949350505050565b61012082015f82015161536a5f8501826148b8565b50602082015161537d60208501826148b8565b50604082015161539060408501826148b8565b5060608201516153a360608501826148b8565b5060808201516153b660808501826148b8565b5060a08201516153c960a08501826148b8565b5060c08201516153dc60c08501826148b8565b5060e08201516153ef60e08501826148b8565b506101008201516154046101008501826148b8565b50505050565b5f6101208201905061541e5f830184615355565b92915050565b5f6020828403121561543957615438614a4f565b5b5f61544684828501614c46565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f604083015f83015161548d5f8601826148b8565b50602083015184820360208601526154a58282614dae565b9150508091505092915050565b5f6154bd8383615478565b905092915050565b5f602082019050919050565b5f6154db8261544f565b6154e58185615459565b9350836020820285016154f785615469565b805f5b85811015615532578484038952815161551385826154b2565b945061551e836154c5565b925060208a019950506001810190506154fa565b50829750879550505050505092915050565b5f6020820190508181035f83015261555c81846154d1565b905092915050565b5f6040820190508181035f83015261557c8185614ce4565b905081810360208301526155908184614ce4565b90509392505050565b5f5f5f606084860312156155b0576155af614a4f565b5b5f6155bd86828701614c46565b93505060206155ce86828701614a6d565b92505060406155df86828701614a6d565b9150509250925092565b5f6040820190506155fc5f830185614fa4565b818103602083015261560e8184614ce4565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f6101a083015f8301516156565f8601826148b8565b50602083015161566960208601826148b8565b50604083015161567c60408601826148b8565b50606083015161568f60608601826148b8565b5060808301516156a260808601826148b8565b5060a08301516156b560a08601826148b8565b5060c08301516156c860c08601826148b8565b5060e08301516156db60e08601826148b8565b506101008301516156f06101008601826148b8565b506101208301516157056101208601826148b8565b5061014083015161571a6101408601826148b8565b5061016083015161572f6101608601826148b8565b506101808301518482036101808601526157498282614dae565b9150508091505092915050565b5f6157618383615640565b905092915050565b5f602082019050919050565b5f61577f82615617565b6157898185615621565b93508360208202850161579b85615631565b805f5b858110156157d657848403895281516157b78582615756565b94506157c283615769565b925060208a0199505060018101905061579e565b50829750879550505050505092915050565b5f6060820190506157fb5f830186614fa4565b818103602083015261580d8185615775565b905081810360408301526158218184615775565b9050949350505050565b5f60408201905061583e5f830185614fa4565b8181036020830152615850818461528a565b90509392505050565b61016082015f82015161586e5f8501826148b8565b50602082015161588160208501826148b8565b50604082015161589460408501826148b8565b5060608201516158a760608501826148b8565b5060808201516158ba60808501826148b8565b5060a08201516158cd60a08501826148b8565b5060c08201516158e060c08501826148b8565b5060e08201516158f360e08501826148b8565b506101008201516159086101008501826148b8565b5061012082015161591d6101208501826148b8565b506101408201516159326101408501826148b8565b50505050565b5f6101608201905061594c5f830184615859565b92915050565b5f5f5f5f5f5f60c0878903121561596c5761596b614a4f565b5b5f61597989828a01614a6d565b965050602061598a89828a01614a6d565b955050604061599b89828a01614a6d565b94505060606159ac89828a01614a6d565b93505060806159bd89828a01614a6d565b92505060a06159ce89828a01614a6d565b9150509295509295509295565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f615a12826148af565b9150615a1d836148af565b9250828203905081811115615a3557615a346159db565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f615a72826148af565b9150615a7d836148af565b9250828201905080821115615a9557615a946159db565b5b92915050565b5f615aa5826148af565b9150615ab0836148af565b9250828202615abe816148af565b91508282048414831517615ad557615ad46159db565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f615b13826148af565b9150615b1e836148af565b925082615b2e57615b2d615adc565b5b82820490509291505056fea2646970667358221220137ad95f047d8f6117acaa283c77bac9e6c7dfbcf68da0151429aa2025d06b5164736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000400000000000000000000000002a007eb889ddf2be3f3bda225734c1873bf1ea420000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000009f
-----Decoded View---------------
Arg [0] : initMarketIds (uint256[]): 0,1,5,159
Arg [1] : _admin (address): 0x2A007Eb889Ddf2bE3f3bdA225734c1873BF1EA42
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000002a007eb889ddf2be3f3bda225734c1873bf1ea42
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [6] : 000000000000000000000000000000000000000000000000000000000000009f
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in HYPE
Token Allocations
HYPE
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| HYPEREVM | 100.00% | $23.79 | 0.00018 | $0.004282 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.