Contract Overview
Balance:
0 AVAX
AVAX Value:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x4e211001ab0b52a3ea8a90b82c85591e205d3a2b5ec118f45e410936fbc5c917 | 0x60c06040 | 18291045 | 11 days 17 hrs ago | 0xf5c8e1eaffd278a383c13061b4980db7619479af | IN | Create: AMM | 0 AVAX | 0.120666475 |
[ Download CSV Export ]
Contract Name:
AMM
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { Governable } from "./legos/Governable.sol"; import { ERC20Detailed, IOracle, IRegistry, IVAMM, IAMM, IClearingHouse } from "./Interfaces.sol"; contract AMM is IAMM, Governable { using SafeCast for uint256; using SafeCast for int256; uint256 public constant spotPriceTwapInterval = 1 hours; uint256 public constant fundingPeriod = 1 hours; int256 constant BASE_PRECISION = 1e18; address public immutable clearingHouse; uint256 public immutable unbondRoundOff; /* ****************** */ /* Storage */ /* ****************** */ // System-wide config IOracle public oracle; // AMM config IVAMM override public vamm; address override public underlyingAsset; string public name; uint256 public fundingBufferPeriod; uint256 public nextFundingTime; int256 public cumulativePremiumFraction; int256 public cumulativePremiumPerDtoken; int256 public posAccumulator; uint256 public longOpenInterestNotional; uint256 public shortOpenInterestNotional; uint256 public maxOracleSpreadRatio; // scaled 2 decimals uint256 public maxLiquidationRatio; // scaled 2 decimals uint256 public maxLiquidationPriceSpread; // scaled 6 decimals enum Side { LONG, SHORT } struct Position { int256 size; uint256 openNotional; int256 lastPremiumFraction; uint liquidationThreshold; } mapping(address => Position) override public positions; mapping(address => Maker) internal _makers; uint256 public withdrawPeriod; uint256 public unbondPeriod; struct ReserveSnapshot { uint256 lastPrice; uint256 timestamp; uint256 blockNumber; bool isLiquidation; } ReserveSnapshot[] public reserveSnapshots; Ignition override public ignition; IAMM.AMMState override public ammState; /// @notice Min amount of base asset quantity to trade or add liquidity for uint256 public minSizeRequirement; struct VarGroup1 { uint minQuote; uint minBase; bool isLiquidation; } uint256[50] private __gap; /* ****************** */ /* Events */ /* ****************** */ // Generic AMM related events event FundingRateUpdated(int256 premiumFraction, uint256 underlyingPrice, int256 cumulativePremiumFraction, int256 cumulativePremiumPerDtoken, int256 posAccumulator, uint256 nextFundingTime, uint256 timestamp, uint256 blockNumber); event FundingPaid(address indexed trader, int256 takerFundingPayment, int256 makerFundingPayment); event Swap(uint256 lastPrice, uint256 openInterestNotional); // Trader related events event PositionChanged(address indexed trader, int256 size, uint256 openNotional, int256 realizedPnl); event LiquidityAdded(address indexed trader, uint dToken, uint baseAsset, uint quoteAsset, uint timestamp); event LiquidityRemoved(address indexed trader, uint dToken, uint baseAsset, uint quoteAsset, int256 realizedPnl, bool isLiquidation, uint timestamp); event Unbonded(address indexed trader, uint256 unbondAmount, uint256 unbondTime, uint timestamp); /** * @dev This is only emitted when maker funding related events are updated. * These fields are: ignition,dToken,lastPremiumFraction,pos,lastPremiumPerDtoken,posAccumulator */ event MakerPositionChanged(address indexed trader, Maker maker, uint timestamp); modifier onlyClearingHouse() { require(msg.sender == clearingHouse, "Only clearingHouse"); _; } modifier onlyVamm() { require(msg.sender == address(vamm), "Only VAMM"); _; } modifier whenIgnition() { require(ammState == AMMState.Ignition, "amm_not_ignition"); _; } modifier whenActive() { require(ammState == AMMState.Active, "amm_not_active"); _; } constructor(address _clearingHouse, uint _unbondRoundOff) { clearingHouse = _clearingHouse; unbondRoundOff = _unbondRoundOff; } function initialize( string memory _name, address _underlyingAsset, address _oracle, uint _minSizeRequirement, address _vamm, address _governance ) external initializer { name = _name; underlyingAsset = _underlyingAsset; oracle = IOracle(_oracle); minSizeRequirement = _minSizeRequirement; vamm = IVAMM(_vamm); _setGovernace(_governance); // values that most likely wouldn't need to change frequently fundingBufferPeriod = 15 minutes; withdrawPeriod = 1 days; maxOracleSpreadRatio = 20; unbondPeriod = 3 days; maxLiquidationRatio = 25; maxLiquidationPriceSpread = 1e6; } /** * @dev baseAssetQuantity != 0 has been validated in clearingHouse._openPosition() */ function openPosition(address trader, int256 baseAssetQuantity, uint quoteAssetLimit) override external onlyClearingHouse whenActive returns (int realizedPnl, uint quoteAsset, bool isPositionIncreased) { Position memory position = positions[trader]; bool isNewPosition = position.size == 0 ? true : false; Side side = baseAssetQuantity > 0 ? Side.LONG : Side.SHORT; if (isNewPosition || (position.size > 0 ? Side.LONG : Side.SHORT) == side) { // realizedPnl = 0; quoteAsset = _increasePosition(trader, baseAssetQuantity, quoteAssetLimit); isPositionIncreased = true; } else { (realizedPnl, quoteAsset, isPositionIncreased) = _openReversePosition(trader, baseAssetQuantity, quoteAssetLimit); } uint totalPosSize = uint(abs(positions[trader].size)); require(totalPosSize == 0 || totalPosSize >= minSizeRequirement, "position_less_than_minSize"); // update liquidation thereshold positions[trader].liquidationThreshold = Math.max( totalPosSize * maxLiquidationRatio / 100, minSizeRequirement ); _emitPositionChanged(trader, realizedPnl); } function liquidatePosition(address trader) override external onlyClearingHouse returns (int realizedPnl, uint quoteAsset) { // don't need an ammState check because there should be no active positions Position memory position = positions[trader]; bool isLongPosition = position.size > 0 ? true : false; uint positionToLiquidate = Math.min(uint(abs(position.size)), position.liquidationThreshold); // liquidation price safeguard // price before liquidaiton should be within X% range of last liquidation price in the same block or previous block price uint index = reserveSnapshots.length - 1; uint lastTradePrice = reserveSnapshots[index].lastPrice; while(reserveSnapshots[index].blockNumber == block.number && index != 0) { if (reserveSnapshots[index].isLiquidation) { lastTradePrice = reserveSnapshots[index].lastPrice; break; } index -= 1; lastTradePrice = reserveSnapshots[index].lastPrice; } uint diff = lastPrice(); if (diff >= lastTradePrice) { diff -= lastTradePrice; } else { diff = lastTradePrice - diff; } require(diff <= lastTradePrice * maxLiquidationPriceSpread / 1e8, "AMM.liquidation_price_slippage"); // liquidate position if (isLongPosition) { (realizedPnl, quoteAsset) = _reducePosition(trader, -positionToLiquidate.toInt256(), 0, true /* isLiquidation */); } else { (realizedPnl, quoteAsset) = _reducePosition(trader, positionToLiquidate.toInt256(), type(uint).max, true /* isLiquidation */); } _emitPositionChanged(trader, realizedPnl); } function updatePosition(address trader) override external onlyClearingHouse returns(int256 fundingPayment) { if (ammState != AMMState.Active) return 0; _setIgnitionShare(trader); Maker storage maker = _makers[trader]; int256 takerFundingPayment; int256 makerFundingPayment; ( takerFundingPayment, makerFundingPayment, maker.lastPremiumFraction, maker.lastPremiumPerDtoken ) = getPendingFundingPayment(trader); _emitMakerPositionChanged(trader); Position storage position = positions[trader]; position.lastPremiumFraction = maker.lastPremiumFraction; // +: trader paid, -: trader received fundingPayment = takerFundingPayment + makerFundingPayment; if (fundingPayment < 0) { fundingPayment -= fundingPayment / 1e3; // receivers charged 0.1% to account for rounding-offs } if (fundingPayment != 0) { emit FundingPaid(trader, takerFundingPayment, makerFundingPayment); } } /* ****************** */ /* Makers */ /* ****************** */ function addLiquidity(address maker, uint baseAssetQuantity, uint minDToken) override external onlyClearingHouse whenActive returns (uint dToken) { require(baseAssetQuantity >= minSizeRequirement, "adding_too_less"); uint quoteAsset; uint baseAssetBal = vamm.balances(1); if (baseAssetBal == 0) { quoteAsset = baseAssetQuantity * vamm.price_scale() / 1e30; } else { quoteAsset = baseAssetQuantity * vamm.balances(0) / baseAssetBal; } dToken = vamm.add_liquidity([quoteAsset, baseAssetQuantity], minDToken); // updates Maker storage _maker = _makers[maker]; if (_maker.dToken > 0) { // Maker only accumulates position when they had non-zero liquidity _maker.pos += (posAccumulator - _maker.posAccumulator) * _maker.dToken.toInt256() / 1e18; } _maker.vUSD += quoteAsset; _maker.vAsset += baseAssetQuantity; _maker.dToken += dToken; _maker.posAccumulator = posAccumulator; _emitMakerPositionChanged(maker); emit LiquidityAdded(maker, dToken, baseAssetQuantity, quoteAsset, _blockTimestamp()); } /** * @notice Express the intention to withdraw liquidity. * Can only withdraw after unbondPeriod and within withdrawal period * All withdrawals are batched together to 00:00 GMT * @param dToken Amount of dToken to withdraw */ function unbondLiquidity(uint dToken) external whenActive { address maker = msg.sender; // this needs to be invoked here because updatePosition is not called before unbondLiquidity _setIgnitionShare(maker); _emitMakerPositionChanged(maker); // because dToken was updated Maker storage _maker = _makers[maker]; require(dToken != 0, "unbonding_0"); require(_maker.dToken >= dToken, "unbonding_too_much"); _maker.unbondAmount = dToken; _maker.unbondTime = ((_blockTimestamp() + unbondPeriod) / unbondRoundOff) * unbondRoundOff; emit Unbonded(maker, dToken, _maker.unbondTime, _blockTimestamp()); } function forceRemoveLiquidity(address maker) override external onlyClearingHouse returns (int realizedPnl, uint makerOpenNotional, int makerPosition) { Maker storage _maker = _makers[maker]; if (ammState == AMMState.Active) { // @todo partial liquidations and slippage checks VarGroup1 memory varGroup1 = VarGroup1(0,0,true); uint dToken = _maker.dToken; _maker.unbondAmount -= Math.min(dToken, _maker.unbondAmount); return _removeLiquidity(maker, dToken, varGroup1); } // ammState == AMMState.Ignition ignition.quoteAsset -= _makers[maker].ignition; _makers[maker].ignition = 0; _emitMakerPositionChanged(maker); } function removeLiquidity(address maker, uint amount, uint minQuote, uint minBase) override external onlyClearingHouse returns (int realizedPnl, uint makerOpenNotional, int makerPosition) { Maker storage _maker = _makers[maker]; require(_maker.unbondAmount >= amount, "withdrawing_more_than_unbonded"); unchecked { _maker.unbondAmount -= amount; } uint _now = _blockTimestamp(); require(_now >= _maker.unbondTime, "still_unbonding"); require(_now <= _maker.unbondTime + withdrawPeriod, "withdraw_period_over"); // there's no need to reset the unbondTime, unbondAmount will take care of everything VarGroup1 memory varGroup1 = VarGroup1(minQuote, minBase, false); (realizedPnl, makerOpenNotional, makerPosition) = _removeLiquidity(maker, amount, varGroup1); if (_maker.dToken != 0) { // if the maker doesn't remove all their liq, ensure decent size require(_maker.vAsset >= minSizeRequirement, "leftover_liquidity_is_too_less"); uint totalPosSize = uint(abs(positions[maker].size)); require(totalPosSize == 0 || totalPosSize >= minSizeRequirement, "removing_very_small_liquidity"); } } function _removeLiquidity(address maker, uint amount, VarGroup1 memory varGroup1) internal returns (int realizedPnl, uint makerOpenNotional, int makerPosition) { Maker storage _maker = _makers[maker]; Position storage position = positions[maker]; // amount <= _maker.dToken will be asserted when updating maker.dToken uint256 totalOpenNotional; uint[2] memory dBalances = [uint(0),uint(0)]; ( makerPosition, makerOpenNotional, totalOpenNotional, realizedPnl, // feeAdjustedPnl dBalances ) = vamm.remove_liquidity( amount, [varGroup1.minQuote, varGroup1.minBase], _maker.vUSD, _maker.vAsset, _maker.dToken, position.size, position.openNotional ); // update maker info { uint diff = _maker.dToken - amount; if (diff == 0) { _maker.pos = 0; _maker.vAsset = 0; _maker.vUSD = 0; _maker.dToken = 0; } else { // muitiply by diff because a taker position will also be opened while removing liquidity and its funding payment is calculated seperately _maker.pos = _maker.pos + (posAccumulator - _maker.posAccumulator) * diff.toInt256() / 1e18; _maker.vAsset = _maker.vAsset * diff / _maker.dToken; _maker.vUSD = _maker.vUSD * diff / _maker.dToken; _maker.dToken = diff; } _maker.posAccumulator = posAccumulator; } // translate impermanent position to a permanent one { if (makerPosition != 0) { // reducing or reversing position if (makerPosition * position.size < 0) { // this ensures takerPosition !=0 realizedPnl += _getPnlWhileReducingPosition(position.size, position.openNotional, makerPosition); } position.openNotional = totalOpenNotional; position.size += makerPosition; // update liquidation thereshold position.liquidationThreshold = Math.max( uint(abs(position.size)) * maxLiquidationRatio / 100, minSizeRequirement ); // update long and short open interest notional if (makerPosition > 0) { longOpenInterestNotional += makerPosition.toUint256(); } else { shortOpenInterestNotional += (-makerPosition).toUint256(); } // these events will enable the parsing logic in the indexer to work seamlessly emit Swap(lastPrice(), openInterestNotional()); _emitPositionChanged(maker, realizedPnl); } } _emitMakerPositionChanged(maker); emit LiquidityRemoved( maker, amount, dBalances[1], // baseAsset dBalances[0], // quoteAsset realizedPnl, varGroup1.isLiquidation, _blockTimestamp() ); } function getOpenNotionalWhileReducingPosition( int256 positionSize, uint256 newNotionalPosition, int256 unrealizedPnl, int256 baseAssetQuantity ) override public pure returns(uint256 remainOpenNotional, int realizedPnl) { require(abs(positionSize) >= abs(baseAssetQuantity), "AMM.ONLY_REDUCE_POS"); bool isLongPosition = positionSize > 0 ? true : false; realizedPnl = unrealizedPnl * abs(baseAssetQuantity) / abs(positionSize); int256 unrealizedPnlAfter = unrealizedPnl - realizedPnl; /** * We need to determine the openNotional value of the reduced position now. * We know notionalPosition and unrealizedPnlAfter (unrealizedPnl times the ratio of open position) * notionalPosition = notionalPosition - quoteAsset (exchangedQuoteAssetAmount) * calculate openNotional (it's different depends on long or short side) * long: unrealizedPnl = notionalPosition - openNotional => openNotional = notionalPosition - unrealizedPnl * short: unrealizedPnl = openNotional - notionalPosition => openNotional = notionalPosition + unrealizedPnl */ if (isLongPosition) { /** * Let baseAssetQuantity = Q, position.size = size, by definition of _reducePosition, abs(size) >= abs(Q) * quoteAsset = notionalPosition * Q / size * unrealizedPnlAfter = unrealizedPnl - realizedPnl = unrealizedPnl - unrealizedPnl * Q / size * remainOpenNotional = notionalPosition - notionalPosition * Q / size - unrealizedPnl + unrealizedPnl * Q / size * => remainOpenNotional = notionalPosition(size-Q)/size - unrealizedPnl(size-Q)/size * => remainOpenNotional = (notionalPosition - unrealizedPnl) * (size-Q)/size * Since notionalPosition includes the PnL component, notionalPosition >= unrealizedPnl and size >= Q * Hence remainOpenNotional >= 0 */ remainOpenNotional = (newNotionalPosition.toInt256() - unrealizedPnlAfter).toUint256(); // will assert that remainOpenNotional >= 0 } else { /** * Let baseAssetQuantity = Q, position.size = size, by definition of _reducePosition, abs(size) >= abs(Q) * quoteAsset = notionalPosition * Q / size * unrealizedPnlAfter = unrealizedPnl - realizedPnl = unrealizedPnl - unrealizedPnl * Q / size * remainOpenNotional = notionalPosition - notionalPosition * Q / size + unrealizedPnl - unrealizedPnl * Q / size * => remainOpenNotional = notionalPosition(size-Q)/size + unrealizedPnl(size-Q)/size * => remainOpenNotional = (notionalPosition + unrealizedPnl) * (size-Q)/size * => In AMM.sol, unrealizedPnl = position.openNotional - notionalPosition * => notionalPosition + unrealizedPnl >= 0 * Hence remainOpenNotional >= 0 */ remainOpenNotional = (newNotionalPosition.toInt256() + unrealizedPnlAfter).toUint256(); // will assert that remainOpenNotional >= 0 } } /** * @notice update funding rate * @dev only allow to update while reaching `nextFundingTime` */ function settleFunding() override external onlyClearingHouse { if ( ammState != AMMState.Active || _blockTimestamp() < nextFundingTime ) return; // premium = twapMarketPrice - twapIndexPrice // timeFraction = fundingPeriod(1 hour) / 1 day // premiumFraction = premium * timeFraction int256 underlyingPrice = getUnderlyingTwapPrice(spotPriceTwapInterval); int256 premium = getTwapPrice(spotPriceTwapInterval) - underlyingPrice; int256 premiumFraction = (premium * int256(fundingPeriod)) / 1 days; int256 premiumPerDtoken = posAccumulator * premiumFraction; // makers pay slightly more to account for rounding off premiumPerDtoken = (premiumPerDtoken / BASE_PRECISION) + 1; cumulativePremiumFraction += premiumFraction; cumulativePremiumPerDtoken += premiumPerDtoken; // Updates for next funding event // in order to prevent multiple funding settlement during very short time after network congestion uint256 minNextValidFundingTime = _blockTimestamp() + fundingBufferPeriod; // floor((nextFundingTime + fundingPeriod) / 3600) * 3600 uint256 nextFundingTimeOnHourStart = ((nextFundingTime + fundingPeriod) / 1 hours) * 1 hours; // max(nextFundingTimeOnHourStart, minNextValidFundingTime) nextFundingTime = nextFundingTimeOnHourStart > minNextValidFundingTime ? nextFundingTimeOnHourStart : minNextValidFundingTime; _emitFundingRateUpdated(premiumFraction, underlyingPrice); } function commitLiquidity(address maker, uint quoteAsset) override external whenIgnition onlyClearingHouse { quoteAsset /= 2; // only need to track the USD side _makers[maker].ignition += quoteAsset; ignition.quoteAsset += quoteAsset; _emitMakerPositionChanged(maker); } function liftOff() external onlyGovernance whenIgnition { uint256 underlyingPrice = getUnderlyingTwapPrice(15 minutes).toUint256(); require(underlyingPrice > 0, "amm.liftOff.underlyingPrice_not_set"); vamm.setinitialPrice(underlyingPrice * 1e12); // vamm expects 18 decimal scale if (ignition.quoteAsset > 0) { ignition.baseAsset = ignition.quoteAsset * 1e18 / underlyingPrice; ignition.dToken = vamm.add_liquidity([ignition.quoteAsset, ignition.baseAsset], 0); // helps in the API logic emit LiquidityAdded(address(this), ignition.dToken, ignition.baseAsset, ignition.quoteAsset, _blockTimestamp()); } ammState = AMMState.Active; // funding games can now begin nextFundingTime = ((_blockTimestamp() + fundingPeriod) / 1 hours) * 1 hours; } function _setIgnitionShare(address maker) internal { uint vUSD = _makers[maker].ignition; if (vUSD == 0) return; Maker storage _maker = _makers[maker]; _maker.vUSD = vUSD; (_maker.vAsset, _maker.dToken) = getIgnitionShare(vUSD); _maker.ignition = 0; } function getIgnitionShare(uint vUSD) override public view returns (uint vAsset, uint dToken) { vAsset = ignition.baseAsset * vUSD / ignition.quoteAsset; dToken = ignition.dToken * vUSD / ignition.quoteAsset; } // View function getSnapshotLen() external view returns (uint256) { return reserveSnapshots.length; } function getUnderlyingTwapPrice(uint256 _intervalInSeconds) public view returns (int256) { return oracle.getUnderlyingTwapPrice(underlyingAsset, _intervalInSeconds); } function getTwapPrice(uint256 _intervalInSeconds) public view returns (int256) { return _calcTwap(_intervalInSeconds).toInt256(); } function getNotionalPositionAndUnrealizedPnl(address trader) override external view returns(uint256 notionalPosition, int256 unrealizedPnl, int256 size, uint256 openNotional) { if (ammState == AMMState.Ignition) { return (_makers[trader].ignition * 2, 0, 0, 0); } uint vUSD = _makers[trader].ignition; uint vAsset; uint dToken; if (vUSD > 0) { // participated in ignition (vAsset, dToken) = getIgnitionShare(vUSD); } else { vUSD = _makers[trader].vUSD; vAsset = _makers[trader].vAsset; dToken = _makers[trader].dToken; } (notionalPosition, size, unrealizedPnl, openNotional) = vamm.get_notional( dToken, vUSD, vAsset, positions[trader].size, positions[trader].openNotional ); } /** * @notice returns false if * (1-maxSpreadRatio)*indexPrice < markPrice < (1+maxSpreadRatio)*indexPrice * else, true */ function isOverSpreadLimit() external view returns(bool) { if (ammState != AMMState.Active) return false; uint oraclePrice = uint(oracle.getUnderlyingPrice(underlyingAsset)); uint markPrice = lastPrice(); uint oracleSpreadRatioAbs; if (markPrice > oraclePrice) { oracleSpreadRatioAbs = markPrice - oraclePrice; } else { oracleSpreadRatioAbs = oraclePrice - markPrice; } oracleSpreadRatioAbs = oracleSpreadRatioAbs * 100 / oraclePrice; if (oracleSpreadRatioAbs >= maxOracleSpreadRatio) { return true; } return false; } /** * @notice returns notionalPosition and unrealizedPnl when isOverSpreadLimit() * calculate margin fraction using markPrice and oraclePrice * if mode = Maintenance_Margin, return values which have maximum margin fraction * if mode = min_allowable_margin, return values which have minimum margin fraction */ function getOracleBasedPnl(address trader, int256 margin, IClearingHouse.Mode mode) override external view returns (uint notionalPosition, int256 unrealizedPnl) { Maker memory _maker = _makers[trader]; if (ammState == AMMState.Ignition) { return (_maker.ignition * 2, 0); } Position memory _taker = positions[trader]; int256 size; uint openNotional; (notionalPosition, size, unrealizedPnl, openNotional) = vamm.get_notional( _maker.dToken, _maker.vUSD, _maker.vAsset, _taker.size, _taker.openNotional ); if (notionalPosition == 0) { return (0, 0); } int256 marginFraction = (margin + unrealizedPnl) * 1e6 / notionalPosition.toInt256(); (int oracleBasedNotional, int256 oracleBasedUnrealizedPnl, int256 oracleBasedMF) = _getOracleBasedMarginFraction( trader, margin, openNotional, size ); if (mode == IClearingHouse.Mode.Maintenance_Margin) { if (oracleBasedMF > marginFraction) { notionalPosition = oracleBasedNotional.toUint256(); unrealizedPnl = oracleBasedUnrealizedPnl; } } else if (oracleBasedMF < marginFraction) { // IClearingHouse.Mode.Min_Allowable_Margin notionalPosition = oracleBasedNotional.toUint256(); unrealizedPnl = oracleBasedUnrealizedPnl; } } function _getOracleBasedMarginFraction(address trader, int256 margin, uint256 openNotional, int256 size) internal view returns (int oracleBasedNotional, int256 oracleBasedUnrealizedPnl, int256 marginFraction) { int256 oraclePrice = oracle.getUnderlyingPrice(underlyingAsset); oracleBasedNotional = oraclePrice * abs(size) / BASE_PRECISION; if (size > 0) { oracleBasedUnrealizedPnl = oracleBasedNotional - openNotional.toInt256(); } else if (size < 0) { oracleBasedUnrealizedPnl = openNotional.toInt256() - oracleBasedNotional; } // notionalPostion = max(makerDebt, makerPositionNotional) + takerPositionalNotional // = max(makerDebt + takerPositionNotional, makerPositionNotional + takerPositionNotional) int256 oracleBasedTakerNotional = oraclePrice * abs(positions[trader].size) / BASE_PRECISION; oracleBasedNotional = _max(2 * _makers[trader].vUSD.toInt256() + oracleBasedTakerNotional, oracleBasedNotional); marginFraction = (margin + oracleBasedUnrealizedPnl) * 1e6 / oracleBasedNotional; } function getPendingFundingPayment(address trader) override public view returns( int256 takerFundingPayment, int256 makerFundingPayment, int256 latestCumulativePremiumFraction, int256 latestPremiumPerDtoken ) { Position memory taker = positions[trader]; Maker memory maker = _makers[trader]; // cache state variables locally for cheaper access and return values latestCumulativePremiumFraction = cumulativePremiumFraction; latestPremiumPerDtoken = cumulativePremiumPerDtoken; // Taker takerFundingPayment = (latestCumulativePremiumFraction - taker.lastPremiumFraction) * taker.size / BASE_PRECISION; // Maker uint256 dToken; uint vUSD = _makers[trader].ignition; if (vUSD > 0) { (,dToken) = getIgnitionShare(vUSD); } else { dToken = maker.dToken; } if (dToken > 0) { int256 cpf = latestCumulativePremiumFraction - maker.lastPremiumFraction; makerFundingPayment = ( maker.pos * cpf + ( latestPremiumPerDtoken - maker.lastPremiumPerDtoken - maker.posAccumulator * cpf / BASE_PRECISION ) * dToken.toInt256() ) / BASE_PRECISION; } } function getCloseQuote(int256 baseAssetQuantity) override public view returns(uint256 quoteAssetQuantity) { if (baseAssetQuantity > 0) { return vamm.get_dy(1, 0, baseAssetQuantity.toUint256()); } else if (baseAssetQuantity < 0) { return vamm.get_dx(0, 1, (-baseAssetQuantity).toUint256()); } return 0; } function getTakerNotionalPositionAndUnrealizedPnl(address trader) override public view returns(uint takerNotionalPosition, int256 unrealizedPnl) { Position memory position = positions[trader]; if (position.size > 0) { takerNotionalPosition = vamm.get_dy(1, 0, position.size.toUint256()); unrealizedPnl = takerNotionalPosition.toInt256() - position.openNotional.toInt256(); } else if (position.size < 0) { takerNotionalPosition = vamm.get_dx(0, 1, (-position.size).toUint256()); unrealizedPnl = position.openNotional.toInt256() - takerNotionalPosition.toInt256(); } } function lastPrice() public view returns(uint256) { return vamm.mark_price() / 1e12; } function openInterestNotional() public view returns (uint256) { return longOpenInterestNotional + shortOpenInterestNotional; } function makers(address maker) override external view returns(Maker memory) { return _makers[maker]; } // internal /** * @dev Go long on an asset * @param baseAssetQuantity Exact base asset quantity to go long * @param max_dx Maximum amount of quote asset to be used while longing baseAssetQuantity. Lower means longing at a lower price (desirable). * @param isLiquidation true if liquidaiton else false * @return quoteAssetQuantity quote asset utilised. quoteAssetQuantity / baseAssetQuantity was the average rate. quoteAssetQuantity <= max_dx */ function _long(int256 baseAssetQuantity, uint max_dx, bool isLiquidation) internal returns (uint256 quoteAssetQuantity) { require(baseAssetQuantity > 0, "VAMM._long: baseAssetQuantity is <= 0"); uint _lastPrice; (quoteAssetQuantity, _lastPrice) = vamm.exchangeExactOut( 0, // sell quote asset 1, // purchase base asset baseAssetQuantity.toUint256(), // long exactly. Note that statement asserts that baseAssetQuantity >= 0 max_dx ); // 6 decimals precision // longs not allowed if market price > (1 + maxOracleSpreadRatio)*index price uint256 oraclePrice = uint(oracle.getUnderlyingPrice(underlyingAsset)); oraclePrice = oraclePrice * (100 + maxOracleSpreadRatio) / 100; if (!isLiquidation && _lastPrice > oraclePrice) { revert("VAMM._long: longs not allowed"); } _addReserveSnapshot(_lastPrice, isLiquidation); // since maker position will be opposite of the trade posAccumulator -= baseAssetQuantity * 1e18 / vamm.totalSupply().toInt256(); emit Swap(_lastPrice, openInterestNotional()); } /** * @dev Go short on an asset * @param baseAssetQuantity Exact base asset quantity to short * @param min_dy Minimum amount of quote asset to be used while shorting baseAssetQuantity. Higher means shorting at a higher price (desirable). * @param isLiquidation true if liquidaiton else false * @return quoteAssetQuantity quote asset utilised. quoteAssetQuantity / baseAssetQuantity was the average short rate. quoteAssetQuantity >= min_dy. */ function _short(int256 baseAssetQuantity, uint min_dy, bool isLiquidation) internal returns (uint256 quoteAssetQuantity) { require(baseAssetQuantity < 0, "VAMM._short: baseAssetQuantity is >= 0"); uint _lastPrice; (quoteAssetQuantity, _lastPrice) = vamm.exchange( 1, // sell base asset 0, // get quote asset (-baseAssetQuantity).toUint256(), // short exactly. Note that statement asserts that baseAssetQuantity <= 0 min_dy ); // shorts not allowed if market price < (1 - maxOracleSpreadRatio)*index price uint256 oraclePrice = uint(oracle.getUnderlyingPrice(underlyingAsset)); oraclePrice = oraclePrice * (100 - maxOracleSpreadRatio) / 100; if (!isLiquidation && _lastPrice < oraclePrice) { revert("VAMM._short: shorts not allowed"); } _addReserveSnapshot(_lastPrice, isLiquidation); // since maker position will be opposite of the trade posAccumulator -= baseAssetQuantity * 1e18 / vamm.totalSupply().toInt256(); emit Swap(_lastPrice, openInterestNotional()); } function _emitPositionChanged(address trader, int256 realizedPnl) internal { Position memory position = positions[trader]; emit PositionChanged(trader, position.size, position.openNotional, realizedPnl); } function _emitMakerPositionChanged(address maker) internal { emit MakerPositionChanged(maker, _makers[maker], _blockTimestamp()); } /** * @dev Get PnL to be realized for the part of the position that is being closed * Check takerPosition != 0 before calling */ function _getPnlWhileReducingPosition( int256 takerPosition, uint takerOpenNotional, int256 makerPosition ) internal view returns (int256 pnlToBeRealized) { // notional of the combined new position uint newNotional = getCloseQuote(takerPosition + makerPosition); uint totalPosition = abs(makerPosition + takerPosition).toUint256(); if (abs(takerPosition) > abs(makerPosition)) { // taker position side remains same uint reducedOpenNotional = takerOpenNotional * abs(makerPosition).toUint256() / abs(takerPosition).toUint256(); uint makerNotional = newNotional * abs(makerPosition).toUint256() / totalPosition; pnlToBeRealized = _getPnlToBeRealized(takerPosition, makerNotional, reducedOpenNotional); } else { // taker position side changes // @todo handle case when totalPosition = 0 uint closedPositionNotional = newNotional * abs(takerPosition).toUint256() / totalPosition; pnlToBeRealized = _getPnlToBeRealized(takerPosition, closedPositionNotional, takerOpenNotional); } } function _getPnlToBeRealized(int256 takerPosition, uint notionalPosition, uint openNotional) internal pure returns (int256 pnlToBeRealized) { if (takerPosition > 0) { pnlToBeRealized = notionalPosition.toInt256() - openNotional.toInt256(); } else { pnlToBeRealized = openNotional.toInt256() - notionalPosition.toInt256(); } } function _increasePosition(address trader, int256 baseAssetQuantity, uint quoteAssetLimit) internal returns(uint quoteAsset) { if (baseAssetQuantity > 0) { // Long - purchase baseAssetQuantity longOpenInterestNotional += baseAssetQuantity.toUint256(); quoteAsset = _long(baseAssetQuantity, quoteAssetLimit, false /* isLiquidation */); } else { // Short - sell baseAssetQuantity shortOpenInterestNotional += (-baseAssetQuantity).toUint256(); quoteAsset = _short(baseAssetQuantity, quoteAssetLimit, false /* isLiquidation */); } positions[trader].size += baseAssetQuantity; // -ve baseAssetQuantity will increase short position positions[trader].openNotional += quoteAsset; } function _openReversePosition(address trader, int256 baseAssetQuantity, uint quoteAssetLimit) internal returns (int realizedPnl, uint quoteAsset, bool isPositionIncreased) { Position memory position = positions[trader]; if (abs(position.size) >= abs(baseAssetQuantity)) { (realizedPnl, quoteAsset) = _reducePosition(trader, baseAssetQuantity, quoteAssetLimit, false /* isLiqudation */); } else { uint closedRatio = (quoteAssetLimit * abs(position.size).toUint256()) / abs(baseAssetQuantity).toUint256(); (realizedPnl, quoteAsset) = _reducePosition(trader, -position.size, closedRatio, false /* isLiqudation */); // this is required because the user might pass a very less value (slippage-prone) while shorting if (quoteAssetLimit >= quoteAsset) { quoteAssetLimit -= quoteAsset; } quoteAsset += _increasePosition(trader, baseAssetQuantity + position.size, quoteAssetLimit); isPositionIncreased = true; } } /** * @dev validate that baseAssetQuantity <= position.size should be performed before the call to _reducePosition */ function _reducePosition(address trader, int256 baseAssetQuantity, uint quoteAssetLimit, bool isLiquidation) internal returns (int realizedPnl, uint256 quoteAsset) { (, int256 unrealizedPnl) = getTakerNotionalPositionAndUnrealizedPnl(trader); Position storage position = positions[trader]; // storage because there are updates at the end bool isLongPosition = position.size > 0 ? true : false; if (isLongPosition) { longOpenInterestNotional -= (-baseAssetQuantity).toUint256(); quoteAsset = _short(baseAssetQuantity, quoteAssetLimit, isLiquidation); } else { shortOpenInterestNotional -= baseAssetQuantity.toUint256(); quoteAsset = _long(baseAssetQuantity, quoteAssetLimit, isLiquidation); } uint256 notionalPosition = getCloseQuote(position.size + baseAssetQuantity); (position.openNotional, realizedPnl) = getOpenNotionalWhileReducingPosition(position.size, notionalPosition, unrealizedPnl, baseAssetQuantity); position.size += baseAssetQuantity; } function _addReserveSnapshot(uint256 price, bool isLiquidation) internal { uint256 currentBlock = block.number; uint256 blockTimestamp = _blockTimestamp(); if (reserveSnapshots.length == 0) { reserveSnapshots.push( ReserveSnapshot(price, blockTimestamp, currentBlock, isLiquidation) ); return; } ReserveSnapshot storage latestSnapshot = reserveSnapshots[reserveSnapshots.length - 1]; // update values in snapshot if in the same block if (currentBlock == latestSnapshot.blockNumber) { latestSnapshot.lastPrice = price; } else { reserveSnapshots.push( ReserveSnapshot(price, blockTimestamp, currentBlock, isLiquidation) ); } } function _blockTimestamp() internal view virtual returns (uint256) { return block.timestamp; } function _calcTwap(uint256 _intervalInSeconds) internal view returns (uint256) { uint256 snapshotIndex = reserveSnapshots.length - 1; uint256 currentPrice = reserveSnapshots[snapshotIndex].lastPrice; if (_intervalInSeconds == 0) { return currentPrice; } uint256 baseTimestamp = _blockTimestamp() - _intervalInSeconds; ReserveSnapshot memory currentSnapshot = reserveSnapshots[snapshotIndex]; // return the latest snapshot price directly // if only one snapshot or the timestamp of latest snapshot is earlier than asking for if (reserveSnapshots.length == 1 || currentSnapshot.timestamp <= baseTimestamp) { return currentPrice; } uint256 previousTimestamp = currentSnapshot.timestamp; uint256 period = _blockTimestamp() - previousTimestamp; uint256 weightedPrice = currentPrice * period; while (true) { // if snapshot history is too short if (snapshotIndex == 0) { return weightedPrice / period; } snapshotIndex = snapshotIndex - 1; currentSnapshot = reserveSnapshots[snapshotIndex]; currentPrice = reserveSnapshots[snapshotIndex].lastPrice; // check if current round timestamp is earlier than target timestamp if (currentSnapshot.timestamp <= baseTimestamp) { // weighted time period will be (target timestamp - previous timestamp). For example, // now is 1000, _interval is 100, then target timestamp is 900. If timestamp of current round is 970, // and timestamp of NEXT round is 880, then the weighted time period will be (970 - 900) = 70, // instead of (970 - 880) weightedPrice = weightedPrice + (currentPrice * (previousTimestamp - baseTimestamp)); break; } uint256 timeFraction = previousTimestamp - currentSnapshot.timestamp; weightedPrice = weightedPrice + (currentPrice * timeFraction); period = period + timeFraction; previousTimestamp = currentSnapshot.timestamp; } return weightedPrice / _intervalInSeconds; } function _emitFundingRateUpdated( int256 _premiumFraction, int256 _underlyingPrice ) internal { emit FundingRateUpdated( _premiumFraction, _underlyingPrice.toUint256(), cumulativePremiumFraction, cumulativePremiumPerDtoken, posAccumulator, nextFundingTime, _blockTimestamp(), block.number ); } // Pure function abs(int x) internal pure returns (int) { return x >= 0 ? x : -x; } function _max(int x, int y) private pure returns (int) { return x >= y ? x : y; } // Governance function putAmmInIgnition() external onlyClearingHouse { ammState = AMMState.Ignition; } function changeOracle(address _oracle) public onlyGovernance { oracle = IOracle(_oracle); } function setFundingBufferPeriod(uint _fundingBufferPeriod) external onlyGovernance { fundingBufferPeriod = _fundingBufferPeriod; } function setUnbondPeriod(uint _unbondPeriod) external onlyGovernance { unbondPeriod = _unbondPeriod; } function setMaxOracleSpreadRatio(uint _maxOracleSpreadRatio) external onlyGovernance { maxOracleSpreadRatio = _maxOracleSpreadRatio; } function setLiquidationParams (uint _maxLiquidationRatio, uint _maxLiquidationPriceSpread) external onlyGovernance { maxLiquidationRatio = _maxLiquidationRatio; maxLiquidationPriceSpread = _maxLiquidationPriceSpread; } function setMinSizeRequirement(uint _minSizeRequirement) external onlyGovernance { minSizeRequirement = _minSizeRequirement; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol) pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits. * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a / b + (a % b == 0 ? 0 : 1); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; contract VanillaGovernable { address public governance; modifier onlyGovernance() { require(msg.sender == governance, "ONLY_GOVERNANCE"); _; } function setGovernace(address _governance) external onlyGovernance { _setGovernace(_governance); } function _setGovernace(address _governance) internal { governance = _governance; } } contract Governable is VanillaGovernable, Initializable {}
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IRegistry { function oracle() external view returns(address); function clearingHouse() external view returns(address); function vusd() external view returns(address); function insuranceFund() external view returns(address); function marginAccount() external view returns(address); } interface IOracle { function getUnderlyingPrice(address asset) external view returns(int256); function getUnderlyingTwapPrice(address asset, uint256 intervalInSeconds) external view returns (int256); } interface IClearingHouse { enum Mode { Maintenance_Margin, Min_Allowable_Margin } function openPosition(uint idx, int256 baseAssetQuantity, uint quoteAssetLimit) external; function closePosition(uint idx, uint quoteAssetLimit) external; function addLiquidity(uint idx, uint256 baseAssetQuantity, uint minDToken) external returns (uint dToken); function removeLiquidity(uint idx, uint256 dToken, uint minQuoteValue, uint minBaseValue) external; function settleFunding() external; function getTotalNotionalPositionAndUnrealizedPnl(address trader, int256 margin, Mode mode) external view returns(uint256 notionalPosition, int256 unrealizedPnl); function isAboveMaintenanceMargin(address trader) external view returns(bool); function assertMarginRequirement(address trader) external view; function updatePositions(address trader) external; function getMarginFraction(address trader) external view returns(int256); function getTotalFunding(address trader) external view returns(int256 totalFunding); function getAmmsLength() external view returns(uint); function amms(uint idx) external view returns(IAMM); function maintenanceMargin() external view returns(int256); function minAllowableMargin() external view returns(int256); function tradeFee() external view returns(uint256); function liquidationPenalty() external view returns(uint256); function getNotionalPositionAndMargin(address trader, bool includeFundingPayments, Mode mode) external view returns(uint256 notionalPosition, int256 margin); function isMaker(address trader) external view returns(bool); function liquidate(address trader) external; function liquidateMaker(address trader) external; function liquidateTaker(address trader) external; function commitLiquidity(uint idx, uint quoteAsset) external; function insuranceFund() external view returns(IInsuranceFund); function calcMarginFraction(address trader, bool includeFundingPayments, Mode mode) external view returns(int256); } interface ERC20Detailed { function decimals() external view returns (uint8); } interface IInsuranceFund { function seizeBadDebt(uint amount) external; function startAuction(address token) external; function calcVusdAmountForAuction(address token, uint amount) external view returns(uint); function buyCollateralFromAuction(address token, uint amount) external; } interface IAMM { struct Maker { uint vUSD; uint vAsset; uint dToken; int pos; // position int posAccumulator; // value of global.posAccumulator until which pos has been updated int lastPremiumFraction; int lastPremiumPerDtoken; uint unbondTime; uint unbondAmount; uint ignition; } struct Ignition { uint quoteAsset; uint baseAsset; uint dToken; } /** * @dev We do not deliberately have a Pause state. There is only a master-level pause at clearingHouse level */ enum AMMState { Inactive, Ignition, Active } function ammState() external view returns(AMMState); function ignition() external view returns(uint quoteAsset, uint baseAsset, uint dToken); function getIgnitionShare(uint vUSD) external view returns (uint vAsset, uint dToken); function openPosition(address trader, int256 baseAssetQuantity, uint quoteAssetLimit) external returns (int realizedPnl, uint quoteAsset, bool isPositionIncreased); function addLiquidity(address trader, uint baseAssetQuantity, uint minDToken) external returns (uint dToken); function removeLiquidity(address maker, uint amount, uint minQuote, uint minBase) external returns (int /* realizedPnl */, uint /* makerOpenNotional */, int /* makerPosition */); function forceRemoveLiquidity(address maker) external returns (int realizedPnl, uint makerOpenNotional, int makerPosition); function getNotionalPositionAndUnrealizedPnl(address trader) external view returns(uint256 notionalPosition, int256 unrealizedPnl, int256 size, uint256 openNotional); function updatePosition(address trader) external returns(int256 fundingPayment); function liquidatePosition(address trader) external returns (int realizedPnl, uint quoteAsset); function settleFunding() external; function underlyingAsset() external view returns (address); function positions(address trader) external view returns (int256,uint256,int256,uint256); function getCloseQuote(int256 baseAssetQuantity) external view returns(uint256 quoteAssetQuantity); function getTakerNotionalPositionAndUnrealizedPnl(address trader) external view returns(uint takerNotionalPosition, int256 unrealizedPnl); function getPendingFundingPayment(address trader) external view returns( int256 takerFundingPayment, int256 makerFundingPayment, int256 latestCumulativePremiumFraction, int256 latestPremiumPerDtoken ); function getOpenNotionalWhileReducingPosition(int256 positionSize, uint256 notionalPosition, int256 unrealizedPnl, int256 baseAssetQuantity) external pure returns(uint256 remainOpenNotional, int realizedPnl); function makers(address maker) external view returns(Maker memory); function vamm() external view returns(IVAMM); function commitLiquidity(address maker, uint quoteAsset) external; function putAmmInIgnition() external; function isOverSpreadLimit() external view returns (bool); function getOracleBasedPnl(address trader, int256 margin, IClearingHouse.Mode mode) external view returns (uint, int256); } interface IMarginAccount { struct Collateral { IERC20 token; uint weight; uint8 decimals; } enum LiquidationStatus { IS_LIQUIDATABLE, OPEN_POSITIONS, NO_DEBT, ABOVE_THRESHOLD } function addMargin(uint idx, uint amount) external; function addMarginFor(uint idx, uint amount, address to) external; function removeMargin(uint idx, uint256 amount) external; function getSpotCollateralValue(address trader) external view returns(int256 spot); function weightedAndSpotCollateral(address trader) external view returns(int256, int256); function getNormalizedMargin(address trader) external view returns(int256); function realizePnL(address trader, int256 realizedPnl) external; function isLiquidatable(address trader, bool includeFunding) external view returns(LiquidationStatus, uint, uint); function supportedAssetsLen() external view returns(uint); function supportedAssets() external view returns (Collateral[] memory); function margin(uint idx, address trader) external view returns(int256); function transferOutVusd(address recipient, uint amount) external; function liquidateExactRepay(address trader, uint repay, uint idx, uint minSeizeAmount) external; } interface IVAMM { function balances(uint256) external view returns (uint256); function get_dy( uint256 i, uint256 j, uint256 dx ) external view returns (uint256); function get_dx( uint256 i, uint256 j, uint256 dy ) external view returns (uint256); function exchange( uint256 i, uint256 j, uint256 dx, uint256 min_dy ) external returns (uint256 dy, uint256 last_price); function exchangeExactOut( uint256 i, uint256 j, uint256 dy, uint256 max_dx ) external returns (uint256 dx, uint256 last_price); function get_notional(uint256 makerDToken, uint256 vUSD, uint256 vAsset, int256 takerPosSize, uint256 takerOpenNotional) external view returns (uint256, int256, int256, uint256); function last_prices() external view returns(uint256); function mark_price() external view returns(uint256); function price_oracle() external view returns(uint256); function price_scale() external view returns(uint256); function add_liquidity(uint256[2] calldata amounts, uint256 min_mint_amount) external returns (uint256); function calc_token_amount(uint256[2] calldata amounts, bool deposit) external view returns (uint256); function remove_liquidity( uint256 amount, uint256[2] calldata minAmounts, uint256 vUSD, uint256 vAsset, uint256 makerDToken, int256 takerPosSize, uint256 takerOpenNotional ) external returns (int256, uint256, uint256, int256, uint[2] calldata); function get_maker_position(uint256 amount, uint256 vUSD, uint256 vAsset, uint256 makerDToken) external view returns (int256, uint256, int256); function totalSupply() external view returns (uint256); function setinitialPrice(uint) external; } interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } interface IERC20FlexibleSupply is IERC20 { function mint(address to, uint256 amount) external; function burn(uint256 amount) external; } interface IVUSD is IERC20 { function mintWithReserve(address to, uint amount) external; } interface IUSDC is IERC20FlexibleSupply { function masterMinter() external view returns(address); function configureMinter(address minter, uint256 minterAllowedAmount) external; } interface IHubbleViewer { function getMakerPositionAndUnrealizedPnl(address _maker, uint idx) external view returns (int256 position, uint openNotional, int256 unrealizedPnl); function clearingHouse() external returns(IClearingHouse); function marginAccount() external returns(IMarginAccount); } interface IHubbleReferral { function getTraderRefereeInfo(address trader) external view returns (address referrer); } interface IJoeRouter02 { function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function factory() external returns(address); function getAmountsIn(uint256 amountOut, address[] calldata path) external returns (uint256[] memory amounts); function getAmountsOut(uint256 amountOut, address[] calldata path) external returns (uint256[] memory amounts); } interface IJoePair { function swap( uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data ) external; } interface IJoeFactory { function getPair(address tokenA, address tokenB) external view returns (address pair); } interface IWAVAX is IERC20 { function deposit() external payable; function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !Address.isContract(address(this)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
{ "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_clearingHouse","type":"address"},{"internalType":"uint256","name":"_unbondRoundOff","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"int256","name":"takerFundingPayment","type":"int256"},{"indexed":false,"internalType":"int256","name":"makerFundingPayment","type":"int256"}],"name":"FundingPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int256","name":"premiumFraction","type":"int256"},{"indexed":false,"internalType":"uint256","name":"underlyingPrice","type":"uint256"},{"indexed":false,"internalType":"int256","name":"cumulativePremiumFraction","type":"int256"},{"indexed":false,"internalType":"int256","name":"cumulativePremiumPerDtoken","type":"int256"},{"indexed":false,"internalType":"int256","name":"posAccumulator","type":"int256"},{"indexed":false,"internalType":"uint256","name":"nextFundingTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"FundingRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256","name":"dToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseAsset","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quoteAsset","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LiquidityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256","name":"dToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseAsset","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quoteAsset","type":"uint256"},{"indexed":false,"internalType":"int256","name":"realizedPnl","type":"int256"},{"indexed":false,"internalType":"bool","name":"isLiquidation","type":"bool"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LiquidityRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"components":[{"internalType":"uint256","name":"vUSD","type":"uint256"},{"internalType":"uint256","name":"vAsset","type":"uint256"},{"internalType":"uint256","name":"dToken","type":"uint256"},{"internalType":"int256","name":"pos","type":"int256"},{"internalType":"int256","name":"posAccumulator","type":"int256"},{"internalType":"int256","name":"lastPremiumFraction","type":"int256"},{"internalType":"int256","name":"lastPremiumPerDtoken","type":"int256"},{"internalType":"uint256","name":"unbondTime","type":"uint256"},{"internalType":"uint256","name":"unbondAmount","type":"uint256"},{"internalType":"uint256","name":"ignition","type":"uint256"}],"indexed":false,"internalType":"struct IAMM.Maker","name":"maker","type":"tuple"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MakerPositionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"int256","name":"size","type":"int256"},{"indexed":false,"internalType":"uint256","name":"openNotional","type":"uint256"},{"indexed":false,"internalType":"int256","name":"realizedPnl","type":"int256"}],"name":"PositionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lastPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"openInterestNotional","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256","name":"unbondAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unbondTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Unbonded","type":"event"},{"inputs":[{"internalType":"address","name":"maker","type":"address"},{"internalType":"uint256","name":"baseAssetQuantity","type":"uint256"},{"internalType":"uint256","name":"minDToken","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"dToken","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ammState","outputs":[{"internalType":"enum IAMM.AMMState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_oracle","type":"address"}],"name":"changeOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clearingHouse","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"maker","type":"address"},{"internalType":"uint256","name":"quoteAsset","type":"uint256"}],"name":"commitLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cumulativePremiumFraction","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cumulativePremiumPerDtoken","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"maker","type":"address"}],"name":"forceRemoveLiquidity","outputs":[{"internalType":"int256","name":"realizedPnl","type":"int256"},{"internalType":"uint256","name":"makerOpenNotional","type":"uint256"},{"internalType":"int256","name":"makerPosition","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundingBufferPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"baseAssetQuantity","type":"int256"}],"name":"getCloseQuote","outputs":[{"internalType":"uint256","name":"quoteAssetQuantity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vUSD","type":"uint256"}],"name":"getIgnitionShare","outputs":[{"internalType":"uint256","name":"vAsset","type":"uint256"},{"internalType":"uint256","name":"dToken","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"getNotionalPositionAndUnrealizedPnl","outputs":[{"internalType":"uint256","name":"notionalPosition","type":"uint256"},{"internalType":"int256","name":"unrealizedPnl","type":"int256"},{"internalType":"int256","name":"size","type":"int256"},{"internalType":"uint256","name":"openNotional","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"positionSize","type":"int256"},{"internalType":"uint256","name":"newNotionalPosition","type":"uint256"},{"internalType":"int256","name":"unrealizedPnl","type":"int256"},{"internalType":"int256","name":"baseAssetQuantity","type":"int256"}],"name":"getOpenNotionalWhileReducingPosition","outputs":[{"internalType":"uint256","name":"remainOpenNotional","type":"uint256"},{"internalType":"int256","name":"realizedPnl","type":"int256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"int256","name":"margin","type":"int256"},{"internalType":"enum IClearingHouse.Mode","name":"mode","type":"uint8"}],"name":"getOracleBasedPnl","outputs":[{"internalType":"uint256","name":"notionalPosition","type":"uint256"},{"internalType":"int256","name":"unrealizedPnl","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"getPendingFundingPayment","outputs":[{"internalType":"int256","name":"takerFundingPayment","type":"int256"},{"internalType":"int256","name":"makerFundingPayment","type":"int256"},{"internalType":"int256","name":"latestCumulativePremiumFraction","type":"int256"},{"internalType":"int256","name":"latestPremiumPerDtoken","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSnapshotLen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"getTakerNotionalPositionAndUnrealizedPnl","outputs":[{"internalType":"uint256","name":"takerNotionalPosition","type":"uint256"},{"internalType":"int256","name":"unrealizedPnl","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_intervalInSeconds","type":"uint256"}],"name":"getTwapPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_intervalInSeconds","type":"uint256"}],"name":"getUnderlyingTwapPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ignition","outputs":[{"internalType":"uint256","name":"quoteAsset","type":"uint256"},{"internalType":"uint256","name":"baseAsset","type":"uint256"},{"internalType":"uint256","name":"dToken","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_underlyingAsset","type":"address"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"uint256","name":"_minSizeRequirement","type":"uint256"},{"internalType":"address","name":"_vamm","type":"address"},{"internalType":"address","name":"_governance","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOverSpreadLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liftOff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"liquidatePosition","outputs":[{"internalType":"int256","name":"realizedPnl","type":"int256"},{"internalType":"uint256","name":"quoteAsset","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"longOpenInterestNotional","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"maker","type":"address"}],"name":"makers","outputs":[{"components":[{"internalType":"uint256","name":"vUSD","type":"uint256"},{"internalType":"uint256","name":"vAsset","type":"uint256"},{"internalType":"uint256","name":"dToken","type":"uint256"},{"internalType":"int256","name":"pos","type":"int256"},{"internalType":"int256","name":"posAccumulator","type":"int256"},{"internalType":"int256","name":"lastPremiumFraction","type":"int256"},{"internalType":"int256","name":"lastPremiumPerDtoken","type":"int256"},{"internalType":"uint256","name":"unbondTime","type":"uint256"},{"internalType":"uint256","name":"unbondAmount","type":"uint256"},{"internalType":"uint256","name":"ignition","type":"uint256"}],"internalType":"struct IAMM.Maker","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLiquidationPriceSpread","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLiquidationRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxOracleSpreadRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minSizeRequirement","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextFundingTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openInterestNotional","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"int256","name":"baseAssetQuantity","type":"int256"},{"internalType":"uint256","name":"quoteAssetLimit","type":"uint256"}],"name":"openPosition","outputs":[{"internalType":"int256","name":"realizedPnl","type":"int256"},{"internalType":"uint256","name":"quoteAsset","type":"uint256"},{"internalType":"bool","name":"isPositionIncreased","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"posAccumulator","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"positions","outputs":[{"internalType":"int256","name":"size","type":"int256"},{"internalType":"uint256","name":"openNotional","type":"uint256"},{"internalType":"int256","name":"lastPremiumFraction","type":"int256"},{"internalType":"uint256","name":"liquidationThreshold","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"putAmmInIgnition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"maker","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minQuote","type":"uint256"},{"internalType":"uint256","name":"minBase","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"int256","name":"realizedPnl","type":"int256"},{"internalType":"uint256","name":"makerOpenNotional","type":"uint256"},{"internalType":"int256","name":"makerPosition","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"reserveSnapshots","outputs":[{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bool","name":"isLiquidation","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fundingBufferPeriod","type":"uint256"}],"name":"setFundingBufferPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governance","type":"address"}],"name":"setGovernace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLiquidationRatio","type":"uint256"},{"internalType":"uint256","name":"_maxLiquidationPriceSpread","type":"uint256"}],"name":"setLiquidationParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxOracleSpreadRatio","type":"uint256"}],"name":"setMaxOracleSpreadRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minSizeRequirement","type":"uint256"}],"name":"setMinSizeRequirement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unbondPeriod","type":"uint256"}],"name":"setUnbondPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleFunding","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shortOpenInterestNotional","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"spotPriceTwapInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dToken","type":"uint256"}],"name":"unbondLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unbondPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unbondRoundOff","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"updatePosition","outputs":[{"internalType":"int256","name":"fundingPayment","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vamm","outputs":[{"internalType":"contract IVAMM","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b50604051620057a4380380620057a483398101604081905262000034916200004b565b6001600160a01b0390911660805260a05262000087565b600080604083850312156200005f57600080fd5b82516001600160a01b03811681146200007757600080fd5b6020939093015192949293505050565b60805160a0516156b1620000f36000396000818161041701526120dd0152600081816104530152818161097f01528181610bd0015281816110e7015281816118050152818161197d015281816124cc01528181612c400152818161317f015261330601526156b16000f3fe608060405234801561001057600080fd5b50600436106103995760003560e01c806362307f44116101e9578063b0200bf41161010f578063e098372c116100ad578063f5a1854a1161007c578063f5a1854a1461086b578063f5c122d41461087e578063f68cd81014610887578063fc0c5ff1146108a157600080fd5b8063e098372c1461082a578063e0beac771461083d578063ed83d79c14610850578063f1b5df861461085857600080fd5b8063bb6e6e53116100e9578063bb6e6e53146107fc578063c2de442f14610805578063c6e7275d1461080e578063e0037a6c1461082157600080fd5b8063b0200bf4146107a6578063b72e1b48146107d6578063bab45f62146107e957600080fd5b80638f5ca38a11610187578063975a6c6111610156578063975a6c61146107555780639af16a95146107685780639cc7fcb61461077b5780639e0103621461078e57600080fd5b80638f5ca38a14610715578063905bb7721461072857806393531f131461073057806393ca2f8a1461074257600080fd5b806374d7c62b116101c357806374d7c62b146106a45780637dc0d1d0146106dc578063851e3ca5146106ef5780638f58f48b1461070257600080fd5b806362307f44146106ad5780637158da7c146106b65780637498a0f0146106c957600080fd5b80632300c1ff116102ce57806345d089131161026c57806355f575101161023b57806355f575101461062e57806355fa3245146106635780635aa6e675146106915780635f1ba1fd146106a457600080fd5b806345d08913146105ec57806347c421b5146105f557806355776b771461060857806355edfbfe1461061b57600080fd5b8063362aecb1116102a8578063362aecb11461054557806337292b60146105d15780633d385e4f146105da5780633fb7b029146105e357600080fd5b80632300c1ff146105175780632565382b1461052a578063349532491461053257600080fd5b80630af968001161033b5780631409136011610315578063140913601461049e57806316f086b7146104a6578063210fdd87146104d957806321e00985146104e257600080fd5b80630af968001461044e5780630d451c8f1461048d57806312eb4f9a1461049557600080fd5b80630413f2b6116103775780630413f2b6146103e2578063053f14da1461040a5780630574f8991461041257806306fdde031461043957600080fd5b806301e3e75d1461039e578063029acde0146103b3578063030a60e6146103cf575b600080fd5b6103b16103ac366004614d61565b6108aa565b005b6103bc600b5481565b6040519081526020015b60405180910390f35b6103b16103dd366004614d91565b61090e565b6103f56103f0366004614d61565b610a54565b604080519283526020830191909152016103c6565b6103bc610a9a565b6103bc7f000000000000000000000000000000000000000000000000000000000000000081565b610441610b37565b6040516103c69190614dbb565b6104757f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103c6565b6013546103bc565b6103bc60115481565b6103b1610bc5565b6104b96104b4366004614e2e565b610c6a565b6040805194855260208501939093529183015260608201526080016103c6565b6103bc60185481565b6104f56104f0366004614d61565b610e0a565b60408051948552602085019390935291830152151560608201526080016103c6565b6103b1610525366004614d61565b610e47565b6103bc610ea6565b6103bc610540366004614d61565b610eb8565b610558610553366004614e2e565b610f63565b6040516103c69190600061014082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151818401525092915050565b6103bc600c5481565b6103bc60075481565b6103bc600a5481565b6103bc600d5481565b6103b1610603366004614e2e565b611046565b6103bc610616366004614e49565b6110da565b6103b1610629366004614efa565b6115fa565b6104b961063c366004614e2e565b600f6020526000908152604090208054600182015460028301546003909301549192909184565b610676610671366004614e2e565b6117f6565b604080519384526020840192909252908201526060016103c6565b600054610475906001600160a01b031681565b6103bc610e1081565b6103bc60095481565b600354610475906001600160a01b031681565b6103f56106d7366004614e2e565b61196f565b600154610475906001600160a01b031681565b6103b16106fd366004614e2e565b611c8b565b6103f5610710366004614ff8565b611d1b565b6103b1610723366004614d61565b611f9f565b6103b1612176565b60145460155460165461067692919083565b61067661075036600461503c565b6124bd565b6103f5610763366004614e2e565b612785565b6103f5610776366004615075565b6129ad565b6103b1610789366004614d61565b612aa4565b610796612b03565b60405190151581526020016103c6565b6107b96107b4366004614e49565b612c31565b6040805193845260208401929092521515908201526060016103c6565b6104b96107e4366004614e2e565b612ec8565b6103b16107f7366004614d61565b6130ae565b6103bc600e5481565b6103bc60055481565b6103b161081c3660046150a7565b61310d565b6103bc60065481565b600254610475906001600160a01b031681565b6103bc61084b366004614e2e565b613172565b6103b16132fb565b6103bc610866366004614d61565b6134aa565b6103bc610879366004614d61565b6134bd565b6103bc60085481565b6017546108949060ff1681565b6040516103c691906150f8565b6103bc60125481565b6000546001600160a01b031633146109095760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e4345000000000000000000000000000000000060448201526064015b60405180910390fd5b601855565b600160175460ff166002811115610927576109276150c9565b146109745760405162461bcd60e51b815260206004820152601060248201527f616d6d5f6e6f745f69676e6974696f6e000000000000000000000000000000006044820152606401610900565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109ec5760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b6109f7600282615197565b6001600160a01b038316600090815260106020526040812060090180549293508392909190610a279084906151ab565b909155505060148054829190600090610a419084906151ab565b90915550610a50905082613560565b5050565b6014546015546000918291610a6a9085906151c3565b610a749190615197565b60145460165491935090610a899085906151c3565b610a939190615197565b9050915091565b600064e8d4a51000600260009054906101000a90046001600160a01b03166001600160a01b031663377d8fbe6040518163ffffffff1660e01b815260040160206040518083038186803b158015610af057600080fd5b505afa158015610b04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b289190615200565b610b329190615197565b905090565b60048054610b4490615219565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7090615219565b8015610bbd5780601f10610b9257610100808354040283529160200191610bbd565b820191906000526020600020905b815481529060010190602001808311610ba057829003601f168201915b505050505081565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c3d5760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b601780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000808080600160175460ff166002811115610c8857610c886150c9565b1415610cc7576001600160a01b038516600090815260106020526040902060090154610cb59060026151c3565b60008060009350935093509350610e03565b6001600160a01b03851660009081526010602052604081206009015490808215610cfe57610cf483610a54565b9092509050610d2a565b5050506001600160a01b0385166000908152601060205260409020805460018201546002909201549091905b6002546001600160a01b038981166000908152600f602052604090819020805460019091015491517f5702d1f500000000000000000000000000000000000000000000000000000000815260048101869052602481018890526044810187905260648101919091526084810191909152911690635702d1f59060a40160806040518083038186803b158015610dbe57600080fd5b505afa158015610dd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df6919061526d565b9299509750955093505050505b9193509193565b60138181548110610e1a57600080fd5b60009182526020909120600490910201805460018201546002830154600390930154919350919060ff1684565b6000546001600160a01b03163314610ea15760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e434500000000000000000000000000000000006044820152606401610900565b600555565b6000600b54600a54610b3291906151ab565b6001546003546040517fd6b28b5f0000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260248101849052600092919091169063d6b28b5f906044015b60206040518083038186803b158015610f2557600080fd5b505afa158015610f39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5d9190615200565b92915050565b610fb9604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b506001600160a01b0316600090815260106020908152604091829020825161014081018452815481526001820154928101929092526002810154928201929092526003820154606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460e0820152600882015461010082015260099091015461012082015290565b6000546001600160a01b031633146110a05760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e434500000000000000000000000000000000006044820152606401610900565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111545760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b600260175460ff16600281111561116d5761116d6150c9565b146111ba5760405162461bcd60e51b815260206004820152600e60248201527f616d6d5f6e6f745f6163746976650000000000000000000000000000000000006044820152606401610900565b60185483101561120c5760405162461bcd60e51b815260206004820152600f60248201527f616464696e675f746f6f5f6c65737300000000000000000000000000000000006044820152606401610900565b6002546040517f4903b0d10000000000000000000000000000000000000000000000000000000081526001600482015260009182916001600160a01b0390911690634903b0d19060240160206040518083038186803b15801561126e57600080fd5b505afa158015611282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a69190615200565b90508061136a57600254604080517fb9e8c9fd00000000000000000000000000000000000000000000000000000000815290516c0c9f2c9cd04674edea40000000926001600160a01b03169163b9e8c9fd916004808301926020929190829003018186803b15801561131757600080fd5b505afa15801561132b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134f9190615200565b61135990876151c3565b6113639190615197565b9150611416565b6002546040517f4903b0d10000000000000000000000000000000000000000000000000000000081526000600482015282916001600160a01b031690634903b0d19060240160206040518083038186803b1580156113c757600080fd5b505afa1580156113db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ff9190615200565b61140990876151c3565b6114139190615197565b91505b6002546040805180820182528481526020810188905290517f0b4c7e4d0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691630b4c7e4d916114719188906004016152cc565b602060405180830381600087803b15801561148b57600080fd5b505af115801561149f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c39190615200565b6001600160a01b03871660009081526010602052604090206002810154919450901561153e57670de0b6b3a76400006114ff826002015461361d565b826004015460095461151191906152e7565b61151b919061535b565b6115259190615417565b816003016000828254611538919061547f565b90915550505b8281600001600082825461155291906151ab565b925050819055508581600101600082825461156d91906151ab565b925050819055508381600201600082825461158891906151ab565b9091555050600954600482015561159e87613560565b6001600160a01b0387167f08d7621a09a86934f387f650007fa17f2413759ca5f2ae0681161b371583a5f58588864260408051948552602085019390935291830152606082015260800160405180910390a25050509392505050565b6000547501000000000000000000000000000000000000000000900460ff166116415760005474010000000000000000000000000000000000000000900460ff1615611645565b303b155b6116b75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610900565b6000547501000000000000000000000000000000000000000000900460ff1615801561171e57600080547fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff1675010100000000000000000000000000000000000000001790555b86516117319060049060208a0190614cd1565b50600380547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b0389811691909117909255600180548216888416179055601886905560028054821686841617905560008054909116918416919091179055610384600555620151806011556014600c556203f4806012556019600d55620f4240600e5580156117ed57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1690555b50505050505050565b60008080336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146118725760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b6001600160a01b0384166000908152601060205260409020600260175460ff1660028111156118a3576118a36150c9565b141561190d576040805160608101825260008082526020820152600191810191909152600282015460088301546118db9082906136b9565b8360080160008282546118ee91906154f3565b909155506118ff90508782846136d1565b955095509550505050611968565b6001600160a01b038516600090815260106020526040812060090154601480549192909161193c9084906154f3565b90915550506001600160a01b03851660009081526010602052604081206009015561196685613560565b505b9193909250565b600080336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146119ea5760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b6001600160a01b0383166000908152600f602090815260408083208151608081018352815480825260018301549482019490945260028201549281019290925260030154606082015291908112611a42576000611a45565b60015b90506000611a63611a598460000151613a9e565b84606001516136b9565b601354909150600090611a78906001906154f3565b9050600060138281548110611a8f57611a8f61550a565b90600052602060002090600402016000015490505b4360138381548110611ab857611ab861550a565b906000526020600020906004020160020154148015611ad657508115155b15611b6f5760138281548110611aee57611aee61550a565b600091825260209091206003600490920201015460ff1615611b365760138281548110611b1d57611b1d61550a565b9060005260206000209060040201600001549050611b6f565b611b416001836154f3565b915060138281548110611b5657611b5661550a565b9060005260206000209060040201600001549050611aa4565b6000611b79610a9a565b9050818110611b9357611b8c82826154f3565b9050611ba0565b611b9d81836154f3565b90505b6305f5e100600e5483611bb391906151c3565b611bbd9190615197565b811115611c0c5760405162461bcd60e51b815260206004820152601e60248201527f414d4d2e6c69717569646174696f6e5f70726963655f736c69707061676500006044820152606401610900565b8415611c3b57611c3189611c1f8661361d565b611c2890615539565b60006001613ab6565b9098509650611c76565b611c7089611c488661361d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001613ab6565b90985096505b611c808989613bb9565b505050505050915091565b6000546001600160a01b03163314611ce55760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e434500000000000000000000000000000000006044820152606401610900565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03831617905550565b6001600160a01b038316600090815260106020908152604080832081516101408101835281548152600180830154948201949094526002820154928101929092526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600881015461010083015260090154610120820152829160175460ff166002811115611dbc57611dbc6150c9565b1415611ddf57610120810151611dd39060026151c3565b60009250925050611f97565b6001600160a01b038681166000908152600f602090815260408083208151608081018352815480825260018301548286018190526002808501548487015260039094015460608401529254888501518951968a015195517f5702d1f500000000000000000000000000000000000000000000000000000000815260048101919091526024810196909652604486019490945260648501526084840191909152938392911690635702d1f59060a40160806040518083038186803b158015611ea557600080fd5b505afa158015611eb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611edd919061526d565b92985096509250905085611efb576000809550955050505050611f97565b6000611f068761361d565b611f10878b61547f565b611f1d90620f424061535b565b611f279190615417565b90506000806000611f3a8d8d8789613c45565b9194509250905060008b6001811115611f5557611f556150c9565b1415611f775783811315611f7257611f6c83613e0d565b99508198505b611f8e565b83811215611f8e57611f8883613e0d565b99508198505b50505050505050505b935093915050565b600260175460ff166002811115611fb857611fb86150c9565b146120055760405162461bcd60e51b815260206004820152600e60248201527f616d6d5f6e6f745f6163746976650000000000000000000000000000000000006044820152606401610900565b3361200f81613e5f565b61201881613560565b6001600160a01b03811660009081526010602052604090208261207d5760405162461bcd60e51b815260206004820152600b60248201527f756e626f6e64696e675f300000000000000000000000000000000000000000006044820152606401610900565b82816002015410156120d15760405162461bcd60e51b815260206004820152601260248201527f756e626f6e64696e675f746f6f5f6d75636800000000000000000000000000006044820152606401610900565b600881018390556012547f000000000000000000000000000000000000000000000000000000000000000090819061210990426151ab565b6121139190615197565b61211d91906151c3565b6007820181905560408051858152602081019290925242908201526001600160a01b038316907ffcc4bc9c6b8463463bcbae7de4078e3ef39ab55315563076c4061fc68ad41337906060015b60405180910390a2505050565b6000546001600160a01b031633146121d05760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e434500000000000000000000000000000000006044820152606401610900565b600160175460ff1660028111156121e9576121e96150c9565b146122365760405162461bcd60e51b815260206004820152601060248201527f616d6d5f6e6f745f69676e6974696f6e000000000000000000000000000000006044820152606401610900565b600061224b612246610384610eb8565b613e0d565b9050600081116122c35760405162461bcd60e51b815260206004820152602360248201527f616d6d2e6c6966744f66662e756e6465726c79696e6750726963655f6e6f745f60448201527f73657400000000000000000000000000000000000000000000000000000000006064820152608401610900565b6002546001600160a01b031663a5debf0e6122e38364e8d4a510006151c3565b6040518263ffffffff1660e01b815260040161230191815260200190565b600060405180830381600087803b15801561231b57600080fd5b505af115801561232f573d6000803e3d6000fd5b5050601454159150612467905057601454819061235490670de0b6b3a76400006151c3565b61235e9190615197565b601581905560025460408051808201825260145481526020810193909352517f0b4c7e4d0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911691630b4c7e4d916123c291906000906004016152cc565b602060405180830381600087803b1580156123dc57600080fd5b505af11580156123f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124149190615200565b6016819055601554601454604080519384526020840192909252828201524260608301525130917f08d7621a09a86934f387f650007fa17f2413759ca5f2ae0681161b371583a5f5919081900360800190a25b601780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055610e1080426124a191906151ab565b6124ab9190615197565b6124b790610e106151c3565b60065550565b60008080336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146125395760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b6001600160a01b038716600090815260106020526040902060088101548711156125a55760405162461bcd60e51b815260206004820152601e60248201527f7769746864726177696e675f6d6f72655f7468616e5f756e626f6e64656400006044820152606401610900565b6008810180548890039055600781015442908110156126065760405162461bcd60e51b815260206004820152600f60248201527f7374696c6c5f756e626f6e64696e6700000000000000000000000000000000006044820152606401610900565b601154826007015461261891906151ab565b8111156126675760405162461bcd60e51b815260206004820152601460248201527f77697468647261775f706572696f645f6f7665720000000000000000000000006044820152606401610900565b604080516060810182528881526020810188905260009181019190915261268f8a8a836136d1565b600286015492985090965094501561277857601854836001015410156126f75760405162461bcd60e51b815260206004820152601e60248201527f6c6566746f7665725f6c69717569646974795f69735f746f6f5f6c65737300006044820152606401610900565b6001600160a01b038a166000908152600f602052604081205461271990613a9e565b905080158061272a57506018548110155b6127765760405162461bcd60e51b815260206004820152601d60248201527f72656d6f76696e675f766572795f736d616c6c5f6c69717569646974790000006044820152606401610900565b505b5050509450945094915050565b6001600160a01b0381166000908152600f602090815260408083208151608081018352815480825260018301549482019490945260028201549281019290925260030154606082015282918212156128ba5760025481516001600160a01b039091169063556d6e9f906001906000906127fd90613e0d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260640160206040518083038186803b15801561285957600080fd5b505afa15801561286d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128919190615200565b92506128a0816020015161361d565b6128a98461361d565b6128b391906152e7565b91506129a7565b8051600013156129a75760025481516001600160a01b03909116906337ed3a7a906000906001906128ee9061224690615539565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260640160206040518083038186803b15801561294a57600080fd5b505afa15801561295e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129829190615200565b925061298d8361361d565b61299a826020015161361d565b6129a491906152e7565b91505b50915091565b6000806129b983613a9e565b6129c287613a9e565b1215612a105760405162461bcd60e51b815260206004820152601360248201527f414d4d2e4f4e4c595f5245445543455f504f53000000000000000000000000006044820152606401610900565b6000808713612a20576000612a23565b60015b9050612a2e87613a9e565b612a3785613a9e565b612a41908761535b565b612a4b9190615417565b91506000612a5983876152e7565b90508115612a7f57612a7881612a6e8961361d565b61224691906152e7565b9350612a99565b612a9681612a8c8961361d565b612246919061547f565b93505b505094509492505050565b6000546001600160a01b03163314612afe5760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e434500000000000000000000000000000000006044820152606401610900565b600c55565b6000600260175460ff166002811115612b1e57612b1e6150c9565b14612b295750600090565b6001546003546040517ffc57d4df0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600092919091169063fc57d4df9060240160206040518083038186803b158015612b8e57600080fd5b505afa158015612ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc69190615200565b90506000612bd2610a9a565b9050600082821115612bef57612be883836154f3565b9050612bfc565b612bf982846154f3565b90505b82612c088260646151c3565b612c129190615197565b9050600c548110612c27576001935050505090565b6000935050505090565b60008080336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612cad5760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b600260175460ff166002811115612cc657612cc66150c9565b14612d135760405162461bcd60e51b815260206004820152600e60248201527f616d6d5f6e6f745f6163746976650000000000000000000000000000000000006044820152606401610900565b6001600160a01b0386166000908152600f6020908152604080832081516080810183528154808252600183015494820194909452600282015492810192909252600301546060820152919015612d6a576000612d6d565b60015b90506000808813612d7f576001612d82565b60005b90508180612dc35750806001811115612d9d57612d9d6150c9565b8351600012612dad576001612db0565b60005b6001811115612dc157612dc16150c9565b145b15612dde57612dd3898989613ebe565b945060019350612df1565b612de9898989613f92565b919750955093505b6001600160a01b0389166000908152600f6020526040812054612e1390613a9e565b9050801580612e2457506018548110155b612e705760405162461bcd60e51b815260206004820152601a60248201527f706f736974696f6e5f6c6573735f7468616e5f6d696e53697a650000000000006044820152606401610900565b612e956064600d5483612e8391906151c3565b612e8d9190615197565b6018546140a9565b6001600160a01b038b166000908152600f6020526040902060030155612ebb8a88613bb9565b5050505093509350939050565b6001600160a01b0381166000818152600f6020908152604080832081516080808201845282548252600180840154838701526002808501548487019081526003958601546060808701919091529989526010885286892087516101408101895281548152938101549884019890985290870154958201959095529285015496830196909652600484015495820195909552600583015460a0820152600683015460c082015260078084015460e083015260088085015461010084015260099094015461012083015254925485519251949586959193909291670de0b6b3a76400009190612fb590876152e7565b612fbf919061535b565b612fc99190615417565b6001600160a01b03881660009081526010602052604081206009015491975090801561300157612ff881610a54565b92506130099050565b826040015191505b81156130a35760008360a001518761302191906152e7565b9050670de0b6b3a76400006130358461361d565b670de0b6b3a764000083876080015161304e919061535b565b6130589190615417565b60c0870151613067908a6152e7565b61307191906152e7565b61307b919061535b565b82866060015161308b919061535b565b613095919061547f565b61309f9190615417565b9750505b505050509193509193565b6000546001600160a01b031633146131085760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e434500000000000000000000000000000000006044820152606401610900565b601255565b6000546001600160a01b031633146131675760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e434500000000000000000000000000000000006044820152606401610900565b600d91909155600e55565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146131ec5760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b600260175460ff166002811115613205576132056150c9565b1461321257506000919050565b61321b82613e5f565b6001600160a01b0382166000908152601060205260408120908061323e85612ec8565b60068701556005860155909250905061325685613560565b6001600160a01b0385166000908152600f6020526040902060058401546002820155613282828461547f565b945060008512156132a6576132996103e886615417565b6132a390866152e7565b94505b84156132f15760408051848152602081018490526001600160a01b038816917fedccdcc7969b9887e53177a1ae44af75a345795493795e21844486928c385e46910160405180910390a25b505050505b919050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146133735760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f75736500000000000000000000000000006044820152606401610900565b600260175460ff16600281111561338c5761338c6150c9565b14158061339a575060065442105b156133a157565b60006133ae610e10610eb8565b90506000816133be610e106134aa565b6133c891906152e7565b90506000620151806133dc610e108461535b565b6133e69190615417565b90506000816009546133f8919061535b565b905061340c670de0b6b3a764000082615417565b61341790600161547f565b9050816007600082825461342b919061547f565b925050819055508060086000828254613444919061547f565b909155505060055460009061345990426151ab565b90506000610e108060065461346e91906151ab565b6134789190615197565b61348490610e106151c3565b90508181116134935781613495565b805b6006556134a284876140b9565b505050505050565b6000610f5d6134b883614134565b61361d565b60008082131561352e576002546001600160a01b031663556d6e9f600160006134e586613e0d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b168152600481019390935260248301919091526044820152606401610f0d565b6000821215613558576002546001600160a01b03166337ed3a7a600060016134e561224687615539565b506000919050565b6001600160a01b03811660008181526010602052604090207f39e2cd703a0e0eee14b668bc716b6173d6d74486ae0d0cc712a6fd1e5558637690426040516136129291908254815260018301546020820152600283015460408201526003830154606082015260048301546080820152600583015460a0820152600683015460c0820152600783015460e082015260088301546101008201526009909201546101208301526101408201526101600190565b60405180910390a250565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156136b55760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e206160448201527f6e20696e743235360000000000000000000000000000000000000000000000006064820152608401610900565b5090565b60008183106136c857816136ca565b825b9392505050565b60008060008060106000886001600160a01b03166001600160a01b0316815260200190815260200160002090506000600f6000896001600160a01b03166001600160a01b03168152602001908152602001600020905060008060405180604001604052806000815260200160008152509050600260009054906101000a90046001600160a01b03166001600160a01b031663ed4519258a60405180604001604052808c6000015181526020018c6020015181525087600001548860010154896002015489600001548a600101546040518863ffffffff1660e01b81526004016137c09796959493929190615572565b60c060405180830381600087803b1580156137da57600080fd5b505af11580156137ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061381291906155b0565b6002890154919b5092995092975093509150600090613832908b906154f3565b905080613856576000600386018190556001860181905580865560028601556138ec565b670de0b6b3a76400006138688261361d565b866004015460095461387a91906152e7565b613884919061535b565b61388e9190615417565b856003015461389d919061547f565b6003860155600285015460018601546138b79083906151c3565b6138c19190615197565b6001860155600285015485546138d89083906151c3565b6138e29190615197565b8555600285018190555b5060095460048501558415613a1857825460009061390a908761535b565b1215613930576139238360000154846001015487614360565b61392d908861547f565b96505b6001830182905582548590849060009061394b90849061547f565b9091555050600d54835461396f9160649161396590613a9e565b612e8391906151c3565b600384015560008513156139a25761398685613e0d565b600a600082825461399791906151ab565b909155506139c59050565b6139ae61224686615539565b600b60008282546139bf91906151ab565b90915550505b7f015fc8ee969fd902d9ebd12a31c54446400a2b512a405366fe14defd6081d2206139ee610a9a565b6139f6610ea6565b6040805192835260208301919091520160405180910390a1613a188a88613bb9565b613a218a613560565b6020810151815160408a01516001600160a01b038d16927f3090ebd533f90973f113db832bb38306dcbd16ea80c1780b9f2121448b329409928d928c90426040805196875260208701959095529385019290925260608401521515608083015260a082015260c00160405180910390a25050505093509350939050565b6000808212156136b557613ab182615539565b610f5d565b6000806000613ac487612785565b6001600160a01b0389166000908152600f6020526040812080549294509250908112613af1576000613af4565b60015b90508015613b3157613b0861224689615539565b600a6000828254613b1991906154f3565b90915550613b2a9050888888614449565b9350613b5f565b613b3a88613e0d565b600b6000828254613b4b91906154f3565b90915550613b5c90508888886147c2565b93505b6000613b74898460000154610879919061547f565b9050613b86836000015482868c6129ad565b6001850191909155835490965089908490600090613ba590849061547f565b925050819055505050505094509492505050565b6001600160a01b0382166000818152600f6020908152604091829020825160808101845281548082526001830154938201849052600283015482860152600390920154606082015292519293927f9ffd1f40a44de66f6b3803ad672fbf4773eca3c1494ef736cb8007e14f9ea1e492612169929187909283526020830191909152604082015260600190565b6001546003546040517ffc57d4df0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152600092839283928392919091169063fc57d4df9060240160206040518083038186803b158015613cb057600080fd5b505afa158015613cc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ce89190615200565b9050670de0b6b3a7640000613cfc86613a9e565b613d06908361535b565b613d109190615417565b93506000851315613d3557613d248661361d565b613d2e90856152e7565b9250613d55565b6000851215613d555783613d488761361d565b613d5291906152e7565b92505b6001600160a01b0388166000908152600f6020526040812054670de0b6b3a764000090613d8190613a9e565b613d8b908461535b565b613d959190615417565b6001600160a01b038a16600090815260106020526040902054909150613ddb908290613dc09061361d565b613dcb90600261535b565b613dd5919061547f565b86614a19565b945084613de8858a61547f565b613df590620f424061535b565b613dff9190615417565b925050509450945094915050565b6000808212156136b55760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f7369746976656044820152606401610900565b6001600160a01b03811660009081526010602052604090206009015480613e84575050565b6001600160a01b0382166000908152601060205260409020818155613ea882610a54565b6002830155600182015560006009909101555050565b600080831315613efb57613ed183613e0d565b600a6000828254613ee291906151ab565b90915550613ef49050838360006147c2565b9050613f2d565b613f0761224684615539565b600b6000828254613f1891906151ab565b90915550613f2a905083836000614449565b90505b6001600160a01b0384166000908152600f602052604081208054859290613f5590849061547f565b90915550506001600160a01b0384166000908152600f602052604081206001018054839290613f859084906151ab565b9091555090949350505050565b6001600160a01b0383166000908152600f6020908152604080832081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015281908190613fe786613a9e565b8151613ff290613a9e565b1261400e576140048787876000613ab6565b909450925061409f565b600061401c61224688613a9e565b61402c6122468460000151613a9e565b61403690886151c3565b6140409190615197565b905061405c88836000015161405490615539565b836000613ab6565b90955093508386106140755761407284876154f3565b95505b815161408d908990614087908a61547f565b88613ebe565b61409790856151ab565b935060019250505b5093509350939050565b6000818310156136c857816136ca565b7f63e1c3bbc27ccaa3683a3c85a499d5547c8942bb17dabc9490d3b2cf2ec6a35a826140e483613e0d565b60075460085460095460065442604080519788526020880196909652948601939093526060850191909152608084015260a083015260c08201524360e08201526101000160405180910390a15050565b6013546000908190614148906001906154f3565b905060006013828154811061415f5761415f61550a565b90600052602060002090600402016000015490508360001415614183579392505050565b600061418f85426154f3565b90506000601384815481106141a6576141a661550a565b600091825260209182902060408051608081018252600490930290910180548352600180820154948401949094526002810154918301919091526003015460ff16151560608201526013549092501480614204575081816020015111155b15614213575090949350505050565b6020810151600061422482426154f3565b9050600061423282876151c3565b90505b86614251576142448282615197565b9998505050505050505050565b61425c6001886154f3565b9650601387815481106142715761427161550a565b60009182526020918290206040805160808101825260049093029091018054835260018101549383019390935260028301549082015260039091015460ff16151560608201526013805491955090889081106142cf576142cf61550a565b906000526020600020906004020160000154955084846020015111614313576142f885846154f3565b61430290876151c3565b61430c90826151ab565b9050614356565b600084602001518461432591906154f3565b905061433181886151c3565b61433b90836151ab565b915061434781846151ab565b92508460200151935050614235565b6142448982615197565b600080614370610879848761547f565b90506000614389612246614384888761547f565b613a9e565b905061439484613a9e565b61439d87613a9e565b131561440c5760006143b161224688613a9e565b6143bd61224687613a9e565b6143c790886151c3565b6143d19190615197565b90506000826143e261224688613a9e565b6143ec90866151c3565b6143f69190615197565b9050614403888284614a29565b94505050614440565b60008161441b61224689613a9e565b61442590856151c3565b61442f9190615197565b905061443c878288614a29565b9350505b50509392505050565b60008084126144c05760405162461bcd60e51b815260206004820152602660248201527f56414d4d2e5f73686f72743a206261736541737365745175616e74697479206960448201527f73203e3d203000000000000000000000000000000000000000000000000000006064820152608401610900565b6002546000906001600160a01b0316635b41b9086001836144e36122468a615539565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b168152600481019390935260248301919091526044820152606481018790526084016040805180830381600087803b15801561454757600080fd5b505af115801561455b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061457f9190615657565b6001546003546040517ffc57d4df0000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015293955091935060009291169063fc57d4df9060240160206040518083038186803b1580156145e857600080fd5b505afa1580156145fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146209190615200565b90506064600c54606461463391906154f3565b61463d90836151c3565b6146479190615197565b90508315801561465657508082105b156146a35760405162461bcd60e51b815260206004820152601f60248201527f56414d4d2e5f73686f72743a2073686f727473206e6f7420616c6c6f776564006044820152606401610900565b6146ad8285614a7a565b600254604080517f18160ddd0000000000000000000000000000000000000000000000000000000081529051614744926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561470c57600080fd5b505afa158015614720573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134b89190615200565b61475687670de0b6b3a764000061535b565b6147609190615417565b6009600082825461477191906152e7565b909155507f015fc8ee969fd902d9ebd12a31c54446400a2b512a405366fe14defd6081d2209050826147a1610ea6565b6040805192835260208301919091520160405180910390a150509392505050565b60008084136148395760405162461bcd60e51b815260206004820152602560248201527f56414d4d2e5f6c6f6e673a206261736541737365745175616e7469747920697360448201527f203c3d20300000000000000000000000000000000000000000000000000000006064820152608401610900565b6002546000906001600160a01b0316635e90cf0e82600161485989613e0d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b168152600481019390935260248301919091526044820152606481018790526084016040805180830381600087803b1580156148bd57600080fd5b505af11580156148d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148f59190615657565b6001546003546040517ffc57d4df0000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015293955091935060009291169063fc57d4df9060240160206040518083038186803b15801561495e57600080fd5b505afa158015614972573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149969190615200565b90506064600c5460646149a991906151ab565b6149b390836151c3565b6149bd9190615197565b9050831580156149cc57508082115b156146a35760405162461bcd60e51b815260206004820152601d60248201527f56414d4d2e5f6c6f6e673a206c6f6e6773206e6f7420616c6c6f7765640000006044820152606401610900565b6000818312156136c857816136ca565b600080841315614a5657614a3c8261361d565b614a458461361d565b614a4f91906152e7565b90506136ca565b614a5f8361361d565b614a688361361d565b614a7291906152e7565b949350505050565b60135443904290614b835760408051608081018252948552602085019182528401918252911515606084019081526013805460018101825560009190915293517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09060049095029485015591517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a091840155517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a092830155517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09390910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6013805460009190614b97906001906154f3565b81548110614ba757614ba761550a565b906000526020600020906004020190508060020154831415614bcb57848155614cca565b6040805160808101825286815260208101848152918101858152861515606083019081526013805460018101825560009190915292517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09060049094029384015592517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a091830155517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09282015590517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09390910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790555b5050505050565b828054614cdd90615219565b90600052602060002090601f016020900481019282614cff5760008555614d45565b82601f10614d1857805160ff1916838001178555614d45565b82800160010185558215614d45579182015b82811115614d45578251825591602001919060010190614d2a565b506136b59291505b808211156136b55760008155600101614d4d565b600060208284031215614d7357600080fd5b5035919050565b80356001600160a01b03811681146132f657600080fd5b60008060408385031215614da457600080fd5b614dad83614d7a565b946020939093013593505050565b600060208083528351808285015260005b81811015614de857858101830151858201604001528201614dcc565b81811115614dfa576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215614e4057600080fd5b6136ca82614d7a565b600080600060608486031215614e5e57600080fd5b614e6784614d7a565b95602085013595506040909401359392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614ef257614ef2614e7c565b604052919050565b60008060008060008060c08789031215614f1357600080fd5b863567ffffffffffffffff80821115614f2b57600080fd5b818901915089601f830112614f3f57600080fd5b8135602082821115614f5357614f53614e7c565b614f83817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601614eab565b92508183528b81838601011115614f9957600080fd5b81818501828501376000818385010152829950614fb7818c01614d7a565b985050505050614fc960408801614d7a565b935060608701359250614fde60808801614d7a565b9150614fec60a08801614d7a565b90509295509295509295565b60008060006060848603121561500d57600080fd5b61501684614d7a565b92506020840135915060408401356002811061503157600080fd5b809150509250925092565b6000806000806080858703121561505257600080fd5b61505b85614d7a565b966020860135965060408601359560600135945092505050565b6000806000806080858703121561508b57600080fd5b5050823594602084013594506040840135936060013592509050565b600080604083850312156150ba57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615133577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000826151a6576151a6615139565b500490565b600082198211156151be576151be615168565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151fb576151fb615168565b500290565b60006020828403121561521257600080fd5b5051919050565b600181811c9082168061522d57607f821691505b60208210811415615267577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b6000806000806080858703121561528357600080fd5b505082516020840151604085015160609095015191969095509092509050565b8060005b60028110156152c65781518452602093840193909101906001016152a7565b50505050565b606081016152da82856152a3565b8260408301529392505050565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561532157615321615168565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561535557615355615168565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561539c5761539c615168565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156153d7576153d7615168565b600087129250878205871284841616156153f3576153f3615168565b8785058712818416161561540957615409615168565b505050929093029392505050565b60008261542657615426615139565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561547a5761547a615168565b500590565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154b9576154b9615168565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156154ed576154ed615168565b50500190565b60008282101561550557615505615168565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007f800000000000000000000000000000000000000000000000000000000000000082141561556b5761556b615168565b5060000390565b878152610100810161558760208301896152a3565b6060820196909652608081019490945260a084019290925260c083015260e09091015292915050565b600080600080600060c086880312156155c857600080fd5b855194506020808701519450604087015193506060870151925087609f8801126155f157600080fd5b6040516040810181811067ffffffffffffffff8211171561561457615614614e7c565b6040528060c089018a81111561562957600080fd5b60808a015b81811015615645578051835291840191840161562e565b50505080925050509295509295909350565b6000806040838503121561566a57600080fd5b50508051602090910151909290915056fea264697066735822122066f243e3120fedcebae04e5daf98bda0e1253993bf5f88974dac46db9946b74c64736f6c634300080900330000000000000000000000004e3535964cb5612a466d8bb25362d485452efcef0000000000000000000000000000000000000000000000000000000000015180
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004e3535964cb5612a466d8bb25362d485452efcef0000000000000000000000000000000000000000000000000000000000015180
-----Decoded View---------------
Arg [0] : _clearingHouse (address): 0x4e3535964cb5612a466d8bb25362d485452efcef
Arg [1] : _unbondRoundOff (uint256): 86400
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004e3535964cb5612a466d8bb25362d485452efcef
Arg [1] : 0000000000000000000000000000000000000000000000000000000000015180
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.