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] | |||
---|---|---|---|---|---|---|---|---|---|
0xdf19ef050d9ceace05c8bc4e4f06b8080561106cda67ba9c23385b354cfb05d6 | 0x60a06040 | 18291001 | 11 days 17 hrs ago | 0xf5c8e1eaffd278a383c13061b4980db7619479af | IN | Create: MarginAccount | 0 AVAX | 0.09793785 |
[ Download CSV Export ]
Contract Name:
MarginAccount
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 { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import { HubbleBase } from "./legos/HubbleBase.sol"; import { ERC20Detailed, IClearingHouse, IInsuranceFund, IOracle, IRegistry, IMarginAccount, IERC20FlexibleSupply, IWAVAX } from "./Interfaces.sol"; /** * @title This contract is used for posting margin (collateral), realizing PnL etc. * @notice Most notable operations include addMargin, removeMargin and liquidations */ contract MarginAccount is IMarginAccount, HubbleBase, ReentrancyGuard { using SafeERC20 for IERC20; using SafeCast for uint256; using SafeCast for int256; // Hubble vUSD is necessitated to be the first whitelisted collateral uint constant VUSD_IDX = 0; uint constant WAVAX_IDX = 1; // assumes wavax index = 1 // used for all usd based values uint constant PRECISION = 1e6; error NOT_LIQUIDATABLE(IMarginAccount.LiquidationStatus); /** * @dev This is only used to group variables to avoid a solidity stack too deep error * incentivePerDollar How many $ liquidator gets for each $ they repay e.g. they might get $1.05 for every $1 liquidation. >= PRECISION * repayAble The maximum debt that can be settled for an account undergoing a liquidation * priceCollateral Most recent oracle price (chainlink) of the collateral that is being seized for an account undergoing a liquidation * decimals Decimals for the collateral being seized */ struct LiquidationBuffer { LiquidationStatus status; uint8 decimals; uint incentivePerDollar; uint repayAble; uint priceCollateral; } /* ****************** */ /* Storage */ /* ****************** */ IClearingHouse public clearingHouse; IOracle public oracle; IInsuranceFund public insuranceFund; IERC20FlexibleSupply public vusd; uint public credit; /// @notice Array of supported collateral Collateral[] public supportedCollateral; /** * @notice How many $ liquidator gets for each $ they repay e.g. they might get $1.05 for every $1 liquidation * @dev In the above scenario, this value will be %0.05 i.e. 5 cents incentive per dollar repayed */ uint public liquidationIncentive; /** * @notice Maps index in supportedCollateral => trader => balance * @dev equivalent to margin(uint idx, address user) */ mapping(uint => mapping(address => int)) override public margin; uint256[50] private __gap; /* ****************** */ /* Events */ /* ****************** */ /// @notice Emitted when user adds margin for any of the supported collaterals event MarginAdded(address indexed trader, uint256 indexed idx, uint amount, uint256 timestamp); /// @notice Emitted when user removes margin for any of the supported collaterals event MarginRemoved(address indexed trader, uint256 indexed idx, uint256 amount, uint256 timestamp); /** * @notice Mutates trader's vUSD balance * @param trader Account who is realizing PnL * @param realizedPnl Increase or decrease trader's vUSD balace by. +ve/-ve value means vUSD is added/removed respectively from trader's margin */ event PnLRealized(address indexed trader, int256 realizedPnl, uint256 timestamp); /** * @notice Emitted when a trader's margin account is liquidated i.e. their vUSD debt is repayed in exchange for their collateral * @param trader Trader whose margin account was liquidated * @param idx Index of the collateral that was seized during the liquidation * @param seizeAmount Amount of the collateral that was seized during the liquidation * @param repayAmount The debt that was repayed */ event MarginAccountLiquidated(address indexed trader, uint indexed idx, uint seizeAmount, uint repayAmount, uint256 timestamp); /** * @notice Emitted when funds from insurance fund are tasked to settle system's bad debt * @param trader Account for which the bad debt was settled * @param seized Collateral amounts that were seized * @param repayAmount Debt that was settled. it's exactly equal to -vUSD when vUSD < 0 */ event SettledBadDebt(address indexed trader, uint[] seized, uint repayAmount, uint256 timestamp); modifier onlyClearingHouse() { require(_msgSender() == address(clearingHouse), "Only clearingHouse"); _; } constructor(address _trustedForwarder) HubbleBase(_trustedForwarder) {} function initialize( address _governance, address _vusd ) external initializer { _setGovernace(_governance); _addCollateral(_vusd, PRECISION); // weight = 1 * PRECISION vusd = IERC20FlexibleSupply(_vusd); } receive() external payable { // only accept AVAX via fallback from the WAVAX contract assert(_msgSender() == address(supportedCollateral[WAVAX_IDX].token)); } /* ****************** */ /* Margin */ /* ****************** */ /** * @notice Post margin * @param idx Index of the supported collateral * @param amount Amount to deposit (scaled same as the asset) */ function addMargin(uint idx, uint amount) override external whenNotPaused { addMarginFor(idx, amount, _msgSender()); } /** * @notice Post margin for another account * @param idx Index of the supported collateral * @param amount Amount to deposit (scaled same as the asset) * @param to Account to post margin for */ function addMarginFor(uint idx, uint amount, address to) override public whenNotPaused { require(amount > 0, "Add non-zero margin"); // will revert for idx >= supportedCollateral.length if (idx == VUSD_IDX) { _transferInVusd(_msgSender(), amount); } else { supportedCollateral[idx].token.safeTransferFrom(_msgSender(), address(this), amount); } margin[idx][to] += amount.toInt256(); emit MarginAdded(to, idx, amount, _blockTimestamp()); } /** * @notice Withdraw margin. * Collateral can not be withdrawn if vUSD balance is < 0. * @dev If the contract has insufficient vUSD balance, a loan is taken from the vUSD contract. * @param idx Index of the supported collateral * @param amount Amount to withdraw (scaled same as the asset) */ function removeMargin(uint idx, uint256 amount) override external whenNotPaused { address trader = _msgSender(); _validateRemoveMargin(idx, amount, trader); if (idx == VUSD_IDX) { _transferOutVusd(trader, amount); } else { supportedCollateral[idx].token.safeTransfer(trader, amount); } emit MarginRemoved(trader, idx, amount, _blockTimestamp()); } /** * @notice remove margin in Avax * @param amount Amount to withdraw */ function removeAvaxMargin(uint amount) external whenNotPaused { address trader = _msgSender(); _validateRemoveMargin(WAVAX_IDX, amount, trader); IWAVAX(address(supportedCollateral[WAVAX_IDX].token)).withdraw(amount); safeTransferAVAX(trader, amount); emit MarginRemoved(trader, WAVAX_IDX, amount, _blockTimestamp()); } /** * @notice Invoked to realize PnL, credit/debit funding payments, pay trade and liquidation fee * @dev Will only make a change to VUSD balance. * only clearingHouse is authorized to call. * @param trader Account to realize PnL for * @param realizedPnl Amount to credit/debit */ function realizePnL(address trader, int256 realizedPnl) override external onlyClearingHouse { // -ve PnL will reduce balance if (realizedPnl != 0) { margin[VUSD_IDX][trader] += realizedPnl; emit PnLRealized(trader, realizedPnl, _blockTimestamp()); } } function transferOutVusd(address recipient, uint amount) override external onlyClearingHouse { _transferOutVusd(recipient, amount); } /* ****************** */ /* Liquidations */ /* ****************** */ /** * @notice Determines if a trader's margin account can be liquidated now * @param trader Account to check liquidation status for * @param includeFunding whether to include funding payments before checking liquidation status * @return _isLiquidatable Whether the account can be liquidated; reason if not * @return repayAmount Trader's debt i.e. the max amount that they can be liquidated for * @return incentivePerDollar How many $ liquidator gets for each $ they repay * e.g. they might get $1.05 for every $1 that is repayed. */ function isLiquidatable(address trader, bool includeFunding) override public view returns(IMarginAccount.LiquidationStatus _isLiquidatable, uint repayAmount, uint incentivePerDollar) { int vusdBal = margin[VUSD_IDX][trader]; if (includeFunding) { vusdBal -= clearingHouse.getTotalFunding(trader); } if (vusdBal >= 0) { // nothing to liquidate return (IMarginAccount.LiquidationStatus.NO_DEBT, 0, 0); } (uint256 notionalPosition,) = clearingHouse.getTotalNotionalPositionAndUnrealizedPnl(trader, 0, IClearingHouse.Mode.Min_Allowable_Margin); // last two arguments are irrelevent as we are checking only for zero/non-zero notional position in next step if (notionalPosition != 0) { // Liquidate positions before liquidating margin account return (IMarginAccount.LiquidationStatus.OPEN_POSITIONS, 0, 0); } (int256 weighted, int256 spot) = weightedAndSpotCollateral(trader); if (weighted >= 0) { return (IMarginAccount.LiquidationStatus.ABOVE_THRESHOLD, 0, 0); } // _isLiquidatable = IMarginAccount.LiquidationStatus.IS_LIQUIDATABLE; repayAmount = (-vusdBal).toUint256(); incentivePerDollar = PRECISION; // get atleast $1 worth of collateral for every $1 paid if (spot > 0) { /** Liquidation scenario B, where Cw < |vUSD| < Cusd => Cw - |vUSD| < 0 => Cw + vUSD (=weighted) < 0; since vUSD < 0 Max possible liquidationIncentive (for repaying |vUSD|) is Cusd */ incentivePerDollar += _min( liquidationIncentive, // incentivePerDollar = PRECISION + liquidationIncentive <= 1.1 // divide up all the extra dollars in proportion to repay amount // note that spot value here is inclusive of the -ve vUSD value spot.toUint256() * PRECISION / repayAmount ); } /* else { Since the protocol is already in deficit we don't have any money to give out as liquidationIncentive Liquidation scenario C, where Cusd <= |vUSD| => Cusd - |vUSD| <= 0 => Cusd + vUSD (=spot) <= 0; since vUSD < 0 @todo consider providing some incentive from insurance fund to execute a liquidation in this scenario. That fee is basically provided so that insurance fund has to settle a lower bad debt and seize lesser amount of assets. (because seized assets then need to sold/auctioned off, so that's extra work) } */ } /** * @notice Liquidate a trader while mentioning the exact repay amount while capping "slippage" on the seized collateral * This maybe be considered as a "swapExactInput" operation. * It's required that trader has no open positions. * @param trader Account to liquidate * @param repay Amount to repay * @param idx Index of the collateral to seize * @param minSeizeAmount Min collateral output amount */ function liquidateExactRepay(address trader, uint repay, uint idx, uint minSeizeAmount) external whenNotPaused { clearingHouse.updatePositions(trader); // credits/debits funding LiquidationBuffer memory buffer = _getLiquidationInfo(trader, idx); if (buffer.status != IMarginAccount.LiquidationStatus.IS_LIQUIDATABLE) { revert NOT_LIQUIDATABLE(buffer.status); } _liquidateExactRepay(buffer, trader, repay, idx, minSeizeAmount); } /** * @notice Liquidate a trader while mentioning the exact collateral amount to be seized while capping "slippage" on the repay amount. * This maybe be considered as a "swapExactOutput" operation. * It's required that trader has no open positions. * @param trader Account to liquidate * @param maxRepay Max vUSD input amount * @param idx Index of the collateral to seize * @param seize Exact collateral amount desired to be seized */ function liquidateExactSeize(address trader, uint maxRepay, uint idx, uint seize) external whenNotPaused { clearingHouse.updatePositions(trader); // credits/debits funding LiquidationBuffer memory buffer = _getLiquidationInfo(trader, idx); if (buffer.status != IMarginAccount.LiquidationStatus.IS_LIQUIDATABLE) { revert NOT_LIQUIDATABLE(buffer.status); } _liquidateExactSeize(buffer, trader, maxRepay, idx, seize); } /** * @notice Either seize all available collateral * OR settle debt completely with (most likely) left over collateral. * It's required that trader has no open positions. * Seized collateral at it's current oracle price should be acceptable to the liquidator. * @param trader Account to liquidate * @param maxRepay Max vUSD input amount * @param idxs Indices of the collateral to seize */ function liquidateFlexible(address trader, uint maxRepay, uint[] calldata idxs) external whenNotPaused { clearingHouse.updatePositions(trader); // credits/debits funding uint repayed; for (uint i; i < idxs.length; i++) { LiquidationBuffer memory buffer = _getLiquidationInfo(trader, idxs[i]); // revert only if trader has open positions, otherwise fail silently if (buffer.status == IMarginAccount.LiquidationStatus.OPEN_POSITIONS) { revert NOT_LIQUIDATABLE(buffer.status); } if (buffer.status != IMarginAccount.LiquidationStatus.IS_LIQUIDATABLE) { break; } repayed = _liquidateFlexible(trader, maxRepay, idxs[i]); maxRepay -= repayed; } } /** * @notice Invoke a bad debt settlement using the insurance fund. * It's required that trader has no open positions when settling bad debt. * @dev Debt is said to be bad when the spot value of user's collateral is not enough to cover their -ve vUSD balance * Since there are no open positions, debit/credit funding payments is not required. * @param trader Account for which the bad debt needs to be settled */ function settleBadDebt(address trader) external whenNotPaused { (uint256 notionalPosition,) = clearingHouse.getTotalNotionalPositionAndUnrealizedPnl(trader, 0, IClearingHouse.Mode.Min_Allowable_Margin); // last two arguments are irrelevent as we are checking only for zero/non-zero notional position in next step require(notionalPosition == 0, "Liquidate positions before settling bad debt"); // The spot value of their collateral minus their vUSD obligation is a negative value require(getSpotCollateralValue(trader) < 0, "Above bad debt threshold"); int vusdBal = margin[VUSD_IDX][trader]; // this check is not strictly required because getSpotCollateralValue(trader) < 0 is a stronger assertion require(vusdBal < 0, "Nothing to repay"); uint badDebt = (-vusdBal).toUint256(); Collateral[] memory assets = supportedCollateral; // This pulls the obligation insuranceFund.seizeBadDebt(badDebt); margin[VUSD_IDX][trader] = 0; // Insurance fund gets all the available collateral uint[] memory seized = new uint[](assets.length); for (uint i = 1 /* skip vusd */; i < assets.length; i++) { int amount = margin[i][trader]; if (amount > 0) { margin[i][trader] = 0; assets[i].token.safeTransfer(address(insuranceFund), amount.toUint256()); seized[i] = amount.toUint256(); insuranceFund.startAuction(address(assets[i].token)); } } emit SettledBadDebt(trader, seized, badDebt, _blockTimestamp()); } /* ********************* */ /* Liquidations Internal */ /* ********************* */ /** * @dev This function wil either seize all available collateral of type idx * OR settle debt completely with (most likely) left over collateral * @return Debt repayed <= repayble i.e. user's max debt */ function _liquidateFlexible(address trader, uint maxRepay, uint idx) internal whenNotPaused returns(uint /* repayed */) { LiquidationBuffer memory buffer = _getLiquidationInfo(trader, idx); // Q. Can user's margin cover the entire debt? uint repay = _seizeToRepay(buffer, margin[idx][trader].toUint256()); // A.1 Yes, it can cover the entire debt. Settle repayAble if (repay >= buffer.repayAble) { _liquidateExactRepay( buffer, trader, buffer.repayAble, // exact repay amount idx, 0 // minSeizeAmount=0 implies accept whatever the oracle price is ); return buffer.repayAble; // repayed exactly repayAble and 0 is left to repay now } // A.2 No, collateral can not cover the entire debt. Seize all of it. return _liquidateExactSeize( buffer, trader, maxRepay, idx, margin[idx][trader].toUint256() ); } function _liquidateExactRepay( LiquidationBuffer memory buffer, address trader, uint repay, uint idx, uint minSeizeAmount ) internal returns (uint seized) { // determine the seizable collateral amount on the basis of the most recent chainlink price feed seized = _min( _scaleDecimals(repay * buffer.incentivePerDollar, buffer.decimals - 6) / buffer.priceCollateral, // can't seize more than available // this also protects the liquidator in the scenario that they were front-run and only a small seize isn't worth it for them margin[idx][trader].toUint256() ); require(seized >= minSeizeAmount, "Not seizing enough"); _executeLiquidation(trader, repay, idx, seized, buffer.repayAble); } function _liquidateExactSeize( LiquidationBuffer memory buffer, address trader, uint maxRepay, uint idx, uint seize ) internal returns (uint repay) { repay = _seizeToRepay(buffer, seize); require(repay <= maxRepay, "Need to repay more to seize that much"); _executeLiquidation(trader, repay, idx, seize, buffer.repayAble); } /** * @dev reverts if margin account is not liquidatable */ function _getLiquidationInfo(address trader, uint idx) internal view returns (LiquidationBuffer memory buffer) { require(idx > VUSD_IDX && idx < supportedCollateral.length, "collateral not seizable"); (buffer.status, buffer.repayAble, buffer.incentivePerDollar) = isLiquidatable(trader, false); if (buffer.status == IMarginAccount.LiquidationStatus.IS_LIQUIDATABLE) { Collateral memory coll = supportedCollateral[idx]; buffer.priceCollateral = oracle.getUnderlyingPrice(address(coll.token)).toUint256(); buffer.decimals = coll.decimals; } } /** * @dev Peform the actual liquidation. * 1. Pull the repay amount from liquidator's account and credit trader's VUSD margin * 2. Debit the seize amount and transfer to liquidator * @return The debt that is leftover to be paid */ function _executeLiquidation(address trader, uint repay, uint idx, uint seize, uint repayAble) internal returns (uint /* left over repayable */) { if (repay == 0 || seize == 0) { // provides more flexibility, so prefer not reverting return repayAble; } _transferInVusd(_msgSender(), repay); margin[VUSD_IDX][trader] += repay.toInt256(); margin[idx][trader] -= seize.toInt256(); supportedCollateral[idx].token.safeTransfer(_msgSender(), seize); emit MarginAccountLiquidated(trader, idx, seize, repay, _blockTimestamp()); return repayAble - repay; // will ensure that the liquidator isn't repaying more than user's debt (and seizing a bigger amount of their collateral) } function _seizeToRepay(LiquidationBuffer memory buffer, uint seize) internal pure returns (uint repay) { repay = seize * buffer.priceCollateral / (10 ** buffer.decimals); if (buffer.incentivePerDollar > 0) { repay = repay * PRECISION / buffer.incentivePerDollar; } } /* ****************** */ /* View */ /* ****************** */ function getSpotCollateralValue(address trader) override public view returns(int256 spot) { (,spot) = weightedAndSpotCollateral(trader); } function getNormalizedMargin(address trader) override public view returns(int256 weighted) { (weighted,) = weightedAndSpotCollateral(trader); } function weightedAndSpotCollateral(address trader) public view returns (int256 weighted, int256 spot) { Collateral[] memory assets = supportedCollateral; Collateral memory _collateral; for (uint i; i < assets.length; i++) { if (margin[i][trader] == 0) continue; _collateral = assets[i]; int numerator = margin[i][trader] * oracle.getUnderlyingPrice(address(assets[i].token)); uint denomDecimals = _collateral.decimals; spot += (numerator / int(10 ** denomDecimals)); weighted += (numerator * _collateral.weight.toInt256() / int(10 ** (denomDecimals + 6))); } } /* ****************** */ /* UI Helpers */ /* ****************** */ function supportedAssets() external view override returns (Collateral[] memory) { return supportedCollateral; } function supportedAssetsLen() override external view returns (uint) { return supportedCollateral.length; } /* ****************** */ /* Misc Internal */ /* ****************** */ function _addCollateral(address _coin, uint _weight) internal { require(_weight <= PRECISION, "weight > 1e6"); Collateral[] memory _collaterals = supportedCollateral; for (uint i; i < _collaterals.length; i++) { require(address(_collaterals[i].token) != _coin, "collateral exists"); } supportedCollateral.push( Collateral({ token: IERC20(_coin), weight: _weight, decimals: ERC20Detailed(_coin).decimals() // will fail if .decimals() is not defined on the contract }) ); } function _scaleDecimals(uint256 amount, uint8 decimals) internal pure returns(uint256) { return amount * (10 ** decimals); } function _min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } function _transferInVusd(address from, uint amount) internal { IERC20(address(vusd)).safeTransferFrom(from, address(this), amount); if (credit > 0) { uint toBurn = Math.min(vusd.balanceOf(address(this)), credit); credit -= toBurn; vusd.burn(toBurn); } } function _transferOutVusd(address recipient, uint amount) internal { uint bal = vusd.balanceOf(address(this)); if (bal < amount) { // Say there are 2 traders, Alice and Bob. // Alice has a profitable position and realizes their PnL in form of vusd margin. // But bob has not yet realized their -ve PnL. // In that case we'll take a credit from vusd contract, which will eventually be returned when Bob pays their debt back. uint _credit = amount - bal; credit += _credit; vusd.mint(address(this), _credit); } IERC20(address(vusd)).safeTransfer(recipient, amount); } function _validateRemoveMargin(uint idx, uint256 amount, address trader) internal { require(amount != 0, 'Remove non-zero margin'); // credit funding payments clearingHouse.updatePositions(trader); require(margin[VUSD_IDX][trader] >= 0, "Cannot remove margin when vusd balance is negative"); require(margin[idx][trader] >= amount.toInt256(), "Insufficient balance"); margin[idx][trader] -= amount.toInt256(); // Check minimum margin requirement after withdrawal clearingHouse.assertMarginRequirement(trader); } function safeTransferAVAX(address to, uint256 value) internal nonReentrant { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, "MA: AVAX_TRANSFER_FAILED"); } /* ****************** */ /* Governance */ /* ****************** */ function syncDeps(address _registry, uint _liquidationIncentive) public onlyGovernance { // protecting against setting a very high liquidation incentive. Max 10% require(_liquidationIncentive <= PRECISION / 10, "MA.syncDeps.LI_GT_10_percent"); IRegistry registry = IRegistry(_registry); require(registry.marginAccount() == address(this), "Incorrect setup"); clearingHouse = IClearingHouse(registry.clearingHouse()); oracle = IOracle(registry.oracle()); insuranceFund = IInsuranceFund(registry.insuranceFund()); liquidationIncentive = _liquidationIncentive; } function whitelistCollateral(address _coin, uint _weight) external onlyGovernance { _addCollateral(_coin, _weight); } // function to change weight of an asset function changeCollateralWeight(uint idx, uint _weight) external onlyGovernance { require(_weight <= PRECISION, "weight > 1e6"); require(idx < supportedCollateral.length, "Collateral not supported"); supportedCollateral[idx].weight = _weight; } }
// 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); }
// 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: 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 v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; import { ERC2771Context } from "@openzeppelin/contracts/metatx/ERC2771Context.sol"; import { Pausable } from "@openzeppelin/contracts/security/Pausable.sol"; import { Context } from "@openzeppelin/contracts/utils/Context.sol"; import { Governable } from "./Governable.sol"; /** * @title This contract is used for posting margin (collateral), realizing PnL etc. * @notice Most notable operations include addMargin, removeMargin and liquidations */ contract HubbleBase is Governable, Pausable, ERC2771Context { /** * @dev _trustedForwarder is a private immutable var in ERC2771Context */ constructor(address _trustedForwarder) ERC2771Context(_trustedForwarder) {} /* ****************** */ /* Internal View */ /* ****************** */ function _msgSender() internal view override(Context, ERC2771Context) returns (address) { return super._msgSender(); } function _msgData() internal view override(Context, ERC2771Context) returns (bytes memory) { return super._msgData(); } function _blockTimestamp() internal view virtual returns (uint256) { return block.timestamp; } /* ****************** */ /* Governance */ /* ****************** */ function pause() external onlyGovernance { _pause(); } function unpause() external onlyGovernance { _unpause(); } }
// 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) (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) (metatx/ERC2771Context.sol) pragma solidity ^0.8.9; import "../utils/Context.sol"; /** * @dev Context variant with ERC2771 support. */ abstract contract ERC2771Context is Context { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable _trustedForwarder; /// @custom:oz-upgrades-unsafe-allow constructor constructor(address trustedForwarder) { _trustedForwarder = trustedForwarder; } function isTrustedForwarder(address forwarder) public view virtual returns (bool) { return forwarder == _trustedForwarder; } function _msgSender() internal view virtual override returns (address sender) { if (isTrustedForwarder(msg.sender)) { // The assembly code is more direct than the Solidity version using `abi.decode`. assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } } else { return super._msgSender(); } } function _msgData() internal view virtual override returns (bytes calldata) { if (isTrustedForwarder(msg.sender)) { return msg.data[:msg.data.length - 20]; } else { return super._msgData(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// 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: 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)); } }
{ "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_trustedForwarder","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"enum IMarginAccount.LiquidationStatus","name":"","type":"uint8"}],"name":"NOT_LIQUIDATABLE","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"idx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"seizeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MarginAccountLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"idx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MarginAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"uint256","name":"idx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MarginRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"int256","name":"realizedPnl","type":"int256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"PnLRealized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"seized","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SettledBadDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"addMarginFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"},{"internalType":"uint256","name":"_weight","type":"uint256"}],"name":"changeCollateralWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clearingHouse","outputs":[{"internalType":"contract IClearingHouse","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"credit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"getNormalizedMargin","outputs":[{"internalType":"int256","name":"weighted","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"getSpotCollateralValue","outputs":[{"internalType":"int256","name":"spot","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_vusd","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"insuranceFund","outputs":[{"internalType":"contract IInsuranceFund","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"bool","name":"includeFunding","type":"bool"}],"name":"isLiquidatable","outputs":[{"internalType":"enum IMarginAccount.LiquidationStatus","name":"_isLiquidatable","type":"uint8"},{"internalType":"uint256","name":"repayAmount","type":"uint256"},{"internalType":"uint256","name":"incentivePerDollar","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"repay","type":"uint256"},{"internalType":"uint256","name":"idx","type":"uint256"},{"internalType":"uint256","name":"minSeizeAmount","type":"uint256"}],"name":"liquidateExactRepay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"maxRepay","type":"uint256"},{"internalType":"uint256","name":"idx","type":"uint256"},{"internalType":"uint256","name":"seize","type":"uint256"}],"name":"liquidateExactSeize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"maxRepay","type":"uint256"},{"internalType":"uint256[]","name":"idxs","type":"uint256[]"}],"name":"liquidateFlexible","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidationIncentive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"margin","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"int256","name":"realizedPnl","type":"int256"}],"name":"realizePnL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"removeAvaxMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"removeMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governance","type":"address"}],"name":"setGovernace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"settleBadDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supportedAssets","outputs":[{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"internalType":"struct IMarginAccount.Collateral[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supportedAssetsLen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportedCollateral","outputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_registry","type":"address"},{"internalType":"uint256","name":"_liquidationIncentive","type":"uint256"}],"name":"syncDeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferOutVusd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vusd","outputs":[{"internalType":"contract IERC20FlexibleSupply","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"}],"name":"weightedAndSpotCollateral","outputs":[{"internalType":"int256","name":"weighted","type":"int256"},{"internalType":"int256","name":"spot","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_coin","type":"address"},{"internalType":"uint256","name":"_weight","type":"uint256"}],"name":"whitelistCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040516200468938038062004689833981016040819052620000349162000057565b6000805460ff60b01b191690556001600160a01b03166080526001805562000089565b6000602082840312156200006a57600080fd5b81516001600160a01b03811681146200008257600080fd5b9392505050565b6080516145dd620000ac6000396000818161039301526125a501526145dd6000f3fe60806040526004361061021d5760003560e01c8063870b00791161011d578063c804cf60116100b0578063e5590ea21161007f578063f9a8232e11610064578063f9a8232e146106d8578063fd9910e1146106f8578063ff71fa221461071857600080fd5b8063e5590ea214610698578063edac5203146106b857600080fd5b8063c804cf6014610603578063d41194b814610623578063e19b74f714610643578063e2c9713b1461066357600080fd5b8063a06d083c116100ec578063a06d083c1461058b578063a80ce55c146105a1578063b7902303146105c3578063c58f0c31146105e357600080fd5b8063870b0079146104fd578063873490ea1461051d5780638c765e94146105555780639277f8ff1461056b57600080fd5b80635aa6e675116101b05780637dc0d1d01161017f57806381d6dd8b1161016457806381d6dd8b146104b35780638456cb59146104c8578063851e3ca5146104dd57600080fd5b80637dc0d1d0146104735780637ed5e2951461049357600080fd5b80635aa6e675146103d35780635c975abb146103f357806360cb5305146104255780636141cc1c1461045357600080fd5b8063485cc955116101ec578063485cc955146103075780634b8f438114610327578063500b226514610347578063572b6c051461037657600080fd5b806304aa459c1461027557806304ec9d6e146102955780630af96800146102b55780633f4ba83a146102f257600080fd5b3661027057600760018154811061023657610236613ba3565b60009182526020909120600390910201546001600160a01b0316610258610760565b6001600160a01b03161461026e5761026e613bd2565b005b600080fd5b34801561028157600080fd5b5061026e610290366004613c16565b61076f565b3480156102a157600080fd5b5061026e6102b0366004613ca2565b610948565b3480156102c157600080fd5b506002546102d5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102fe57600080fd5b5061026e6109b0565b34801561031357600080fd5b5061026e610322366004613cce565b610a14565b34801561033357600080fd5b5061026e610342366004613d07565b610bdf565b34801561035357600080fd5b50610367610362366004613d37565b610cfc565b6040516102e993929190613da8565b34801561038257600080fd5b506103c3610391366004613dc7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b60405190151581526020016102e9565b3480156103df57600080fd5b506000546102d5906001600160a01b031681565b3480156103ff57600080fd5b50600054760100000000000000000000000000000000000000000000900460ff166103c3565b34801561043157600080fd5b50610445610440366004613dc7565b610f47565b6040519081526020016102e9565b34801561045f57600080fd5b5061026e61046e366004613de4565b610f59565b34801561047f57600080fd5b506003546102d5906001600160a01b031681565b34801561049f57600080fd5b5061026e6104ae366004613ca2565b6110e7565b3480156104bf57600080fd5b50600754610445565b3480156104d457600080fd5b5061026e611452565b3480156104e957600080fd5b5061026e6104f8366004613dc7565b6114b4565b34801561050957600080fd5b5061026e610518366004613d07565b611547565b34801561052957600080fd5b50610445610538366004613e1d565b600960209081526000928352604080842090915290825290205481565b34801561056157600080fd5b5061044560085481565b34801561057757600080fd5b5061026e610586366004613ca2565b611672565b34801561059757600080fd5b5061044560065481565b3480156105ad57600080fd5b506105b6611774565b6040516102e99190613e42565b3480156105cf57600080fd5b506004546102d5906001600160a01b031681565b3480156105ef57600080fd5b5061026e6105fe366004613ea7565b6117f9565b34801561060f57600080fd5b5061026e61061e366004613dc7565b61196c565b34801561062f57600080fd5b5061026e61063e366004613d07565b611f2e565b34801561064f57600080fd5b5061026e61065e366004613ec0565b611fa8565b34801561066f57600080fd5b5061068361067e366004613dc7565b6120f7565b604080519283526020830191909152016102e9565b3480156106a457600080fd5b506104456106b3366004613dc7565b61238c565b3480156106c457600080fd5b506005546102d5906001600160a01b031681565b3480156106e457600080fd5b5061026e6106f3366004613ec0565b61239e565b34801561070457600080fd5b5061026e610713366004613ca2565b6124ed565b34801561072457600080fd5b50610738610733366004613ea7565b612561565b604080516001600160a01b039094168452602084019290925260ff16908201526060016102e9565b600061076a6125a1565b905090565b600054760100000000000000000000000000000000000000000000900460ff16156107e15760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064015b60405180910390fd5b6002546040517f43ba49700000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152909116906343ba497090602401600060405180830381600087803b15801561084157600080fd5b505af1158015610855573d6000803e3d6000fd5b505050506000805b828110156109405760006108898786868581811061087d5761087d613ba3565b90506020020135612604565b90506001815160038111156108a0576108a0613d65565b14156108db5780516040517f25ba9ec60000000000000000000000000000000000000000000000000000000081526107d89190600401613efb565b6000815160038111156108f0576108f0613d65565b146108fb5750610940565b61091e878787878681811061091257610912613ba3565b90506020020135612800565b925061092a8387613f38565b955050808061093890613f4f565b91505061085d565b505050505050565b6000546001600160a01b031633146109a25760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e4345000000000000000000000000000000000060448201526064016107d8565b6109ac8282612928565b5050565b6000546001600160a01b03163314610a0a5760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e4345000000000000000000000000000000000060448201526064016107d8565b610a12612bd0565b565b6000547501000000000000000000000000000000000000000000900460ff16610a5b5760005474010000000000000000000000000000000000000000900460ff1615610a5f565b303b155b610ad15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107d8565b6000547501000000000000000000000000000000000000000000900460ff16158015610b3857600080547fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff1675010100000000000000000000000000000000000000001790555b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038516179055610b7882620f4240612928565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790558015610bda57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1690555b505050565b600054760100000000000000000000000000000000000000000000900460ff1615610c4c5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b6000610c56610760565b9050610c63838383612caa565b82610c7757610c728183612f50565b610cb0565b610cb0818360078681548110610c8f57610c8f613ba3565b60009182526020909120600390910201546001600160a01b031691906130a6565b826001600160a01b0382167ffe460128225239fdbbc5909326e8198b8396336ff9b32b8f4dbda29447ecf97c84425b6040805192835260208301919091520160405180910390a3505050565b6001600160a01b03821660009081527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b6020526040812054819081908415610de1576002546040517fe239e8400000000000000000000000000000000000000000000000000000000081526001600160a01b0388811660048301529091169063e239e8409060240160206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190613f88565b610dde9082613fa1565b90505b60008112610dfa57600260008093509350935050610f40565b6002546040517f813167a70000000000000000000000000000000000000000000000000000000081526000916001600160a01b03169063813167a790610e49908a908590600190600401614015565b604080518083038186803b158015610e6057600080fd5b505afa158015610e74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e98919061404a565b5090508015610eb35760016000809450945094505050610f40565b600080610ebf896120f7565b9150915060008212610edf57600360008096509650965050505050610f40565b610ef0610eeb8561406e565b61316d565b9550620f424094506000811315610f3b57610f2e60085487620f4240610f158561316d565b610f1f91906140a7565b610f299190614113565b6131c3565b610f389086614127565b94505b505050505b9250925092565b6000610f52826120f7565b9392505050565b600054760100000000000000000000000000000000000000000000900460ff1615610fc65760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b600082116110165760405162461bcd60e51b815260206004820152601360248201527f416464206e6f6e2d7a65726f206d617267696e0000000000000000000000000060448201526064016107d8565b826110315761102c611026610760565b836131d9565b611073565b61107361103c610760565b30846007878154811061105157611051613ba3565b60009182526020909120600390910201546001600160a01b0316929190613328565b61107c8261337f565b60008481526009602090815260408083206001600160a01b0386168452909152812080549091906110ae90849061413f565b909155508390506001600160a01b0382167fe424152e5f8dcbc0fbba9108ff4e148910ddb920dd772c655cb76517f579decf8442610cdf565b6000546001600160a01b031633146111415760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e4345000000000000000000000000000000000060448201526064016107d8565b61114f600a620f4240614113565b81111561119e5760405162461bcd60e51b815260206004820152601c60248201527f4d412e73796e63446570732e4c495f47545f31305f70657263656e740000000060448201526064016107d8565b6000829050306001600160a01b0316816001600160a01b031663f742269d6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111e657600080fd5b505afa1580156111fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121e91906141b3565b6001600160a01b0316146112745760405162461bcd60e51b815260206004820152600f60248201527f496e636f7272656374207365747570000000000000000000000000000000000060448201526064016107d8565b806001600160a01b0316630af968006040518163ffffffff1660e01b815260040160206040518083038186803b1580156112ad57600080fd5b505afa1580156112c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e591906141b3565b600260006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b0316637dc0d1d06040518163ffffffff1660e01b815260040160206040518083038186803b15801561134457600080fd5b505afa158015611358573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137c91906141b3565b600360006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001600160a01b031663b79023036040518163ffffffff1660e01b815260040160206040518083038186803b1580156113db57600080fd5b505afa1580156113ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141391906141b3565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03929092169190911790555060085550565b6000546001600160a01b031633146114ac5760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e4345000000000000000000000000000000000060448201526064016107d8565b610a12613417565b6000546001600160a01b0316331461150e5760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e4345000000000000000000000000000000000060448201526064016107d8565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03831617905550565b50565b6000546001600160a01b031633146115a15760405162461bcd60e51b815260206004820152600f60248201527f4f4e4c595f474f5645524e414e4345000000000000000000000000000000000060448201526064016107d8565b620f42408111156115f45760405162461bcd60e51b815260206004820152600c60248201527f776569676874203e20316536000000000000000000000000000000000000000060448201526064016107d8565b60075482106116455760405162461bcd60e51b815260206004820152601860248201527f436f6c6c61746572616c206e6f7420737570706f72746564000000000000000060448201526064016107d8565b806007838154811061165957611659613ba3565b9060005260206000209060030201600101819055505050565b6002546001600160a01b0316611686610760565b6001600160a01b0316146116dc5760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f757365000000000000000000000000000060448201526064016107d8565b80156109ac576001600160a01b03821660009081527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b60205260408120805483929061172990849061413f565b90915550506040805182815242602082015281516001600160a01b038516927ff9067ab1bfec1213afebcdd6735481adbaecc73093f35eeb381b1bb499aa4544928290030190a25050565b60606007805480602002602001604051908101604052809291908181526020016000905b828210156117f0576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015460ff16918301919091529083529092019101611798565b50505050905090565b600054760100000000000000000000000000000000000000000000900460ff16156118665760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b6000611870610760565b905061187e60018383612caa565b600760018154811061189257611892613ba3565b60009182526020909120600390910201546040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b5050505061192181836134ee565b60016001600160a01b0382167ffe460128225239fdbbc5909326e8198b8396336ff9b32b8f4dbda29447ecf97c84426040805192835260208301919091520160405180910390a35050565b600054760100000000000000000000000000000000000000000000900460ff16156119d95760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b6002546040517f813167a70000000000000000000000000000000000000000000000000000000081526000916001600160a01b03169063813167a790611a289085908590600190600401614015565b604080518083038186803b158015611a3f57600080fd5b505afa158015611a53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a77919061404a565b5090508015611aee5760405162461bcd60e51b815260206004820152602c60248201527f4c697175696461746520706f736974696f6e73206265666f726520736574746c60448201527f696e67206261642064656274000000000000000000000000000000000000000060648201526084016107d8565b6000611af983610f47565b12611b465760405162461bcd60e51b815260206004820152601860248201527f41626f7665206261642064656274207468726573686f6c64000000000000000060448201526064016107d8565b6001600160a01b03821660009081527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b6020526040812054908112611bcd5760405162461bcd60e51b815260206004820152601060248201527f4e6f7468696e6720746f2072657061790000000000000000000000000000000060448201526064016107d8565b6000611bdb610eeb8361406e565b905060006007805480602002602001604051908101604052809291908181526020016000905b82821015611c59576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015460ff16918301919091529083529092019101611c01565b5050600480546040517fe2eb4f5e0000000000000000000000000000000000000000000000000000000081529495506001600160a01b03169363e2eb4f5e9350611caa925086910190815260200190565b600060405180830381600087803b158015611cc457600080fd5b505af1158015611cd8573d6000803e3d6000fd5b505050506001600160a01b03851660009081527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b60205260408120819055815167ffffffffffffffff811115611d3057611d306141d0565b604051908082528060200260200182016040528015611d59578160200160208202803683370190505b50905060015b8251811015611ee05760008181526009602090815260408083206001600160a01b038b16845290915281205490811315611ecd5760008281526009602090815260408083206001600160a01b03808d1685529252822091909155600454611e009116611dca8361316d565b868581518110611ddc57611ddc613ba3565b6020026020010151600001516001600160a01b03166130a69092919063ffffffff16565b611e098161316d565b838381518110611e1b57611e1b613ba3565b602090810291909101015260045484516001600160a01b0390911690634075fa0f90869085908110611e4f57611e4f613ba3565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015611eb457600080fd5b505af1158015611ec8573d6000803e3d6000fd5b505050505b5080611ed881613f4f565b915050611d5f565b506001600160a01b0386167f18172d438ecc20ef650e13e0037292d809dc7a0803e0505eed947341008e6e7c828542604051611f1e939291906141ff565b60405180910390a2505050505050565b600054760100000000000000000000000000000000000000000000900460ff1615611f9b5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b6109ac828261046e610760565b600054760100000000000000000000000000000000000000000000900460ff16156120155760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b6002546040517f43ba49700000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152909116906343ba497090602401600060405180830381600087803b15801561207557600080fd5b505af1158015612089573d6000803e3d6000fd5b5050505060006120998584612604565b90506000815160038111156120b0576120b0613d65565b146120ea5780516040517f25ba9ec60000000000000000000000000000000000000000000000000000000081526107d89190600401613efb565b610940818686868661360c565b60008060006007805480602002602001604051908101604052809291908181526020016000905b82821015612176576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015460ff1691830191909152908352909201910161211e565b5050505090506121ac604051806060016040528060006001600160a01b0316815260200160008152602001600060ff1681525090565b60005b82518110156123845760008181526009602090815260408083206001600160a01b038a1684529091529020546121e457612372565b8281815181106121f6576121f6613ba3565b602002602001015191506000600360009054906101000a90046001600160a01b03166001600160a01b031663fc57d4df85848151811061223857612238613ba3565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561229b57600080fd5b505afa1580156122af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d39190613f88565b60008381526009602090815260408083206001600160a01b038c168452909152902054612300919061424c565b604084015190915060ff1661231681600a614428565b6123209083614434565b61232a908761413f565b9550612337816006614127565b61234290600a614428565b61234f856020015161337f565b612359908461424c565b6123639190614434565b61236d908861413f565b965050505b8061237c81613f4f565b9150506121af565b505050915091565b6000612397826120f7565b5092915050565b600054760100000000000000000000000000000000000000000000900460ff161561240b5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b6002546040517f43ba49700000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152909116906343ba497090602401600060405180830381600087803b15801561246b57600080fd5b505af115801561247f573d6000803e3d6000fd5b50505050600061248f8584612604565b90506000815160038111156124a6576124a6613d65565b146124e05780516040517f25ba9ec60000000000000000000000000000000000000000000000000000000081526107d89190600401613efb565b61094081868686866136ab565b6002546001600160a01b0316612501610760565b6001600160a01b0316146125575760405162461bcd60e51b815260206004820152601260248201527f4f6e6c7920636c656172696e67486f757365000000000000000000000000000060448201526064016107d8565b6109ac8282612f50565b6007818154811061257157600080fd5b60009182526020909120600390910201805460018201546002909201546001600160a01b03909116925060ff1683565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314156125ff57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36013560601c90565b503390565b61263a6040805160a081019091528060008152602001600060ff1681526020016000815260200160008152602001600081525090565b60008211801561264b575060075482105b6126975760405162461bcd60e51b815260206004820152601760248201527f636f6c6c61746572616c206e6f74207365697a61626c6500000000000000000060448201526064016107d8565b6126a2836000610cfc565b6040840181905260608401829052838360038111156126c3576126c3613d65565b60038111156126d4576126d4613d65565b905250600091506126e29050565b815160038111156126f5576126f5613d65565b14156127fa5760006007838154811061271057612710613ba3565b600091825260209182902060408051606081018252600393840290920180546001600160a01b0390811680855260018301549685019690965260029091015460ff1683830152925490517ffc57d4df00000000000000000000000000000000000000000000000000000000815260048101949094529093506127e89291169063fc57d4df9060240160206040518083038186803b1580156127b057600080fd5b505afa1580156127c4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eeb9190613f88565b60808301526040015160ff1660208201525b92915050565b60008054760100000000000000000000000000000000000000000000900460ff161561286e5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b600061287a8584612604565b60008481526009602090815260408083206001600160a01b038a168452909152812054919250906128b59083906128b09061316d565b613777565b9050816060015181106128e1576128d4828784606001518760006136ab565b5050606001519050610f52565b60008481526009602090815260408083206001600160a01b038a16845290915290205461291e9083908890889088906129199061316d565b61360c565b9695505050505050565b620f424081111561297b5760405162461bcd60e51b815260206004820152600c60248201527f776569676874203e20316536000000000000000000000000000000000000000060448201526064016107d8565b60006007805480602002602001604051908101604052809291908181526020016000905b828210156129f7576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015460ff1691830191909152908352909201910161299f565b50505050905060005b8151811015612a9a57836001600160a01b0316828281518110612a2557612a25613ba3565b6020026020010151600001516001600160a01b03161415612a885760405162461bcd60e51b815260206004820152601160248201527f636f6c6c61746572616c2065786973747300000000000000000000000000000060448201526064016107d8565b80612a9281613f4f565b915050612a00565b5060076040518060600160405280856001600160a01b03168152602001848152602001856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612af657600080fd5b505afa158015612b0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2e919061449c565b60ff9081169091528254600180820185556000948552602094859020845160039093020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039093169290921782559383015193810193909355604090910151600290920180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001692909116919091179055505050565b600054760100000000000000000000000000000000000000000000900460ff16612c3c5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016107d8565b600080547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612c8d610760565b6040516001600160a01b03909116815260200160405180910390a1565b81612cf75760405162461bcd60e51b815260206004820152601660248201527f52656d6f7665206e6f6e2d7a65726f206d617267696e0000000000000000000060448201526064016107d8565b6002546040517f43ba49700000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152909116906343ba497090602401600060405180830381600087803b158015612d5757600080fd5b505af1158015612d6b573d6000803e3d6000fd5b505050506001600160a01b03811660009081527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b60205260408120541215612e1b5760405162461bcd60e51b815260206004820152603260248201527f43616e6e6f742072656d6f7665206d617267696e207768656e2076757364206260448201527f616c616e6365206973206e65676174697665000000000000000000000000000060648201526084016107d8565b612e248261337f565b60008481526009602090815260408083206001600160a01b03861684529091529020541215612e955760405162461bcd60e51b815260206004820152601460248201527f496e73756666696369656e742062616c616e636500000000000000000000000060448201526064016107d8565b612e9e8261337f565b60008481526009602090815260408083206001600160a01b038616845290915281208054909190612ed0908490613fa1565b90915550506002546040517f9001568e0000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015290911690639001568e9060240160006040518083038186803b158015612f3357600080fd5b505afa158015612f47573d6000803e3d6000fd5b50505050505050565b6005546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015612fad57600080fd5b505afa158015612fc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe59190613f88565b905081811015613093576000612ffb8284613f38565b9050806006600082825461300f9190614127565b90915550506005546040517f40c10f19000000000000000000000000000000000000000000000000000000008152306004820152602481018390526001600160a01b03909116906340c10f1990604401600060405180830381600087803b15801561307957600080fd5b505af115801561308d573d6000803e3d6000fd5b50505050505b600554610bda906001600160a01b031684845b6040516001600160a01b038316602482015260448101829052610bda9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526137cc565b6000808212156131bf5760405162461bcd60e51b815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016107d8565b5090565b60008183106131d25781610f52565b5090919050565b6005546131f1906001600160a01b0316833084613328565b600654156109ac576005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009161329c916001600160a01b03909116906370a082319060240160206040518083038186803b15801561325c57600080fd5b505afa158015613270573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132949190613f88565b6006546131c3565b905080600660008282546132b09190613f38565b90915550506005546040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b03909116906342966c6890602401600060405180830381600087803b15801561331457600080fd5b505af1158015612f47573d6000803e3d6000fd5b6040516001600160a01b03808516602483015283166044820152606481018290526133799085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016130eb565b50505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156131bf5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e206160448201527f6e20696e7432353600000000000000000000000000000000000000000000000060648201526084016107d8565b600054760100000000000000000000000000000000000000000000900460ff16156134845760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016107d8565b600080547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff167601000000000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612c8d610760565b600260015414156135415760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107d8565b6002600155604080516000808252602082019092526001600160a01b03841690839060405161357091906144eb565b60006040518083038185875af1925050503d80600081146135ad576040519150601f19603f3d011682016040523d82523d6000602084013e6135b2565b606091505b50509050806136035760405162461bcd60e51b815260206004820152601860248201527f4d413a20415641585f5452414e534645525f4641494c4544000000000000000060448201526064016107d8565b50506001805550565b60006136188683613777565b9050838111156136905760405162461bcd60e51b815260206004820152602560248201527f4e65656420746f207265706179206d6f726520746f207365697a65207468617460448201527f206d75636800000000000000000000000000000000000000000000000000000060648201526084016107d8565b6136a1858285858a606001516138b1565b5095945050505050565b600061371486608001516136de8860400151876136c891906140a7565b60068a602001516136d99190614507565b6139f4565b6136e89190614113565b60008581526009602090815260408083206001600160a01b038b168452909152902054610f299061316d565b9050818110156137665760405162461bcd60e51b815260206004820152601260248201527f4e6f74207365697a696e6720656e6f756768000000000000000000000000000060448201526064016107d8565b6136a1858585848a606001516138b1565b60008260200151600a61378a919061452a565b608084015161379990846140a7565b6137a39190614113565b6040840151909150156127fa5760408301516137c2620f4240836140a7565b610f529190614113565b6000613821826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613a0b9092919063ffffffff16565b805190915015610bda578080602001905181019061383f9190614539565b610bda5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016107d8565b60008415806138be575082155b156138ca5750806139eb565b6138db6138d5610760565b866131d9565b6138e48561337f565b6001600160a01b03871660009081527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b60205260408120805490919061392b90849061413f565b9091555061393a90508361337f565b60008581526009602090815260408083206001600160a01b038b1684529091528120805490919061396c908490613fa1565b90915550613991905061397d610760565b8460078781548110610c8f57610c8f613ba3565b836001600160a01b0387167f7fb23588e5b71d6f001557fcf957144c19a47dd6b80368d48b6289f6ba4cf1998588426040805193845260208401929092529082015260600160405180910390a36139e88583613f38565b90505b95945050505050565b6000613a0182600a61452a565b610f5290846140a7565b6060613a1a8484600085613a22565b949350505050565b606082471015613a9a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016107d8565b6001600160a01b0385163b613af15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107d8565b600080866001600160a01b03168587604051613b0d91906144eb565b60006040518083038185875af1925050503d8060008114613b4a576040519150601f19603f3d011682016040523d82523d6000602084013e613b4f565b606091505b5091509150613b5f828286613b6a565b979650505050505050565b60608315613b79575081610f52565b825115613b895782518084602001fd5b8160405162461bcd60e51b81526004016107d89190614556565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6001600160a01b038116811461154457600080fd5b60008060008060608587031215613c2c57600080fd5b8435613c3781613c01565b935060208501359250604085013567ffffffffffffffff80821115613c5b57600080fd5b818701915087601f830112613c6f57600080fd5b813581811115613c7e57600080fd5b8860208260051b8501011115613c9357600080fd5b95989497505060200194505050565b60008060408385031215613cb557600080fd5b8235613cc081613c01565b946020939093013593505050565b60008060408385031215613ce157600080fd5b8235613cec81613c01565b91506020830135613cfc81613c01565b809150509250929050565b60008060408385031215613d1a57600080fd5b50508035926020909101359150565b801515811461154457600080fd5b60008060408385031215613d4a57600080fd5b8235613d5581613c01565b91506020830135613cfc81613d29565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110613da457613da4613d65565b9052565b60608101613db68286613d94565b602082019390935260400152919050565b600060208284031215613dd957600080fd5b8135610f5281613c01565b600080600060608486031215613df957600080fd5b83359250602084013591506040840135613e1281613c01565b809150509250925092565b60008060408385031215613e3057600080fd5b823591506020830135613cfc81613c01565b602080825282518282018190526000919060409081850190868401855b82811015613e9a57815180516001600160a01b03168552868101518786015285015160ff168585015260609093019290850190600101613e5f565b5091979650505050505050565b600060208284031215613eb957600080fd5b5035919050565b60008060008060808587031215613ed657600080fd5b8435613ee181613c01565b966020860135965060408601359560600135945092505050565b602081016127fa8284613d94565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613f4a57613f4a613f09565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613f8157613f81613f09565b5060010190565b600060208284031215613f9a57600080fd5b5051919050565b6000808312837f800000000000000000000000000000000000000000000000000000000000000001831281151615613fdb57613fdb613f09565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561400f5761400f613f09565b50500390565b6001600160a01b038416815260208101839052606081016002831061403c5761403c613d65565b826040830152949350505050565b6000806040838503121561405d57600080fd5b505080516020909101519092909150565b60007f80000000000000000000000000000000000000000000000000000000000000008214156140a0576140a0613f09565b5060000390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156140df576140df613f09565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614122576141226140e4565b500490565b6000821982111561413a5761413a613f09565b500190565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561417957614179613f09565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156141ad576141ad613f09565b50500190565b6000602082840312156141c557600080fd5b8151610f5281613c01565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b606080825284519082018190526000906020906080840190828801845b828110156142385781518452928401929084019060010161421c565b505050908301949094525060400152919050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561428d5761428d613f09565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156142c8576142c8613f09565b600087129250878205871284841616156142e4576142e4613f09565b878505871281841616156142fa576142fa613f09565b505050929093029392505050565b600181815b8085111561436157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561434757614347613f09565b8085161561435457918102915b93841c939080029061430d565b509250929050565b600082614378575060016127fa565b81614385575060006127fa565b816001811461439b57600281146143a5576143c1565b60019150506127fa565b60ff8411156143b6576143b6613f09565b50506001821b6127fa565b5060208310610133831016604e8410600b84101617156143e4575081810a6127fa565b6143ee8383614308565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561442057614420613f09565b029392505050565b6000610f528383614369565b600082614443576144436140e4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561449757614497613f09565b500590565b6000602082840312156144ae57600080fd5b815160ff81168114610f5257600080fd5b60005b838110156144da5781810151838201526020016144c2565b838111156133795750506000910152565b600082516144fd8184602087016144bf565b9190910192915050565b600060ff821660ff84168082101561452157614521613f09565b90039392505050565b6000610f5260ff841683614369565b60006020828403121561454b57600080fd5b8151610f5281613d29565b60208152600082518060208401526145758160408501602087016144bf565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220a7857ddb5b1fce45c16ee04ed2674949dcb696ac483e0a28d55bdf052d4e658364736f6c63430008090033000000000000000000000000ed27fb82dab4c5384b38aee8d0ab81b3b591c0fa
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ed27fb82dab4c5384b38aee8d0ab81b3b591c0fa
-----Decoded View---------------
Arg [0] : _trustedForwarder (address): 0xed27fb82dab4c5384b38aee8d0ab81b3b591c0fa
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ed27fb82dab4c5384b38aee8d0ab81b3b591c0fa
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.