ETH Price: $1,640.67 (-2.26%)
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0xf93ac304840fc80bf97f6b37c3626900edac2aefeeb5b56e6d397727be0395be Withdraw(pending)2025-04-13 8:12:372 days ago1744531957IN
0x6830C61d...677F32078
0 ETH(Pending)(Pending)
Update Protocol ...222682272025-04-14 15:49:4718 hrs ago1744645787IN
0x6830C61d...677F32078
0 ETH0.000363798.44394961
Update Protocol ...222642662025-04-14 2:33:4731 hrs ago1744598027IN
0x6830C61d...677F32078
0 ETH0.000155283.60424131
Update Protocol ...222628002025-04-13 21:39:5936 hrs ago1744580399IN
0x6830C61d...677F32078
0 ETH0.000163563.79636036
Update Protocol ...222578092025-04-13 4:58:112 days ago1744520291IN
0x6830C61d...677F32078
0 ETH0.000147173.4160868
Update Protocol ...222558382025-04-12 22:22:352 days ago1744496555IN
0x6830C61d...677F32078
0 ETH0.00015023.48629282
Update Protocol ...222532672025-04-12 13:45:472 days ago1744465547IN
0x6830C61d...677F32078
0 ETH0.000165293.83660965
Update Protocol ...222443942025-04-11 8:06:234 days ago1744358783IN
0x6830C61d...677F32078
0 ETH0.000155783.61679326
Update Protocol ...222420322025-04-11 0:12:234 days ago1744330343IN
0x6830C61d...677F32078
0 ETH0.000145293.37245169
Update Protocol ...222395342025-04-10 15:50:234 days ago1744300223IN
0x6830C61d...677F32078
0 ETH0.0007439417.26723933
Update Protocol ...222389042025-04-10 13:43:234 days ago1744292603IN
0x6830C61d...677F32078
0 ETH0.0011982227.81135025
Update Protocol ...222357652025-04-10 3:14:355 days ago1744254875IN
0x6830C61d...677F32078
0 ETH0.000147643.4269668
Update Protocol ...222330742025-04-09 18:14:475 days ago1744222487IN
0x6830C61d...677F32078
0 ETH0.0021600850.1365225
Update Protocol ...222328392025-04-09 17:27:475 days ago1744219667IN
0x6830C61d...677F32078
0 ETH0.000327537.60224009
Update Protocol ...222328252025-04-09 17:24:595 days ago1744219499IN
0x6830C61d...677F32078
0 ETH0.000153033.55198858
Update Protocol ...222298772025-04-09 7:32:596 days ago1744183979IN
0x6830C61d...677F32078
0 ETH0.000155223.60287834
Update Protocol ...222282612025-04-09 2:07:236 days ago1744164443IN
0x6830C61d...677F32078
0 ETH0.000168963.92175961
Update Protocol ...222280362025-04-09 1:22:236 days ago1744161743IN
0x6830C61d...677F32078
0 ETH0.000193394.48886056
Update Protocol ...222271362025-04-08 22:21:596 days ago1744150919IN
0x6830C61d...677F32078
0 ETH0.000150173.48570163
Update Protocol ...222254332025-04-08 16:39:116 days ago1744130351IN
0x6830C61d...677F32078
0 ETH0.000152723.5448695
Update Protocol ...222228012025-04-08 7:50:597 days ago1744098659IN
0x6830C61d...677F32078
0 ETH0.000151153.50829057
Update Protocol ...222211182025-04-08 2:13:237 days ago1744078403IN
0x6830C61d...677F32078
0 ETH0.000181074.20274469
Update Protocol ...222176022025-04-07 14:24:597 days ago1744035899IN
0x6830C61d...677F32078
0 ETH0.0017673241.02044056
Update Protocol ...222175732025-04-07 14:18:597 days ago1744035539IN
0x6830C61d...677F32078
0 ETH0.0011527726.75651664
Update Protocol ...222175402025-04-07 14:12:237 days ago1744035143IN
0x6830C61d...677F32078
0 ETH0.0006813815.81518014
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RelayerV2

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 14 : RelayerV2.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;

// Core
import {QuarantineList} from "./core/QuarantineList.sol";

// Structs
import {UserRequest, RequestData, ProcessParam, AssetInfo} from "./core/Structs.sol";

// Utils
import {Ownable} from "./utils/Ownable.sol";
import {PercentageMath} from "./utils/PercentageMath.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";

// Interfaces
import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import {IFyde} from "./interfaces/IFyde.sol";
import {IGovernanceModule} from "./interfaces/IGovernanceModule.sol";
import {IOracle} from "./interfaces/IOracle.sol";
import {ITaxModule} from "./interfaces/ITaxModule.sol";

///@title RelayerV2
///@notice The relayer is the entry point contract for users to interact with the protocol.
///        The relayer is monitored by an off-chain keeper that will update the protocol AUM.

contract RelayerV2 is QuarantineList {
  using SafeERC20 for IERC20;
  /*//////////////////////////////////////////////////////////////
                                 STORAGE
    //////////////////////////////////////////////////////////////*/

  ///@notice Fyde contract
  IFyde public fyde;

  ///@notice OracleModule contract
  IOracle public oracleModule;

  //@notice GovernanceModule contract
  IGovernanceModule public immutable GOVERNANCE_MODULE;

  //@notice calculates the tax for protocol actions
  ITaxModule public taxModule;

  ///@dev Only used for tracking events offchain
  uint32 public nonce;

  ///@notice Threshold of deviation for updating AUM
  uint16 public deviationThreshold;

  ///@notice State of the protocol
  bool public paused;

  //@notice Swap state
  bool public swapPaused;

  /*//////////////////////////////////////////////////////////////
                                 ERROR
    //////////////////////////////////////////////////////////////*/

  error ValueOutOfBounds();
  error ActionPaused();
  error SlippageExceed();
  error SwapDisabled(address asset);
  error AssetNotAllowedInGovernancePool(address asset);
  error DuplicatesAssets();

  /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

  event Pause(uint256 timestamp);
  event Unpause(uint256 timestamp);
  event Deposit(uint32 requestId, RequestData request);
  event Withdraw(uint32 requestId, RequestData request);
  event Swap(uint32 requestId, RequestData request);

  /*//////////////////////////////////////////////////////////////
                            CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

  constructor(address _oracleModule, address _govModule, uint8 _deviationThreshold)
    Ownable(msg.sender)
  {
    oracleModule = IOracle(_oracleModule);
    GOVERNANCE_MODULE = IGovernanceModule(_govModule);
    updateDeviationThreshold(_deviationThreshold);
  }

  /*//////////////////////////////////////////////////////////////
                                GUARD
    //////////////////////////////////////////////////////////////*/

  ///@notice Pause the protocol
  function pauseProtocol() public onlyGuard {
    paused = true;
    emit Pause(block.timestamp);
  }

  ///@notice Pause the swaps
  function pauseSwap() external onlyGuard {
    swapPaused = true;
    emit Pause(block.timestamp);
  }

  /*//////////////////////////////////////////////////////////////
                                 OWNER
    //////////////////////////////////////////////////////////////*/

  ///@notice sets the addres of fyde contract
  ///@param _fyde address of fyde
  function setFyde(address _fyde) external onlyOwner {
    fyde = IFyde(_fyde);
  }

  ///@notice Set the oracle module
  function setOracleModule(address _oracleModule) external onlyOwner {
    oracleModule = IOracle(_oracleModule);
  }

  ///@notice Set the tax module
  function setTaxModule(address _taxModule) external onlyOwner {
    taxModule = ITaxModule(_taxModule);
  }

  ///@notice Change the deviation threshold
  ///@dev 50 = 0.5 % of deviation
  function updateDeviationThreshold(uint16 _threshold) public onlyOwner {
    // We bound the threshold between 0.1 % to 10%
    if (_threshold < 10 || _threshold > 1000) revert ValueOutOfBounds();
    deviationThreshold = _threshold;
  }

  ///@notice Approve Fyde to transfer token from relayer, should be called once per asset
  function approveFyde(address[] calldata _assets) external onlyOwner {
    for (uint256 i; i < _assets.length; ++i) {
      IERC20(_assets[i]).safeApprove(address(fyde), type(uint256).max);
    }
  }

  ///@notice Collect and send token fees (from tax fees) to an external address
  ///@param _asset Address to send fees to
  ///@param _recipient Address to send fees to
  ///@param _amount Amount to send
  function collectFees(address _asset, address _recipient, uint256 _amount) external onlyOwner {
    IERC20(_asset).safeTransfer(_recipient, _amount);
  }

  ///@notice Unpause the protocol
  function unpauseProtocol() external onlyOwner {
    paused = false;
    emit Unpause(block.timestamp);
  }

  ///@notice Unpause the swaps
  function unpauseSwap() external onlyOwner {
    swapPaused = false;
    emit Unpause(block.timestamp);
  }

  /*//////////////////////////////////////////////////////////////
                            EXT USER ENTRY POINT
    //////////////////////////////////////////////////////////////*/

  ///@notice Entry function for depositing, can be a standard deposit or a governance
  /// deposit
  ///@param _userRequest struct containing data
  ///@param _keepGovRights If true make a governance
  ///@param _minTRSYExpected Slippage parameter ensuring minimum amout of TRSY to be received
  function deposit(
    UserRequest[] calldata _userRequest,
    bool _keepGovRights,
    uint256 _minTRSYExpected
  ) external whenNotPaused onlyUser {
    address[] memory assetIn = new address[](_userRequest.length);
    uint256[] memory amountIn = new uint256[](_userRequest.length);

    for (uint256 i; i < _userRequest.length; ++i) {
      // Unpack data
      assetIn[i] = _userRequest[i].asset;
      amountIn[i] = _userRequest[i].amount;
    }

    _checkForDuplicates(assetIn);

    if (_keepGovRights) _checkIsAllowedInGov(assetIn);

    RequestData memory req = RequestData({
      id: nonce,
      requestor: address(this),
      assetIn: assetIn,
      amountIn: amountIn,
      assetOut: new address[](0),
      amountOut: new uint256[](0),
      keepGovRights: _keepGovRights,
      slippageChecker: _minTRSYExpected
    });

    nonce++;

    uint256 currentAUM = fyde.getProtocolAUM();

    // Cache prices in oracle (gas savings when fyde reads prices)
    _enableOracleCache(assetIn);

    // get params for tax calculation from tax module
    (ProcessParam[] memory processParam, uint256 sharesToMint,,) =
      taxModule.getProcessParamDeposit(req, currentAUM);

    // Slippage checker
    if (req.slippageChecker > sharesToMint) revert SlippageExceed();

    // Transfer assets to Relayer
    for (uint256 i; i < req.assetIn.length; ++i) {
      IERC20(req.assetIn[i]).safeTransferFrom(msg.sender, address(this), req.amountIn[i]);
    }

    // Deposit
    fyde.processDeposit(currentAUM, req);

    if (_keepGovRights) {
      for (uint256 i; i < processParam.length; ++i) {
        // send staked trsy to the user
        address sTrsy = GOVERNANCE_MODULE.assetToStrsy(req.assetIn[i]);
        uint256 strsyBal = IERC20(sTrsy).balanceOf(address(this));
        uint256 toTransfer =
          strsyBal >= processParam[i].sharesAfterTax ? processParam[i].sharesAfterTax : strsyBal;
        IERC20(sTrsy).transfer(msg.sender, toTransfer);

        // unstake tax amount to get standard trsy
        uint256 taxTrsy = strsyBal - toTransfer;
        if (taxTrsy != 0) GOVERNANCE_MODULE.unstakeGov(taxTrsy, req.assetIn[i]);
      }
    } else {
      // send trsy to user
      IERC20(address(fyde)).transfer(msg.sender, sharesToMint);
    }

    _disableOracleCache();

    emit Deposit(req.id, req);
  }

  ///@notice Entry function for withdrawing
  ///@param _userRequest struct containing data
  ///@param _maxTRSYToPay Slippage parameter ensure maximum amout of TRSY willing to pay
  function withdraw(UserRequest[] calldata _userRequest, uint256 _maxTRSYToPay)
    external
    whenNotPaused
    onlyUser
  {
    address[] memory assetOut = new address[](_userRequest.length);
    uint256[] memory amountOut = new uint256[](_userRequest.length);

    for (uint256 i; i < _userRequest.length; i++) {
      assetOut[i] = _userRequest[i].asset;
      amountOut[i] = _userRequest[i].amount;
    }

    _checkForDuplicates(assetOut);

    RequestData memory req = RequestData({
      id: nonce,
      requestor: address(this),
      assetIn: new address[](0),
      amountIn: new uint256[](0),
      assetOut: assetOut,
      amountOut: amountOut,
      keepGovRights: false,
      slippageChecker: _maxTRSYToPay
    });

    nonce++;

    uint256 currentAUM = fyde.getProtocolAUM();

    _enableOracleCache(assetOut);

    // get params for tax calculation from tax module
    (, uint256 totalSharesToBurn,,,) = taxModule.getProcessParamWithdraw(req, currentAUM);

    if (totalSharesToBurn > req.slippageChecker) revert SlippageExceed();

    // Transfer TRSY to Relayer
    IERC20(address(fyde)).transferFrom(msg.sender, address(this), totalSharesToBurn);

    // Withdraw
    fyde.processWithdraw(currentAUM, req);

    // Transfer assets to user
    for (uint256 i; i < req.assetOut.length; ++i) {
      IERC20(req.assetOut[i]).safeTransfer(msg.sender, req.amountOut[i]);
    }

    _disableOracleCache();

    emit Withdraw(req.id, req);
  }

  ///@notice Function used by user to make a (single-token) withdrawal from their governance proxy
  ///@param _userRequest struct containing data
  ///@param _user address of user who makes the withdraw
  ///@param _maxTRSYToPay maximum amout of stTRSY willing to pay, otherwise withdraw reverts
  ///@dev owner of fyde can force withdraw for other users
  function governanceWithdraw(UserRequest memory _userRequest, address _user, uint256 _maxTRSYToPay)
    external
    whenNotPaused
    onlyUser
  {
    if (msg.sender != _user && msg.sender != owner) revert Unauthorized();

    address[] memory assetOut = new address[](1);
    uint256[] memory amountOut = new uint256[](1);

    assetOut[0] = _userRequest.asset;
    amountOut[0] = _userRequest.amount;

    // for withdraw, assetIn and amountIn are set to empty array
    RequestData memory request = RequestData({
      id: nonce,
      requestor: _user,
      assetIn: new address[](0),
      amountIn: new uint256[](0),
      assetOut: assetOut,
      amountOut: amountOut,
      keepGovRights: true,
      slippageChecker: _maxTRSYToPay
    });

    nonce++;

    uint256 currentAUM = fyde.getProtocolAUM();

    fyde.processWithdraw(currentAUM, request);
    emit Withdraw(request.id, request);
  }

  /*//////////////////////////////////////////////////////////////
                               SWAP
    //////////////////////////////////////////////////////////////*/

  function swap(address _assetIn, uint256 _amountIn, address _assetOut, uint256 _minAmountOut)
    external
    whenSwapNotPaused
    onlySwapper
  {
    address[] memory assetIn = new address[](1);
    uint256[] memory amountIn = new uint256[](1);
    address[] memory assetOut = new address[](1);
    uint256[] memory amountOut = new uint256[](1);

    assetIn[0] = _assetIn;
    amountIn[0] = _amountIn;
    assetOut[0] = _assetOut;

    RequestData memory req = RequestData({
      id: nonce,
      requestor: address(this),
      assetIn: assetIn,
      amountIn: amountIn,
      assetOut: assetOut,
      amountOut: amountOut,
      keepGovRights: false,
      slippageChecker: _minAmountOut
    });

    nonce++;

    uint256 currentAUM = fyde.getProtocolAUM();

    address[] memory assetsSwap = new address[](2);
    assetsSwap[0] = _assetIn;
    assetsSwap[1] = _assetOut;

    _enableOracleCache(assetsSwap);

    // get params for tax calculation from taxModule
    (uint256 amountOutTaxed,) =
      taxModule.getSwapAmountOut(req.assetIn[0], req.amountIn[0], req.assetOut[0], currentAUM);

    // Transfer asset to Relayer
    IERC20(req.assetIn[0]).safeTransferFrom(msg.sender, address(this), req.amountIn[0]);

    fyde.processSwap(currentAUM, req);

    uint256 tokenBalance = IERC20(assetOut[0]).balanceOf(address(this));

    amountOutTaxed = amountOutTaxed > tokenBalance ? tokenBalance : amountOutTaxed;
    if (amountOutTaxed < req.slippageChecker) revert SlippageExceed();

    // Transfer assets to swapper
    IERC20(req.assetOut[0]).safeTransfer(msg.sender, amountOutTaxed);

    emit Swap(req.id, req);

    // deposit tax to receive trsy
    amountIn[0] = tokenBalance - amountOutTaxed;
    if (amountIn[0] > 0) {
      req = RequestData({
        id: nonce,
        requestor: address(this),
        assetIn: assetOut,
        amountIn: amountIn,
        assetOut: new address[](0),
        amountOut: new uint256[](0),
        keepGovRights: false,
        slippageChecker: 0
      });

      nonce++;

      currentAUM = fyde.getProtocolAUM();
      fyde.processDeposit(currentAUM, req);
    }

    _disableOracleCache();
  }

  /*//////////////////////////////////////////////////////////////
                            Keeper FUNCTIONS
    //////////////////////////////////////////////////////////////*/

  ///@notice Offchain checker for AUM deviation
  function checkUpkeep(bytes calldata checkData)
    external
    view
    returns (bool upkeepNeeded, bytes memory performData)
  {
    (uint256 updateFactor, uint256 pauseFactor, bool isChainlink) =
      abi.decode(checkData, (uint256, uint256, bool));

    uint256 aum = fyde.getProtocolAUM();
    uint256 nAum = fyde.computeProtocolAUM();

    // AUM in range of deviation threshold times update factor do nothing
    if (PercentageMath._isInRange(aum, nAum, updateFactor * deviationThreshold / 100)) {
      return (false, "AUM is in range");
    }

    // if stored AUM exceeds the maximum deviation threshold by the pause factor
    // something is wrong and we stop the protocol
    if (!PercentageMath._isInRange(aum, nAum, pauseFactor * deviationThreshold / 100) && !paused) {
      if (isChainlink) return (true, abi.encode(false, 0));
      return (true, abi.encodeCall(this.performUpkeep, (abi.encode(false, 0))));
    }

    // if not in range and not outside the wider range, update AUM
    int256 diffAUM = int256(nAum) - int256(aum);
    if (isChainlink) return (true, abi.encode(true, diffAUM));
    return (true, abi.encodeCall(this.performUpkeep, (abi.encode(true, diffAUM))));
  }

  function performUpkeep(bytes calldata performData) external {
    (bool updateAum, int256 diffAUM) = abi.decode(performData, (bool, int256));

    if (!updateAum) {
      pauseProtocol();
    } else {
      uint256 nAum = uint256(int256(fyde.getProtocolAUM()) + diffAUM);
      updateProtocolAUM(nAum);
    }
  }

  ///@notice Update the protocol AUM, called by Keeper
  function updateProtocolAUM(uint256 nAum) public onlyKeeper {
    fyde.updateProtocolAUM(nAum);
  }
  /*//////////////////////////////////////////////////////////////
                                 INTERNAL
    //////////////////////////////////////////////////////////////*/

  function _enableOracleCache(address[] memory assets) internal {
    AssetInfo[] memory assetInfos = new AssetInfo[](assets.length);
    for (uint256 i; i < assets.length; ++i) {
      assetInfos[i] = fyde.assetInfo(assets[i]);
    }
    oracleModule.useCache(assets, assetInfos);
  }

  function _disableOracleCache() internal {
    oracleModule.disableCache();
  }

  function _checkIsAllowedInGov(address[] memory _assets) internal view {
    address notAllowedInGovAsset = GOVERNANCE_MODULE.isAnyNotOnGovWhitelist(_assets);
    if (notAllowedInGovAsset != address(0x0)) {
      revert AssetNotAllowedInGovernancePool(notAllowedInGovAsset);
    }
  }

  function _checkForDuplicates(address[] memory _assetList) internal pure {
    for (uint256 idx; idx < _assetList.length - 1; idx++) {
      for (uint256 idx2 = idx + 1; idx2 < _assetList.length; idx2++) {
        if (_assetList[idx] == _assetList[idx2]) revert DuplicatesAssets();
      }
    }
  }

  function _uint2str(uint256 _i) internal pure returns (string memory) {
    if (_i == 0) return "0";
    uint256 j = _i;
    uint256 len;
    while (j != 0) {
      len++;
      j /= 10;
    }
    bytes memory bstr = new bytes(len);
    uint256 k = len;
    while (_i != 0) {
      k = k - 1;
      uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
      bytes1 b1 = bytes1(temp);
      bstr[k] = b1;
      _i /= 10;
    }
    return string(bstr);
  }

  modifier whenNotPaused() {
    if (paused) revert ActionPaused();
    _;
  }

  modifier whenSwapNotPaused() {
    if (swapPaused) revert ActionPaused();
    _;
  }
}

File 2 of 14 : QuarantineList.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity 0.8.19;

import {AccessControl} from "./AccessControl.sol";

///@title QuarantineList contract
///@notice Handle the logic for the quarantine list
abstract contract QuarantineList is AccessControl {
  /// -----------------------------
  ///         Storage
  /// -----------------------------
  uint256 public min_quarantine_duration = 1 days;
  mapping(address => uint128) public quarantineList;

  /// -----------------------------
  ///         Events
  /// -----------------------------

  event AddedToQuarantine(address asset, uint128 expirationTime);
  event RemovedFromQuarantine(address asset);
  /// -----------------------------
  ///         Errors
  /// -----------------------------

  error AssetIsQuarantined(address asset);
  error AssetIsNotQuarantined(address asset);
  error ShortenedExpiration(uint128 currentExpiration, uint128 expiration);
  error ShortQurantineDuration(uint128 duration);

  /// -----------------------------
  ///         Admin external
  /// -----------------------------

  ///@notice Set the minimum quarantine duration
  ///@param _min_quarantine_duration the new minimum quarantine duration
  function set_min_quarantine_duration(uint256 _min_quarantine_duration) external onlyOwner {
    min_quarantine_duration = _min_quarantine_duration;
  }

  ///@notice Add an asset to the quarantine list
  ///@param _asset the address of the assset to be added to the quarantine list
  ///@param _duration the time (in seconds) that the asset should stay in quarantine
  function addToQuarantine(address _asset, uint128 _duration) external onlyGuard {
    if (_duration < min_quarantine_duration) revert ShortQurantineDuration(_duration);

    // gas savings
    uint128 expiration = uint128(block.timestamp) + _duration;
    uint128 currentExpiration = quarantineList[_asset];

    // the new expiration cannot be before the curent one i.e. expiration cannot be reduced, just
    // extended
    if (expiration <= currentExpiration) revert ShortenedExpiration(currentExpiration, expiration);

    quarantineList[_asset] = expiration;

    emit AddedToQuarantine(_asset, expiration);
  }

  ///@notice Remove an asset from the quarantine list
  ///@param _asset the address of the assset to be removed from the quarantine list
  function removeFromQuarantine(address _asset) external onlyGuard {
    // If the asset has nto been quarantined or the duarion period has expired then revert
    if (quarantineList[_asset] < uint128(block.timestamp)) revert AssetIsNotQuarantined(_asset);

    // just set the duration to zero to remove from quarantine
    quarantineList[_asset] = 0;
    emit RemovedFromQuarantine(_asset);
  }

  /// -----------------------------
  ///    External view functions
  /// -----------------------------

  ///@notice Check if an asset is quarantined
  ///@param _asset the address of the assset to be checked
  function isQuarantined(address _asset) public view returns (bool) {
    return quarantineList[_asset] >= uint128(block.timestamp);
  }

  ///@notice Check if any asset from a given list is quarantined
  ///@param _assets an array of asset addresses that need to be checked
  ///@return address of first quarantined asset or address(0x0) if none quarantined
  function isAnyQuarantined(address[] memory _assets) public view returns (address) {
    for (uint256 i = 0; i < _assets.length;) {
      if (isQuarantined(_assets[i])) return _assets[i];

      unchecked {
        ++i;
      }
    }
    return address(0x0);
  }
}

File 3 of 14 : Structs.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;

struct AssetInfo {
  uint72 targetConcentration;
  address uniswapPool;
  int72 incentiveFactor;
  uint8 assetDecimals;
  uint8 quoteTokenDecimals;
  address uniswapQuoteToken;
  bool isSupported;
}

struct ProtocolData {
  ///@notice Protocol AUM in USD
  uint256 aum;
  ///@notice multiplicator for the tax equation, 100% = 100e18
  uint72 taxFactor;
  ///@notice Max deviation allowed between AUM from keeper and registry
  uint16 maxAumDeviationAllowed; // Default val 200 == 2 %
  ///@notice block number where AUM was last updated
  uint48 lastAUMUpdateBlock;
  ///@notice annual fee on AUM, in % per year 100% = 100e18
  uint72 managementFee;
  ///@notice last block.timestamp when fee was collected
  uint48 lastFeeCollectionTime;
}

struct UserRequest {
  address asset;
  uint256 amount;
}

struct RequestData {
  uint32 id;
  address requestor;
  address[] assetIn;
  uint256[] amountIn;
  address[] assetOut;
  uint256[] amountOut;
  bool keepGovRights;
  uint256 slippageChecker;
}

struct RequestQ {
  uint64 start;
  uint64 end;
  mapping(uint64 => RequestData) requestData;
}

struct ProcessParam {
  uint256 targetConc;
  uint256 currentConc;
  uint256 usdValue;
  uint256 taxableAmount;
  uint256 taxInUSD;
  uint256 sharesBeforeTax;
  uint256 sharesAfterTax;
}

struct RebalanceParam {
  address asset;
  uint256 assetTotalAmount;
  uint256 assetProxyAmount;
  uint256 assetPrice;
  uint256 sTrsyTotalSupply;
  uint256 trsyPrice;
}

File 4 of 14 : Ownable.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.19;

///@title Ownable contract
/// @notice Simple 2step owner authorization combining solmate and OZ implementation
abstract contract Ownable {
  /*//////////////////////////////////////////////////////////////
                             STORAGE
    //////////////////////////////////////////////////////////////*/

  ///@notice Address of the owner
  address public owner;

  ///@notice Address of the pending owner
  address public pendingOwner;

  /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

  event OwnershipTransferred(address indexed user, address indexed newOner);
  event OwnershipTransferStarted(address indexed user, address indexed newOwner);
  event OwnershipTransferCanceled(address indexed pendingOwner);

  /*//////////////////////////////////////////////////////////////
                                 ERROR
    //////////////////////////////////////////////////////////////*/

  error Unauthorized();

  /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

  constructor(address _owner) {
    owner = _owner;

    emit OwnershipTransferred(address(0), _owner);
  }

  /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

  ///@notice Transfer ownership to a new address
  ///@param newOwner address of the new owner
  ///@dev newOwner have to acceptOwnership
  function transferOwnership(address newOwner) external onlyOwner {
    pendingOwner = newOwner;
    emit OwnershipTransferStarted(msg.sender, pendingOwner);
  }

  ///@notice NewOwner accept the ownership, it transfer the ownership to newOwner
  function acceptOwnership() external {
    if (msg.sender != pendingOwner) revert Unauthorized();
    address oldOwner = owner;
    owner = pendingOwner;
    delete pendingOwner;
    emit OwnershipTransferred(oldOwner, owner);
  }

  ///@notice Cancel the ownership transfer
  function cancelTransferOwnership() external onlyOwner {
    emit OwnershipTransferCanceled(pendingOwner);
    delete pendingOwner;
  }

  modifier onlyOwner() {
    if (msg.sender != owner) revert Unauthorized();
    _;
  }
}

File 5 of 14 : PercentageMath.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;

library PercentageMath {
  ///	CONSTANTS ///

  uint256 internal constant PERCENTAGE_FACTOR = 1e4; // 100.00%
  uint256 internal constant HALF_PERCENTAGE_FACTOR = 0.5e4; // 50.00%
  uint256 internal constant MAX_UINT256 = 2 ** 256 - 1;
  uint256 internal constant MAX_UINT256_MINUS_HALF_PERCENTAGE = 2 ** 256 - 1 - 0.5e4;

  /// INTERNAL ///

  ///@notice Check if value are within the range
  function _isInRange(uint256 valA, uint256 valB, uint256 deviationThreshold)
    internal
    pure
    returns (bool)
  {
    uint256 lowerBound = percentSub(valA, deviationThreshold);
    uint256 upperBound = percentAdd(valA, deviationThreshold);
    if (valB < lowerBound || valB > upperBound) return false;
    else return true;
  }

  /// @notice Executes a percentage addition (x * (1 + p)), rounded up.
  /// @param x The value to which to add the percentage.
  /// @param percentage The percentage of the value to add.
  /// @return y The result of the addition.
  function percentAdd(uint256 x, uint256 percentage) internal pure returns (uint256 y) {
    // Must revert if
    // PERCENTAGE_FACTOR + percentage > type(uint256).max
    //     or x * (PERCENTAGE_FACTOR + percentage) + HALF_PERCENTAGE_FACTOR > type(uint256).max
    // <=> percentage > type(uint256).max - PERCENTAGE_FACTOR
    //     or x > (type(uint256).max - HALF_PERCENTAGE_FACTOR) / (PERCENTAGE_FACTOR + percentage)
    // Note: PERCENTAGE_FACTOR + percentage >= PERCENTAGE_FACTOR > 0
    assembly {
      y := add(PERCENTAGE_FACTOR, percentage) // Temporary assignment to save gas.

      if or(
        gt(percentage, sub(MAX_UINT256, PERCENTAGE_FACTOR)),
        gt(x, div(MAX_UINT256_MINUS_HALF_PERCENTAGE, y))
      ) { revert(0, 0) }

      y := div(add(mul(x, y), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR)
    }
  }

  /// @notice Executes a percentage subtraction (x * (1 - p)), rounded up.
  /// @param x The value to which to subtract the percentage.
  /// @param percentage The percentage of the value to subtract.
  /// @return y The result of the subtraction.
  function percentSub(uint256 x, uint256 percentage) internal pure returns (uint256 y) {
    // Must revert if
    // percentage > PERCENTAGE_FACTOR
    //     or x * (PERCENTAGE_FACTOR - percentage) + HALF_PERCENTAGE_FACTOR > type(uint256).max
    // <=> percentage > PERCENTAGE_FACTOR
    //     or ((PERCENTAGE_FACTOR - percentage) > 0 and x > (type(uint256).max -
    // HALF_PERCENTAGE_FACTOR) / (PERCENTAGE_FACTOR - percentage))
    assembly {
      y := sub(PERCENTAGE_FACTOR, percentage) // Temporary assignment to save gas.

      if or(
        gt(percentage, PERCENTAGE_FACTOR), mul(y, gt(x, div(MAX_UINT256_MINUS_HALF_PERCENTAGE, y)))
      ) { revert(0, 0) }

      y := div(add(mul(x, y), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR)
    }
  }
}

File 6 of 14 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/IERC20Permit.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;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    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));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    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");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @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");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @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).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // 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 cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

File 7 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @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);
}

File 8 of 14 : IFyde.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.19;

import {RequestData, RebalanceParam, ProcessParam, AssetInfo} from "src/core/Structs.sol";

interface IFyde {
  function protocolData() external view returns (uint256, uint72, uint16, uint48, uint72, uint48);

  function assetInfo(address) external view returns (AssetInfo memory);

  function isAnyNotSupported(address[] calldata _assets) external view returns (address);

  function isSwapAllowed(address[] calldata _assets) external view returns (address);

  function computeProtocolAUM() external view returns (uint256);

  function getProtocolAUM() external view returns (uint256);

  function updateProtocolAUM(uint256) external;

  function processDeposit(uint256, RequestData calldata) external returns (uint256);

  function processWithdraw(uint256, RequestData calldata) external returns (uint256);

  function totalSupply() external view returns (uint256);

  function setOracleModule(address _oracle) external;

  function oracleModule() external view returns (address);

  function setRelayer(address _relayer) external;

  function RELAYER() external view returns (address);

  function totalAssetAccounting(address) external view returns (uint256);

  function proxyAssetAccounting(address) external view returns (uint256);

  function standardAssetAccounting(address) external view returns (uint256);

  function getQuote(address, uint256) external view returns (uint256);

  function getAssetDecimals(address) external view returns (uint8);

  function collectManagementFee() external;

  function getAssetsListLength() external view returns (uint256);

  function assetsList(uint256 index) external view returns (address);

  function processSwap(uint256, RequestData calldata) external returns (int256);

  function owner() external view returns (address);

  function getProcessParamDeposit(RequestData memory _req, uint256 _protocolAUM)
    external
    view
    returns (
      ProcessParam[] memory processParam,
      uint256 sharesToMint,
      uint256 taxInTRSY,
      uint256 totalUsdDeposit
    );

  function getProcessParamWithdraw(RequestData calldata _req, uint256 _protocolAUM)
    external
    view
    returns (
      ProcessParam[] memory processParam,
      uint256 totalSharesToBurn,
      uint256 sharesToBurnBeforeTax,
      uint256 taxInTRSY,
      uint256 totalUsdWithdraw
    );

  function acceptOwnership() external;

  // GOVERNANCE ACCESS FUNCTIONS

  function transferAsset(address _asset, address _recipient, uint256 _amount) external;

  function getRebalanceParams(address _asset) external view returns (RebalanceParam memory);

  function updateAssetProxyAmount(address _asset, uint256 _amount) external;
}

File 9 of 14 : IGovernanceModule.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.19;

interface IGovernanceModule {
  function fyde() external view returns (address);

  function proxyImplementation() external view returns (address);

  function proxyBalance(address proxy, address asset) external view returns (uint256);

  function strsyBalance(address _user, address _govToken) external view returns (uint256 balance);

  function assetToStrsy(address _asset) external view returns (address);

  function userToProxy(address _user) external view returns (address);

  function proxyToUser(address _proxy) external view returns (address);

  function isOnGovernanceWhitelist(address _asset) external view returns (bool);

  function getAllGovUsers() external view returns (address[] memory);

  function isAnyNotOnGovWhitelist(address[] calldata _assets) external view returns (address);

  function getUserGTAllowance(uint256 _TRSYAmount, address _token) external view returns (uint256);

  function govDeposit(
    address _depositor,
    address[] calldata _govToken,
    uint256[] calldata _amount,
    uint256[] calldata _amountTRSY,
    uint256 _totalTRSY
  ) external returns (address proxy);

  function govWithdraw(
    address _user,
    address _asset,
    uint256 _amountToWithdraw,
    uint256 _trsyToBurn
  ) external;

  function onStrsyTransfer(address sender, address _recipient) external;

  function unstakeGov(uint256 _amount, address _asset) external;

  function rebalanceProxy(address _proxy, address _asset, address[] memory _usersToRebalance)
    external;

  function acceptOwnership() external;
}

File 10 of 14 : IOracle.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.19;

import {AssetInfo} from "../core/Structs.sol";

interface IOracle {
  function getPriceInUSD(address, AssetInfo calldata) external view returns (uint256);

  function getGweiPrice() external view returns (uint256);

  function useCache(address[] calldata addr, AssetInfo[] calldata assetInfo) external;

  function disableCache() external;
}

File 11 of 14 : ITaxModule.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.19;

import {RequestData, ProcessParam} from "src/core/Structs.sol";

interface ITaxModule {
  function getProcessParamDeposit(RequestData memory _req, uint256 _protocolAUM)
    external
    view
    returns (
      ProcessParam[] memory processParam,
      uint256 sharesToMint,
      uint256 taxInTRSY,
      uint256 totalUsdDeposit
    );

  function getProcessParamWithdraw(RequestData calldata _req, uint256 _protocolAUM)
    external
    view
    returns (
      ProcessParam[] memory processParam,
      uint256 totalSharesToBurn,
      uint256 sharesToBurnBeforeTax,
      uint256 taxInTRSY,
      uint256 totalUsdWithdraw
    );

  function getSwapAmountOut(
    address _assetIn,
    uint256 _amountIn,
    address _assetOut,
    uint256 _protocolAUM
  ) external view returns (uint256, int256);
}

File 12 of 14 : AccessControl.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;

import {Ownable} from "src/utils/Ownable.sol";

///@title AccessControl
/// @notice Handles the different access authorizations for the relayer
abstract contract AccessControl is Ownable {
  /*//////////////////////////////////////////////////////////////
                             STORAGE
    //////////////////////////////////////////////////////////////*/

  ///@notice exclusive user - when != address(0x0), other users are removed from whitelist
  ///        intended for short term use during incidence response, escrow, migration
  address public exclusiveUser;

  ///@notice guard authorization
  mapping(address => bool) public isGuard;

  ///@notice keeper authorization
  mapping(address => bool) public isKeeper;

  ///@notice user authorization, can use deposit, withdraw
  mapping(address => bool) public isUser;

  ///@notice swapper authorization, can use swap
  mapping(address => bool) public isSwapper;

  ///@notice incentive manager authorization, can set incentives for swaps on Fyde
  mapping(address => bool) public isIncentiveManager;

  /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

  event ExclusiveUserSet(address indexed);
  event GuardAdded(address indexed);
  event GuardRemoved(address indexed);
  event KeeperAdded(address indexed);
  event KeeperRemoved(address indexed);
  event UserAdded(address indexed);
  event UserRemoved(address indexed);
  event IncentiveManagerAdded(address indexed);
  event IncentiveManagerRemoved(address indexed);
  event SwapperAdded(address indexed);
  event SwapperRemoved(address indexed);

  /*//////////////////////////////////////////////////////////////
                               SETTER
    //////////////////////////////////////////////////////////////*/

  function setExclusiveUser(address _exclusiveUser) external onlyOwner {
    exclusiveUser = _exclusiveUser;
    emit ExclusiveUserSet(_exclusiveUser);
  }

  function addGuard(address _guard) external onlyOwner {
    isGuard[_guard] = true;
    emit GuardAdded(_guard);
  }

  function removeGuard(address _guard) external onlyOwner {
    isGuard[_guard] = false;
    emit GuardRemoved(_guard);
  }

  function addKeeper(address _keeper) external onlyOwner {
    isKeeper[_keeper] = true;
    emit KeeperAdded(_keeper);
  }

  function removeKeeper(address _keeper) external onlyOwner {
    isKeeper[_keeper] = false;
    emit KeeperRemoved(_keeper);
  }

  function addUser(address[] calldata _user) external onlyOwner {
    for (uint256 i; i < _user.length; ++i) {
      isUser[_user[i]] = true;
      emit UserAdded(_user[i]);
    }
  }

  function removeUser(address[] calldata _user) external onlyOwner {
    for (uint256 i; i < _user.length; ++i) {
      isUser[_user[i]] = false;
      emit UserRemoved(_user[i]);
    }
  }

  function addIncentiveManager(address _incentiveManager) external onlyOwner {
    isIncentiveManager[_incentiveManager] = true;
    emit IncentiveManagerAdded(_incentiveManager);
  }

  function removeIncentiveManager(address _incentiveManager) external onlyOwner {
    isIncentiveManager[_incentiveManager] = false;
    emit IncentiveManagerRemoved(_incentiveManager);
  }

  function addSwapper(address _swapper) external onlyOwner {
    isSwapper[_swapper] = true;
    emit SwapperAdded(_swapper);
  }

  function removeSwapper(address _swapper) external onlyOwner {
    isSwapper[_swapper] = false;
    emit SwapperRemoved(_swapper);
  }

  /*//////////////////////////////////////////////////////////////
                               MODIFIER
    //////////////////////////////////////////////////////////////*/

  ///@notice only a registered keeper can access
  modifier onlyKeeper() {
    if (!isKeeper[msg.sender]) revert Unauthorized();
    _;
  }

  ///@notice only a registered guard can access
  modifier onlyGuard() {
    if (!isGuard[msg.sender]) revert Unauthorized();
    _;
  }

  ///@dev whitelisting address(0x0) disables whitelist -> full permissionless access
  ///@dev setting exclusiveUser to != address(0x0) blocks everyone else
  ///     - intended for escrow, incidence response and migration
  modifier onlyUser() {
    // if whitelist is not disabeld and user not whitelisted -> no access
    if (!isUser[address(0x0)] && !isUser[msg.sender]) revert Unauthorized();
    // if exclusive user exists and is not user -> no accesss
    if (exclusiveUser != address(0x0) && exclusiveUser != msg.sender) revert Unauthorized();
    _;
  }

  ///@dev whitelisting address(0x0) disables whitelist -> full permissionless access
  ///@dev setting exclusiveUser to != address(0x0) blocks everyone else
  ///     - intended for escrow, incidence response and migration
  modifier onlySwapper() {
    if (!isSwapper[address(0x0)] && !isSwapper[msg.sender]) revert Unauthorized();
    if (exclusiveUser != address(0x0) && exclusiveUser != msg.sender) revert Unauthorized();
    _;
  }
}

File 13 of 14 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 14 of 14 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or 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 {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

Settings
{
  "remappings": [
    "@uniswap/v3-core/=lib/v3-core/",
    "@uniswap/v3-periphery/=lib/v3-periphery/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "solmate/=lib/solmate/src/",
    "synthetix-v3/=lib/synthetix-v3/",
    "v3-core/=lib/v3-core/contracts/",
    "v3-periphery/=lib/v3-periphery/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_oracleModule","type":"address"},{"internalType":"address","name":"_govModule","type":"address"},{"internalType":"uint8","name":"_deviationThreshold","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ActionPaused","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"AssetIsNotQuarantined","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"AssetIsQuarantined","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"AssetNotAllowedInGovernancePool","type":"error"},{"inputs":[],"name":"DuplicatesAssets","type":"error"},{"inputs":[{"internalType":"uint128","name":"duration","type":"uint128"}],"name":"ShortQurantineDuration","type":"error"},{"inputs":[{"internalType":"uint128","name":"currentExpiration","type":"uint128"},{"internalType":"uint128","name":"expiration","type":"uint128"}],"name":"ShortenedExpiration","type":"error"},{"inputs":[],"name":"SlippageExceed","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"SwapDisabled","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ValueOutOfBounds","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint128","name":"expirationTime","type":"uint128"}],"name":"AddedToQuarantine","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"requestId","type":"uint32"},{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"address","name":"requestor","type":"address"},{"internalType":"address[]","name":"assetIn","type":"address[]"},{"internalType":"uint256[]","name":"amountIn","type":"uint256[]"},{"internalType":"address[]","name":"assetOut","type":"address[]"},{"internalType":"uint256[]","name":"amountOut","type":"uint256[]"},{"internalType":"bool","name":"keepGovRights","type":"bool"},{"internalType":"uint256","name":"slippageChecker","type":"uint256"}],"indexed":false,"internalType":"struct RequestData","name":"request","type":"tuple"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"ExclusiveUserSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"IncentiveManagerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"IncentiveManagerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"KeeperAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"KeeperRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipTransferCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"asset","type":"address"}],"name":"RemovedFromQuarantine","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"requestId","type":"uint32"},{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"address","name":"requestor","type":"address"},{"internalType":"address[]","name":"assetIn","type":"address[]"},{"internalType":"uint256[]","name":"amountIn","type":"uint256[]"},{"internalType":"address[]","name":"assetOut","type":"address[]"},{"internalType":"uint256[]","name":"amountOut","type":"uint256[]"},{"internalType":"bool","name":"keepGovRights","type":"bool"},{"internalType":"uint256","name":"slippageChecker","type":"uint256"}],"indexed":false,"internalType":"struct RequestData","name":"request","type":"tuple"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"SwapperAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"SwapperRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"UserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"UserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"requestId","type":"uint32"},{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"address","name":"requestor","type":"address"},{"internalType":"address[]","name":"assetIn","type":"address[]"},{"internalType":"uint256[]","name":"amountIn","type":"uint256[]"},{"internalType":"address[]","name":"assetOut","type":"address[]"},{"internalType":"uint256[]","name":"amountOut","type":"uint256[]"},{"internalType":"bool","name":"keepGovRights","type":"bool"},{"internalType":"uint256","name":"slippageChecker","type":"uint256"}],"indexed":false,"internalType":"struct RequestData","name":"request","type":"tuple"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"GOVERNANCE_MODULE","outputs":[{"internalType":"contract IGovernanceModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_incentiveManager","type":"address"}],"name":"addIncentiveManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"addKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_swapper","type":"address"}],"name":"addSwapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint128","name":"_duration","type":"uint128"}],"name":"addToQuarantine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_user","type":"address[]"}],"name":"addUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"approveFyde","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelTransferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"checkData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"collectFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct UserRequest[]","name":"_userRequest","type":"tuple[]"},{"internalType":"bool","name":"_keepGovRights","type":"bool"},{"internalType":"uint256","name":"_minTRSYExpected","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deviationThreshold","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exclusiveUser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fyde","outputs":[{"internalType":"contract IFyde","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct UserRequest","name":"_userRequest","type":"tuple"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_maxTRSYToPay","type":"uint256"}],"name":"governanceWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"isAnyQuarantined","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGuard","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isIncentiveManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isKeeper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"isQuarantined","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isSwapper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isUser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"min_quarantine_duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleModule","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"quarantineList","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"removeFromQuarantine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_incentiveManager","type":"address"}],"name":"removeIncentiveManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"removeKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_swapper","type":"address"}],"name":"removeSwapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_user","type":"address[]"}],"name":"removeUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_exclusiveUser","type":"address"}],"name":"setExclusiveUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fyde","type":"address"}],"name":"setFyde","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracleModule","type":"address"}],"name":"setOracleModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_taxModule","type":"address"}],"name":"setTaxModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_min_quarantine_duration","type":"uint256"}],"name":"set_min_quarantine_duration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_assetIn","type":"address"},{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_assetOut","type":"address"},{"internalType":"uint256","name":"_minAmountOut","type":"uint256"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxModule","outputs":[{"internalType":"contract ITaxModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_threshold","type":"uint16"}],"name":"updateDeviationThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nAum","type":"uint256"}],"name":"updateProtocolAUM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct UserRequest[]","name":"_userRequest","type":"tuple[]"},{"internalType":"uint256","name":"_maxTRSYToPay","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a0604052620151806008553480156200001857600080fd5b5060405162004c6338038062004c638339810160408190526200003b916200015a565b600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600b80546001600160a01b0319166001600160a01b03858116919091179091558216608052620000af60ff8216620000b8565b505050620001ad565b6000546001600160a01b03163314620000e3576040516282b42960e81b815260040160405180910390fd5b600a8161ffff161080620000fc57506103e88161ffff16115b156200011b57604051636d4d4a6760e11b815260040160405180910390fd5b600c805461ffff909216600160c01b0261ffff60c01b19909216919091179055565b80516001600160a01b03811681146200015557600080fd5b919050565b6000806000606084860312156200017057600080fd5b6200017b846200013d565b92506200018b602085016200013d565b9150604084015160ff81168114620001a257600080fd5b809150509250925092565b608051614a85620001de6000396000818161037401528181610ddf01528181610fdd01526136b10152614a856000f3fe608060405234801561001057600080fd5b50600436106103425760003560e01c806398fbfbea116101b8578063cdfca7f211610104578063e787caa4116100a2578063ed6b5ad51161007c578063ed6b5ad5146107f9578063f2fde38b14610801578063f80c6d9c14610814578063f93b6be51461082757600080fd5b8063e787caa4146107c0578063e838d0a9146107d3578063ec2a0992146107e657600080fd5b8063dbf62489116100de578063dbf624891461077f578063ddb015c814610787578063e00efe4a1461079a578063e30c3978146107ad57600080fd5b8063cdfca7f21461072d578063d307983d14610740578063d94ad8371461075757600080fd5b8063b623501611610171578063bae2be561161014b578063bae2be56146106e1578063c073fd74146106f4578063c87eed4614610707578063cc88688b1461071a57600080fd5b8063b623501614610698578063b64230ba146106ab578063b813a8df146106ce57600080fd5b806398fbfbea146105fd5780639938500614610610578063a8ad7a0314610623578063affed0e014610636578063b0bdafbe14610662578063b588c10b1461067557600080fd5b8063489c120211610292578063769315a4116102305780638a0ccd561161020a5780638a0ccd56146105bc5780638da5cb5b146105cf57806392fede00146105e257806393263b8a146105ea57600080fd5b8063769315a41461058e57806379ba5097146105a15780637cb1d3df146105a957600080fd5b80636913a63c1161026c5780636913a63c146105245780636ba42aaa146105375780636d9b83ec1461055a5780636e04ff0d1461056d57600080fd5b8063489c1202146104da5780634fd8cb94146104fd5780635c975abb1461051057600080fd5b80633b42d038116102ff5780634209fff1116102d95780634209fff1146104595780634585e33b1461047c578063485d6ef81461048f5780634866788b146104c757600080fd5b80633b42d038146104205780633f2d4131146104335780634032b72b1461044657600080fd5b806314ae9f2e1461034757806316805c811461035c5780631a366bb71461036f57806320157d0a146103b3578063245a4e72146103bb57806339663ef2146103df575b600080fd5b61035a610355366004613e4a565b61082f565b005b61035a61036a366004613eb9565b6108a2565b6103967f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61035a61116b565b600c546103cf90600160d81b900460ff1681565b60405190151581526020016103aa565b6104086103ed366004613e4a565b6009602052600090815260409020546001600160801b031681565b6040516001600160801b0390911681526020016103aa565b61035a61042e366004613f15565b6111d8565b61035a610441366004613e4a565b61126c565b61035a610454366004613e4a565b6112df565b6103cf610467366004613e4a565b60056020526000908152604090205460ff1681565b61035a61048a366004613f89565b611355565b6103cf61049d366004613e4a565b6001600160a01b03166000908152600960205260409020546001600160801b034281169116101590565b61035a6104d5366004614056565b611411565b6103cf6104e8366004613e4a565b60036020526000908152604090205460ff1681565b600a54610396906001600160a01b031681565b600c546103cf90600160d01b900460ff1681565b61035a610532366004613e4a565b611807565b6103cf610545366004613e4a565b60046020526000908152604090205460ff1681565b61035a6105683660046140d8565b61187d565b61058061057b366004613f89565b6118ac565b6040516103aa929190614141565b61035a61059c366004613f15565b611bd8565b61035a611cce565b61035a6105b736600461415c565b611d52565b61035a6105ca366004614180565b611dd4565b600054610396906001600160a01b031681565b61035a612652565b600254610396906001600160a01b031681565b61035a61060b366004613e4a565b6126c6565b61035a61061e366004613e4a565b61273c565b61035a6106313660046141c8565b6127b2565b600c5461064d90600160a01b900463ffffffff1681565b60405163ffffffff90911681526020016103aa565b61035a610670366004613e4a565b612d6c565b6103cf610683366004613e4a565b60076020526000908152604090205460ff1681565b61035a6106a6366004613e4a565b612db8565b6103cf6106b9366004613e4a565b60066020526000908152604090205460ff1681565b61035a6106dc366004614213565b612e2b565b61035a6106ef366004613e4a565b612f70565b61035a610702366004613e4a565b61304c565b61035a610715366004613e4a565b613098565b600b54610396906001600160a01b031681565b61035a61073b366004613f15565b61310b565b61074960085481565b6040519081526020016103aa565b600c5461076c90600160c01b900461ffff1681565b60405161ffff90911681526020016103aa565b61035a613201565b61035a610795366004613e4a565b613275565b61035a6107a8366004614258565b6132e9565b600154610396906001600160a01b031681565b61035a6107ce3660046140d8565b613327565b600c54610396906001600160a01b031681565b61035a6107f4366004613e4a565b6133b0565b61035a6133fc565b61035a61080f366004613e4a565b613470565b6103966108223660046142bc565b6134e6565b61035a613572565b6000546001600160a01b03163314610859576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260046020526040808220805460ff19169055517fa7a775c2c8141f7985c111748ec31c11e5e44b83528e105c8d1d4e8e6b81cf809190a250565b600c54600160d01b900460ff16156108cd576040516318c0a57b60e31b815260040160405180910390fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5460ff1615801561091857503360009081526005602052604090205460ff16155b15610935576040516282b42960e81b815260040160405180910390fd5b6002546001600160a01b03161580159061095a57506002546001600160a01b03163314155b15610977576040516282b42960e81b815260040160405180910390fd5b6000836001600160401b0381111561099157610991613fe8565b6040519080825280602002602001820160405280156109ba578160200160208202803683370190505b5090506000846001600160401b038111156109d7576109d7613fe8565b604051908082528060200260200182016040528015610a00578160200160208202803683370190505b50905060005b85811015610ab157868682818110610a2057610a2061434f565b610a369260206040909202019081019150613e4a565b838281518110610a4857610a4861434f565b60200260200101906001600160a01b031690816001600160a01b031681525050868682818110610a7a57610a7a61434f565b90506040020160200135828281518110610a9657610a9661434f565b6020908102919091010152610aaa8161437b565b9050610a06565b50610abb826135d9565b8315610aca57610aca82613697565b6040805161010081018252600c54600160a01b900463ffffffff168152306020820152908101839052606081018290526000906080810182604051908082528060200260200182016040528015610b2b578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610b5c578160200160208202803683370190505b5081528615156020820152604001859052600c8054919250600160a01b90910463ffffffff16906014610b8e83614394565b91906101000a81548163ffffffff021916908363ffffffff160217905550506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2691906143b7565b9050610c318461375c565b600c54604051630552ed0f60e21b815260009182916001600160a01b039091169063154bb43c90610c6890879087906004016144fe565b600060405180830381865afa158015610c85573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cad91908101906145dc565b505091509150808460e001511115610cd857604051635b688e4760e01b815260040160405180910390fd5b60005b846040015151811015610d5257610d42333087606001518481518110610d0357610d0361434f565b602002602001015188604001518581518110610d2157610d2161434f565b60200260200101516001600160a01b0316613921909392919063ffffffff16565b610d4b8161437b565b9050610cdb565b50600a54604051632d58fd7560e01b81526001600160a01b0390911690632d58fd7590610d859086908890600401614633565b6020604051808303816000875af1158015610da4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc891906143b7565b5087156110a65760005b82518110156110a05760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630e99550e87604001518481518110610e2257610e2261434f565b60200260200101516040518263ffffffff1660e01b8152600401610e5591906001600160a01b0391909116815260200190565b602060405180830381865afa158015610e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e96919061465c565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0491906143b7565b90506000858481518110610f1a57610f1a61434f565b602002602001015160c00151821015610f335781610f52565b858481518110610f4557610f4561434f565b602002602001015160c001515b60405163a9059cbb60e01b8152336004820152602481018290529091506001600160a01b0384169063a9059cbb906044016020604051808303816000875af1158015610fa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc69190614684565b506000610fd382846146a1565b9050801561108b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166329f9b686828b6040015188815181106110215761102161434f565b60200260200101516040518363ffffffff1660e01b81526004016110589291909182526001600160a01b0316602082015260400190565b600060405180830381600087803b15801561107257600080fd5b505af1158015611086573d6000803e3d6000fd5b505050505b50505050806110999061437b565b9050610dd2565b5061111d565b600a5460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156110f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111b9190614684565b505b61112561398c565b83516040517f566cb6be00efdb1d5df0cf7dc225dfa95b7293197e28c815e9a9ef8a3624a9b0916111579187906146ba565b60405180910390a150505050505050505050565b6000546001600160a01b03163314611195576040516282b42960e81b815260040160405180910390fd5b600c805460ff60d81b191690556040514281527faaa520fdd7d2c83061d632fa017b0432407e798818af63ea908589fceda39ab7906020015b60405180910390a1565b6000546001600160a01b03163314611202576040516282b42960e81b815260040160405180910390fd5b60005b8181101561126757600a54611257906001600160a01b03166000198585858181106112325761123261434f565b90506020020160208101906112479190613e4a565b6001600160a01b031691906139f0565b6112608161437b565b9050611205565b505050565b6000546001600160a01b03163314611296576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260066020526040808220805460ff19169055517f1bdacea439f3d52c1495fc881858088a33f2ad0cc4a6a1a08780ca96eb6b702d9190a250565b6000546001600160a01b03163314611309576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260046020526040808220805460ff19166001179055517f1584773458d98c71b34a270ee1100b3a42889bf91e3b7a858563b684c24d838e9190a250565b600080611364838501856146d9565b915091508161137a57611375613201565b61140b565b600081600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f491906143b7565b6113fe9190614705565b905061140981613327565b505b50505050565b600c54600160d01b900460ff161561143c576040516318c0a57b60e31b815260040160405180910390fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5460ff1615801561148757503360009081526005602052604090205460ff16155b156114a4576040516282b42960e81b815260040160405180910390fd5b6002546001600160a01b0316158015906114c957506002546001600160a01b03163314155b156114e6576040516282b42960e81b815260040160405180910390fd5b336001600160a01b0383161480159061150a57506000546001600160a01b03163314155b15611527576040516282b42960e81b815260040160405180910390fd5b6040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508460000151826000815181106115845761158461434f565b60200260200101906001600160a01b031690816001600160a01b0316815250508460200151816000815181106115bc576115bc61434f565b6020026020010181815250506000604051806101000160405280600c60149054906101000a900463ffffffff1663ffffffff168152602001866001600160a01b0316815260200160006001600160401b0381111561161c5761161c613fe8565b604051908082528060200260200182016040528015611645578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015611676578160200160208202803683370190505b508152602081018590526040810184905260016060820152608001859052600c8054919250600160a01b90910463ffffffff169060146116b583614394565b91906101000a81548163ffffffff021916908363ffffffff160217905550506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174d91906143b7565b600a54604051633ea1a23f60e11b81529192506001600160a01b031690637d43447e906117809084908690600401614633565b6020604051808303816000875af115801561179f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c391906143b7565b5081516040517fbd24668b5d3b2d8e900a72a66a182591f8c9dd2c8b0493785b5f6e385eb964a9916117f69185906146ba565b60405180910390a150505050505050565b6000546001600160a01b03163314611831576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260036020526040808220805460ff19166001179055517f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f599190a250565b6000546001600160a01b031633146118a7576040516282b42960e81b815260040160405180910390fd5b600855565b600060608180806118bf8688018861472d565b9250925092506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561191a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193e91906143b7565b90506000600a60009054906101000a90046001600160a01b03166001600160a01b03166383307f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015611995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b991906143b7565b600c549091506119ee90839083906064906119df90600160c01b900461ffff168a614766565b6119e9919061477d565b613b05565b15611a2b5760006040518060400160405280600f81526020016e41554d20697320696e2072616e676560881b815250965096505050505050611bd1565b600c54611a4e90839083906064906119df90600160c01b900461ffff1689614766565b158015611a655750600c54600160d01b900460ff16155b15611b16578215611aa357505060408051600060208201819052818301528151808203830181526060909101909152600195509350611bd192505050565b6040805160006020820181905281830152815180820383018152606082019092526001913091634585e33b91611adb9160840161479f565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050965096505050505050611bd1565b6000611b2283836147b2565b90508315611b5e576040805160016020820181905291810183905260600160405160208183030381529060405297509750505050505050611bd1565b604080516001602082018190529181018390523090634585e33b9060600160408051601f1981840301815290829052611b999160240161479f565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050975097505050505050505b9250929050565b6000546001600160a01b03163314611c02576040516282b42960e81b815260040160405180910390fd5b60005b8181101561126757600060056000858585818110611c2557611c2561434f565b9050602002016020810190611c3a9190613e4a565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055828282818110611c7457611c7461434f565b9050602002016020810190611c899190613e4a565b6001600160a01b03167fe9dce8c992623ce791725b21e857e33248d1f190a25b5168313420eebdaae99d60405160405180910390a2611cc78161437b565b9050611c05565b6001546001600160a01b03163314611cf8576040516282b42960e81b815260040160405180910390fd5b60008054600180546001600160a01b038082166001600160a01b031980861682178755909216909255604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6000546001600160a01b03163314611d7c576040516282b42960e81b815260040160405180910390fd5b600a8161ffff161080611d9457506103e88161ffff16115b15611db257604051636d4d4a6760e11b815260040160405180910390fd5b600c805461ffff909216600160c01b0261ffff60c01b19909216919091179055565b600c54600160d81b900460ff1615611dff576040516318c0a57b60e31b815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff16158015611e4a57503360009081526006602052604090205460ff16155b15611e67576040516282b42960e81b815260040160405180910390fd5b6002546001600160a01b031615801590611e8c57506002546001600160a01b03163314155b15611ea9576040516282b42960e81b815260040160405180910390fd5b604080516001808252818301909252600091602080830190803683375050604080516001808252818301909252929350600092915060208083019080368337505060408051600180825281830190925292935060009291506020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508784600081518110611f4857611f4861434f565b60200260200101906001600160a01b031690816001600160a01b0316815250508683600081518110611f7c57611f7c61434f565b6020026020010181815250508582600081518110611f9c57611f9c61434f565b6001600160a01b039092166020928302919091018201526040805161010081018252600c805463ffffffff600160a01b909104168083523094830194909452918101879052606081018690526080810185905260a08101849052600060c082015260e081018890529190601461201183614394565b91906101000a81548163ffffffff021916908363ffffffff160217905550506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612085573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a991906143b7565b60408051600280825260608201835292935060009290916020830190803683370190505090508a816000815181106120e3576120e361434f565b60200260200101906001600160a01b031690816001600160a01b03168152505088816001815181106121175761211761434f565b60200260200101906001600160a01b031690816001600160a01b0316815250506121408161375c565b600c54604084015180516000926001600160a01b03169163f58f951091849061216b5761216b61434f565b6020026020010151866060015160008151811061218a5761218a61434f565b602002602001015187608001516000815181106121a9576121a961434f565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201526024810192909252919091166044820152606481018690526084016040805180830381865afa15801561220f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223391906147d9565b509050612271333086606001516000815181106122525761225261434f565b60200260200101518760400151600081518110610d2157610d2161434f565b600a54604051633d655c3760e11b81526001600160a01b0390911690637acab86e906122a39086908890600401614633565b6020604051808303816000875af11580156122c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e691906143b7565b506000866000815181106122fc576122fc61434f565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561234c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237091906143b7565b905080821161237f5781612381565b805b91508460e001518210156123a857604051635b688e4760e01b815260040160405180910390fd5b6123e4338387608001516000815181106123c4576123c461434f565b60200260200101516001600160a01b0316613b4d9092919063ffffffff16565b84516040517fabbffc9fb8ca979e43d12dbd0d18675156cfa9a4e18e808eeb893fa05e46f5a1916124169188906146ba565b60405180910390a161242882826146a1565b8860008151811061243b5761243b61434f565b60200260200101818152505060008860008151811061245c5761245c61434f565b6020026020010151111561263b576040805161010081018252600c54600160a01b900463ffffffff168152306020820152908101889052606081018990526080810160006040519080825280602002602001820160405280156124c9578160200160208202803683370190505b50815260200160006040519080825280602002602001820160405280156124fa578160200160208202803683370190505b508152600060208201819052604090910152600c8054919650600160a01b90910463ffffffff1690601461252d83614394565b91906101000a81548163ffffffff021916908363ffffffff16021790555050600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561259f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c391906143b7565b600a54604051632d58fd7560e01b81529195506001600160a01b031690632d58fd75906125f69087908990600401614633565b6020604051808303816000875af1158015612615573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263991906143b7565b505b61264361398c565b50505050505050505050505050565b6000546001600160a01b0316331461267c576040516282b42960e81b815260040160405180910390fd5b6001546040516001600160a01b03909116907f6ecd4842251bedd053b09547c0fabaab9ec98506ebf24469e8dd5560412ed37f90600090a2600180546001600160a01b0319169055565b6000546001600160a01b031633146126f0576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260076020526040808220805460ff19166001179055517ff7de8a78655219727a7c0d0db42a97c024f91cb131c5713063c555ce7d7c56529190a250565b6000546001600160a01b03163314612766576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260066020526040808220805460ff19166001179055517f459edbd4f641bfd6cb8eba5ac1b9e7a4629853efd00cc505d055fd3b051867e09190a250565b600c54600160d01b900460ff16156127dd576040516318c0a57b60e31b815260040160405180910390fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5460ff1615801561282857503360009081526005602052604090205460ff16155b15612845576040516282b42960e81b815260040160405180910390fd5b6002546001600160a01b03161580159061286a57506002546001600160a01b03163314155b15612887576040516282b42960e81b815260040160405180910390fd5b6000826001600160401b038111156128a1576128a1613fe8565b6040519080825280602002602001820160405280156128ca578160200160208202803683370190505b5090506000836001600160401b038111156128e7576128e7613fe8565b604051908082528060200260200182016040528015612910578160200160208202803683370190505b50905060005b848110156129c3578585828181106129305761293061434f565b6129469260206040909202019081019150613e4a565b8382815181106129585761295861434f565b60200260200101906001600160a01b031690816001600160a01b03168152505085858281811061298a5761298a61434f565b905060400201602001358282815181106129a6576129a661434f565b6020908102919091010152806129bb8161437b565b915050612916565b506129cd826135d9565b6040805161010081018252600c54600160a01b900463ffffffff168152306020820152600091810182604051908082528060200260200182016040528015612a1f578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612a50578160200160208202803683370190505b508152602081018590526040810184905260006060820152608001859052600c8054919250600160a01b90910463ffffffff16906014612a8f83614394565b91906101000a81548163ffffffff021916908363ffffffff160217905550506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2791906143b7565b9050612b328461375c565b600c54604051634b1163ab60e11b81526000916001600160a01b031690639622c75690612b6590869086906004016144fe565b600060405180830381865afa158015612b82573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612baa91908101906147fd565b5050509150508260e00151811115612bd557604051635b688e4760e01b815260040160405180910390fd5b600a546040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015612c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c509190614684565b50600a54604051633ea1a23f60e11b81526001600160a01b0390911690637d43447e90612c839085908790600401614633565b6020604051808303816000875af1158015612ca2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc691906143b7565b5060005b836080015151811015612d1f57612d0f338560a001518381518110612cf157612cf161434f565b6020026020010151866080015184815181106123c4576123c461434f565b612d188161437b565b9050612cca565b50612d2861398c565b82516040517fbd24668b5d3b2d8e900a72a66a182591f8c9dd2c8b0493785b5f6e385eb964a991612d5a9186906146ba565b60405180910390a15050505050505050565b6000546001600160a01b03163314612d96576040516282b42960e81b815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314612de2576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260036020526040808220805460ff19169055517f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d0489190a250565b3360009081526003602052604090205460ff16612e5a576040516282b42960e81b815260040160405180910390fd5b600854816001600160801b03161015612e9657604051632797027760e01b81526001600160801b03821660048201526024015b60405180910390fd5b6000612ea2824261485e565b6001600160a01b0384166000908152600960205260409020549091506001600160801b039081169082168110612efe57604051630a4dc5d360e31b81526001600160801b03808316600483015283166024820152604401612e8d565b6001600160a01b03841660008181526009602090815260409182902080546001600160801b0319166001600160801b0387169081179091558251938452908301527f6a8b3a105d0f4bca0c6d25f6f59282c2cac3e2acdd3f3466dabe9725f3299703910160405180910390a150505050565b3360009081526003602052604090205460ff16612f9f576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166000908152600960205260409020546001600160801b0342811691161015612fef57604051637407be0b60e11b81526001600160a01b0382166004820152602401612e8d565b6001600160a01b03811660008181526009602090815260409182902080546001600160801b031916905590519182527f975fea2c466fdf1d3e8dd9969713fbfde0822e5b3921c18c0003e033f216bf5a910160405180910390a150565b6000546001600160a01b03163314613076576040516282b42960e81b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146130c2576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260076020526040808220805460ff19169055517f4d6789b83afc897fab8472d33d3f7cc1fba254215a1cd007ce51f3c5bf6f57729190a250565b6000546001600160a01b03163314613135576040516282b42960e81b815260040160405180910390fd5b60005b81811015611267576001600560008585858181106131585761315861434f565b905060200201602081019061316d9190613e4a565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558282828181106131a7576131a761434f565b90506020020160208101906131bc9190613e4a565b6001600160a01b03167f19ef9a4877199f89440a26acb26895ec02ed86f2df1aeaa90dc18041b892f71f60405160405180910390a26131fa8161437b565b9050613138565b3360009081526003602052604090205460ff16613230576040516282b42960e81b815260040160405180910390fd5b600c805460ff60d01b1916600160d01b1790556040517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d906111ce9042815260200190565b6000546001600160a01b0316331461329f576040516282b42960e81b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517fc720a84179457777bd6ab883473f5ae8b0d37c9d100fd66f070ddcbd35af020f90600090a250565b6000546001600160a01b03163314613313576040516282b42960e81b815260040160405180910390fd5b6112676001600160a01b0384168383613b4d565b3360009081526004602052604090205460ff16613356576040516282b42960e81b815260040160405180910390fd5b600a546040516339e1f2a960e21b8152600481018390526001600160a01b039091169063e787caa490602401600060405180830381600087803b15801561339c57600080fd5b505af1158015611409573d6000803e3d6000fd5b6000546001600160a01b031633146133da576040516282b42960e81b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b3360009081526003602052604090205460ff1661342b576040516282b42960e81b815260040160405180910390fd5b600c805460ff60d81b1916600160d81b1790556040517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d906111ce9042815260200190565b6000546001600160a01b0316331461349a576040516282b42960e81b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270090600090a350565b6000805b82518110156135695761353a8382815181106135085761350861434f565b60200260200101516001600160a01b03166000908152600960205260409020546001600160801b034281169116101590565b15613561578281815181106135515761355161434f565b6020026020010151915050919050565b6001016134ea565b50600092915050565b6000546001600160a01b0316331461359c576040516282b42960e81b815260040160405180910390fd5b600c805460ff60d01b191690556040514281527faaa520fdd7d2c83061d632fa017b0432407e798818af63ea908589fceda39ab7906020016111ce565b60005b600182516135ea91906146a1565b8110156136935760006135fe82600161487e565b90505b82518110156136805782818151811061361c5761361c61434f565b60200260200101516001600160a01b031683838151811061363f5761363f61434f565b60200260200101516001600160a01b03160361366e57604051630df7483960e41b815260040160405180910390fd5b806136788161437b565b915050613601565b508061368b8161437b565b9150506135dc565b5050565b60405163eb2fea2d60e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063eb2fea2d906136e6908590600401614891565b602060405180830381865afa158015613703573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613727919061465c565b90506001600160a01b038116156136935760405163b3ef117360e01b81526001600160a01b0382166004820152602401612e8d565b600081516001600160401b0381111561377757613777613fe8565b6040519080825280602002602001820160405280156137de57816020015b6040805160e08101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282526000199092019101816137955790505b50905060005b82518110156138b857600a5483516001600160a01b0390911690638b0dcb4e908590849081106138165761381661434f565b60200260200101516040518263ffffffff1660e01b815260040161384991906001600160a01b0391909116815260200190565b60e060405180830381865afa158015613866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061388a91906148c7565b82828151811061389c5761389c61434f565b6020026020010181905250806138b19061437b565b90506137e4565b50600b54604051637c9bd2a160e01b81526001600160a01b0390911690637c9bd2a1906138eb9085908590600401614969565b600060405180830381600087803b15801561390557600080fd5b505af1158015613919573d6000803e3d6000fd5b505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905261140b9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613b7d565b600b60009054906101000a90046001600160a01b03166001600160a01b03166305778fdf6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156139dc57600080fd5b505af115801561140b573d6000803e3d6000fd5b801580613a6a5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6891906143b7565b155b613ad55760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401612e8d565b6040516001600160a01b03831660248201526044810182905261126790849063095ea7b360e01b90606401613955565b600080613b128584613c52565b90506000613b208685613c83565b905081851080613b2f57508085115b15613b3f57600092505050613b46565b6001925050505b9392505050565b6040516001600160a01b03831660248201526044810182905261126790849063a9059cbb60e01b90606401613955565b6000613bd2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613ca29092919063ffffffff16565b9050805160001480613bf3575080806020019051810190613bf39190614684565b6112675760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401612e8d565b61271081810390821161138819829004841182021715613c7157600080fd5b61271092026113880191909104919050565b61271081016127101982116113881982900484111715613c7157600080fd5b6060613cb18484600085613cb9565b949350505050565b606082471015613d1a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401612e8d565b600080866001600160a01b03168587604051613d369190614a33565b60006040518083038185875af1925050503d8060008114613d73576040519150601f19603f3d011682016040523d82523d6000602084013e613d78565b606091505b5091509150613d8987838387613d94565b979650505050505050565b60608315613e03578251600003613dfc576001600160a01b0385163b613dfc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612e8d565b5081613cb1565b613cb18383815115613e185781518083602001fd5b8060405162461bcd60e51b8152600401612e8d919061479f565b6001600160a01b0381168114613e4757600080fd5b50565b600060208284031215613e5c57600080fd5b8135613b4681613e32565b60008083601f840112613e7957600080fd5b5081356001600160401b03811115613e9057600080fd5b6020830191508360208260061b8501011115611bd157600080fd5b8015158114613e4757600080fd5b60008060008060608587031215613ecf57600080fd5b84356001600160401b03811115613ee557600080fd5b613ef187828801613e67565b9095509350506020850135613f0581613eab565b9396929550929360400135925050565b60008060208385031215613f2857600080fd5b82356001600160401b0380821115613f3f57600080fd5b818501915085601f830112613f5357600080fd5b813581811115613f6257600080fd5b8660208260051b8501011115613f7757600080fd5b60209290920196919550909350505050565b60008060208385031215613f9c57600080fd5b82356001600160401b0380821115613fb357600080fd5b818501915085601f830112613fc757600080fd5b813581811115613fd657600080fd5b866020828501011115613f7757600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b038111828210171561402057614020613fe8565b60405290565b604051601f8201601f191681016001600160401b038111828210171561404e5761404e613fe8565b604052919050565b6000806000838503608081121561406c57600080fd5b604081121561407a57600080fd5b50604051604081018181106001600160401b038211171561409d5761409d613fe8565b60405284356140ab81613e32565b815260208581013590820152925060408401356140c781613e32565b929592945050506060919091013590565b6000602082840312156140ea57600080fd5b5035919050565b60005b8381101561410c5781810151838201526020016140f4565b50506000910152565b6000815180845261412d8160208601602086016140f1565b601f01601f19169290920160200192915050565b8215158152604060208201526000613cb16040830184614115565b60006020828403121561416e57600080fd5b813561ffff81168114613b4657600080fd5b6000806000806080858703121561419657600080fd5b84356141a181613e32565b93506020850135925060408501356141b881613e32565b9396929550929360600135925050565b6000806000604084860312156141dd57600080fd5b83356001600160401b038111156141f357600080fd5b6141ff86828701613e67565b909790965060209590950135949350505050565b6000806040838503121561422657600080fd5b823561423181613e32565b915060208301356001600160801b038116811461424d57600080fd5b809150509250929050565b60008060006060848603121561426d57600080fd5b833561427881613e32565b9250602084013561428881613e32565b929592945050506040919091013590565b60006001600160401b038211156142b2576142b2613fe8565b5060051b60200190565b600060208083850312156142cf57600080fd5b82356001600160401b038111156142e557600080fd5b8301601f810185136142f657600080fd5b803561430961430482614299565b614026565b81815260059190911b8201830190838101908783111561432857600080fd5b928401925b82841015613d8957833561434081613e32565b8252928401929084019061432d565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161438d5761438d614365565b5060010190565b600063ffffffff8083168181036143ad576143ad614365565b6001019392505050565b6000602082840312156143c957600080fd5b5051919050565b600081518084526020808501945080840160005b838110156144095781516001600160a01b0316875295820195908201906001016143e4565b509495945050505050565b600081518084526020808501945080840160005b8381101561440957815187529582019590820190600101614428565b805163ffffffff1682526000610100602083015161446d60208601826001600160a01b03169052565b506040830151816040860152614485828601826143d0565b9150506060830151848203606086015261449f8282614414565b915050608083015184820360808601526144b982826143d0565b91505060a083015184820360a08601526144d38282614414565b91505060c08301516144e960c086018215159052565b5060e083015160e08501528091505092915050565b6040815260006145116040830185614444565b90508260208301529392505050565b600082601f83011261453157600080fd5b8151602061454161430483614299565b82815260e0928302850182019282820191908785111561456057600080fd5b8387015b858110156145cf5781818a03121561457c5760008081fd5b614584613ffe565b81518152858201518682015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c080830151908201528452928401928101614564565b5090979650505050505050565b600080600080608085870312156145f257600080fd5b84516001600160401b0381111561460857600080fd5b61461487828801614520565b6020870151604088015160609098015191999098509095509350505050565b828152604060208201526000613cb16040830184614444565b805161465781613e32565b919050565b60006020828403121561466e57600080fd5b8151613b4681613e32565b805161465781613eab565b60006020828403121561469657600080fd5b8151613b4681613eab565b818103818111156146b4576146b4614365565b92915050565b63ffffffff83168152604060208201526000613cb16040830184614444565b600080604083850312156146ec57600080fd5b82356146f781613eab565b946020939093013593505050565b808201828112600083128015821682158216171561472557614725614365565b505092915050565b60008060006060848603121561474257600080fd5b8335925060208401359150604084013561475b81613eab565b809150509250925092565b80820281158282048414176146b4576146b4614365565b60008261479a57634e487b7160e01b600052601260045260246000fd5b500490565b602081526000613b466020830184614115565b81810360008312801583831316838312821617156147d2576147d2614365565b5092915050565b600080604083850312156147ec57600080fd5b505080516020909101519092909150565b600080600080600060a0868803121561481557600080fd5b85516001600160401b0381111561482b57600080fd5b61483788828901614520565b6020880151604089015160608a01516080909a0151929b919a509897509095509350505050565b6001600160801b038181168382160190808211156147d2576147d2614365565b808201808211156146b4576146b4614365565b602081526000613b4660208301846143d0565b8051600881900b811461465757600080fd5b805160ff8116811461465757600080fd5b600060e082840312156148d957600080fd5b6148e1613ffe565b825168ffffffffffffffffff811681146148fa57600080fd5b81526149086020840161464c565b6020820152614919604084016148a4565b604082015261492a606084016148b6565b606082015261493b608084016148b6565b608082015261494c60a0840161464c565b60a082015261495d60c08401614679565b60c08201529392505050565b6000604080835261497c818401866143d0565b83810360208581019190915285518083528682019282019060005b81811015614a25578451805168ffffffffffffffffff168452848101516001600160a01b0316858501528681015160080b8785015260608082015160ff908116918601919091526080808301519091169085015260a080820151614a05828701826001600160a01b03169052565b505060c0908101511515908401529383019360e090920191600101614997565b509098975050505050505050565b60008251614a458184602087016140f1565b919091019291505056fea2646970667358221220c87174f0c894151860a1e227ff037e959d1c5d845988d8e5d63c758ec670d13264736f6c63430008130033000000000000000000000000e8e40fd4ddab26b44b1fb2d6d73833cb0a33b736000000000000000000000000c6f50903a058f3807111619bd4b24ca64b8239e10000000000000000000000000000000000000000000000000000000000000064

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103425760003560e01c806398fbfbea116101b8578063cdfca7f211610104578063e787caa4116100a2578063ed6b5ad51161007c578063ed6b5ad5146107f9578063f2fde38b14610801578063f80c6d9c14610814578063f93b6be51461082757600080fd5b8063e787caa4146107c0578063e838d0a9146107d3578063ec2a0992146107e657600080fd5b8063dbf62489116100de578063dbf624891461077f578063ddb015c814610787578063e00efe4a1461079a578063e30c3978146107ad57600080fd5b8063cdfca7f21461072d578063d307983d14610740578063d94ad8371461075757600080fd5b8063b623501611610171578063bae2be561161014b578063bae2be56146106e1578063c073fd74146106f4578063c87eed4614610707578063cc88688b1461071a57600080fd5b8063b623501614610698578063b64230ba146106ab578063b813a8df146106ce57600080fd5b806398fbfbea146105fd5780639938500614610610578063a8ad7a0314610623578063affed0e014610636578063b0bdafbe14610662578063b588c10b1461067557600080fd5b8063489c120211610292578063769315a4116102305780638a0ccd561161020a5780638a0ccd56146105bc5780638da5cb5b146105cf57806392fede00146105e257806393263b8a146105ea57600080fd5b8063769315a41461058e57806379ba5097146105a15780637cb1d3df146105a957600080fd5b80636913a63c1161026c5780636913a63c146105245780636ba42aaa146105375780636d9b83ec1461055a5780636e04ff0d1461056d57600080fd5b8063489c1202146104da5780634fd8cb94146104fd5780635c975abb1461051057600080fd5b80633b42d038116102ff5780634209fff1116102d95780634209fff1146104595780634585e33b1461047c578063485d6ef81461048f5780634866788b146104c757600080fd5b80633b42d038146104205780633f2d4131146104335780634032b72b1461044657600080fd5b806314ae9f2e1461034757806316805c811461035c5780631a366bb71461036f57806320157d0a146103b3578063245a4e72146103bb57806339663ef2146103df575b600080fd5b61035a610355366004613e4a565b61082f565b005b61035a61036a366004613eb9565b6108a2565b6103967f000000000000000000000000c6f50903a058f3807111619bd4b24ca64b8239e181565b6040516001600160a01b0390911681526020015b60405180910390f35b61035a61116b565b600c546103cf90600160d81b900460ff1681565b60405190151581526020016103aa565b6104086103ed366004613e4a565b6009602052600090815260409020546001600160801b031681565b6040516001600160801b0390911681526020016103aa565b61035a61042e366004613f15565b6111d8565b61035a610441366004613e4a565b61126c565b61035a610454366004613e4a565b6112df565b6103cf610467366004613e4a565b60056020526000908152604090205460ff1681565b61035a61048a366004613f89565b611355565b6103cf61049d366004613e4a565b6001600160a01b03166000908152600960205260409020546001600160801b034281169116101590565b61035a6104d5366004614056565b611411565b6103cf6104e8366004613e4a565b60036020526000908152604090205460ff1681565b600a54610396906001600160a01b031681565b600c546103cf90600160d01b900460ff1681565b61035a610532366004613e4a565b611807565b6103cf610545366004613e4a565b60046020526000908152604090205460ff1681565b61035a6105683660046140d8565b61187d565b61058061057b366004613f89565b6118ac565b6040516103aa929190614141565b61035a61059c366004613f15565b611bd8565b61035a611cce565b61035a6105b736600461415c565b611d52565b61035a6105ca366004614180565b611dd4565b600054610396906001600160a01b031681565b61035a612652565b600254610396906001600160a01b031681565b61035a61060b366004613e4a565b6126c6565b61035a61061e366004613e4a565b61273c565b61035a6106313660046141c8565b6127b2565b600c5461064d90600160a01b900463ffffffff1681565b60405163ffffffff90911681526020016103aa565b61035a610670366004613e4a565b612d6c565b6103cf610683366004613e4a565b60076020526000908152604090205460ff1681565b61035a6106a6366004613e4a565b612db8565b6103cf6106b9366004613e4a565b60066020526000908152604090205460ff1681565b61035a6106dc366004614213565b612e2b565b61035a6106ef366004613e4a565b612f70565b61035a610702366004613e4a565b61304c565b61035a610715366004613e4a565b613098565b600b54610396906001600160a01b031681565b61035a61073b366004613f15565b61310b565b61074960085481565b6040519081526020016103aa565b600c5461076c90600160c01b900461ffff1681565b60405161ffff90911681526020016103aa565b61035a613201565b61035a610795366004613e4a565b613275565b61035a6107a8366004614258565b6132e9565b600154610396906001600160a01b031681565b61035a6107ce3660046140d8565b613327565b600c54610396906001600160a01b031681565b61035a6107f4366004613e4a565b6133b0565b61035a6133fc565b61035a61080f366004613e4a565b613470565b6103966108223660046142bc565b6134e6565b61035a613572565b6000546001600160a01b03163314610859576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260046020526040808220805460ff19169055517fa7a775c2c8141f7985c111748ec31c11e5e44b83528e105c8d1d4e8e6b81cf809190a250565b600c54600160d01b900460ff16156108cd576040516318c0a57b60e31b815260040160405180910390fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5460ff1615801561091857503360009081526005602052604090205460ff16155b15610935576040516282b42960e81b815260040160405180910390fd5b6002546001600160a01b03161580159061095a57506002546001600160a01b03163314155b15610977576040516282b42960e81b815260040160405180910390fd5b6000836001600160401b0381111561099157610991613fe8565b6040519080825280602002602001820160405280156109ba578160200160208202803683370190505b5090506000846001600160401b038111156109d7576109d7613fe8565b604051908082528060200260200182016040528015610a00578160200160208202803683370190505b50905060005b85811015610ab157868682818110610a2057610a2061434f565b610a369260206040909202019081019150613e4a565b838281518110610a4857610a4861434f565b60200260200101906001600160a01b031690816001600160a01b031681525050868682818110610a7a57610a7a61434f565b90506040020160200135828281518110610a9657610a9661434f565b6020908102919091010152610aaa8161437b565b9050610a06565b50610abb826135d9565b8315610aca57610aca82613697565b6040805161010081018252600c54600160a01b900463ffffffff168152306020820152908101839052606081018290526000906080810182604051908082528060200260200182016040528015610b2b578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015610b5c578160200160208202803683370190505b5081528615156020820152604001859052600c8054919250600160a01b90910463ffffffff16906014610b8e83614394565b91906101000a81548163ffffffff021916908363ffffffff160217905550506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2691906143b7565b9050610c318461375c565b600c54604051630552ed0f60e21b815260009182916001600160a01b039091169063154bb43c90610c6890879087906004016144fe565b600060405180830381865afa158015610c85573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cad91908101906145dc565b505091509150808460e001511115610cd857604051635b688e4760e01b815260040160405180910390fd5b60005b846040015151811015610d5257610d42333087606001518481518110610d0357610d0361434f565b602002602001015188604001518581518110610d2157610d2161434f565b60200260200101516001600160a01b0316613921909392919063ffffffff16565b610d4b8161437b565b9050610cdb565b50600a54604051632d58fd7560e01b81526001600160a01b0390911690632d58fd7590610d859086908890600401614633565b6020604051808303816000875af1158015610da4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc891906143b7565b5087156110a65760005b82518110156110a05760007f000000000000000000000000c6f50903a058f3807111619bd4b24ca64b8239e16001600160a01b0316630e99550e87604001518481518110610e2257610e2261434f565b60200260200101516040518263ffffffff1660e01b8152600401610e5591906001600160a01b0391909116815260200190565b602060405180830381865afa158015610e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e96919061465c565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0491906143b7565b90506000858481518110610f1a57610f1a61434f565b602002602001015160c00151821015610f335781610f52565b858481518110610f4557610f4561434f565b602002602001015160c001515b60405163a9059cbb60e01b8152336004820152602481018290529091506001600160a01b0384169063a9059cbb906044016020604051808303816000875af1158015610fa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc69190614684565b506000610fd382846146a1565b9050801561108b577f000000000000000000000000c6f50903a058f3807111619bd4b24ca64b8239e16001600160a01b03166329f9b686828b6040015188815181106110215761102161434f565b60200260200101516040518363ffffffff1660e01b81526004016110589291909182526001600160a01b0316602082015260400190565b600060405180830381600087803b15801561107257600080fd5b505af1158015611086573d6000803e3d6000fd5b505050505b50505050806110999061437b565b9050610dd2565b5061111d565b600a5460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156110f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111b9190614684565b505b61112561398c565b83516040517f566cb6be00efdb1d5df0cf7dc225dfa95b7293197e28c815e9a9ef8a3624a9b0916111579187906146ba565b60405180910390a150505050505050505050565b6000546001600160a01b03163314611195576040516282b42960e81b815260040160405180910390fd5b600c805460ff60d81b191690556040514281527faaa520fdd7d2c83061d632fa017b0432407e798818af63ea908589fceda39ab7906020015b60405180910390a1565b6000546001600160a01b03163314611202576040516282b42960e81b815260040160405180910390fd5b60005b8181101561126757600a54611257906001600160a01b03166000198585858181106112325761123261434f565b90506020020160208101906112479190613e4a565b6001600160a01b031691906139f0565b6112608161437b565b9050611205565b505050565b6000546001600160a01b03163314611296576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260066020526040808220805460ff19169055517f1bdacea439f3d52c1495fc881858088a33f2ad0cc4a6a1a08780ca96eb6b702d9190a250565b6000546001600160a01b03163314611309576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260046020526040808220805460ff19166001179055517f1584773458d98c71b34a270ee1100b3a42889bf91e3b7a858563b684c24d838e9190a250565b600080611364838501856146d9565b915091508161137a57611375613201565b61140b565b600081600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f491906143b7565b6113fe9190614705565b905061140981613327565b505b50505050565b600c54600160d01b900460ff161561143c576040516318c0a57b60e31b815260040160405180910390fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5460ff1615801561148757503360009081526005602052604090205460ff16155b156114a4576040516282b42960e81b815260040160405180910390fd5b6002546001600160a01b0316158015906114c957506002546001600160a01b03163314155b156114e6576040516282b42960e81b815260040160405180910390fd5b336001600160a01b0383161480159061150a57506000546001600160a01b03163314155b15611527576040516282b42960e81b815260040160405180910390fd5b6040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508460000151826000815181106115845761158461434f565b60200260200101906001600160a01b031690816001600160a01b0316815250508460200151816000815181106115bc576115bc61434f565b6020026020010181815250506000604051806101000160405280600c60149054906101000a900463ffffffff1663ffffffff168152602001866001600160a01b0316815260200160006001600160401b0381111561161c5761161c613fe8565b604051908082528060200260200182016040528015611645578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015611676578160200160208202803683370190505b508152602081018590526040810184905260016060820152608001859052600c8054919250600160a01b90910463ffffffff169060146116b583614394565b91906101000a81548163ffffffff021916908363ffffffff160217905550506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174d91906143b7565b600a54604051633ea1a23f60e11b81529192506001600160a01b031690637d43447e906117809084908690600401614633565b6020604051808303816000875af115801561179f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c391906143b7565b5081516040517fbd24668b5d3b2d8e900a72a66a182591f8c9dd2c8b0493785b5f6e385eb964a9916117f69185906146ba565b60405180910390a150505050505050565b6000546001600160a01b03163314611831576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260036020526040808220805460ff19166001179055517f93405f05cd04f0d1bd875f2de00f1f3890484ffd0589248953bdfd29ba7f2f599190a250565b6000546001600160a01b031633146118a7576040516282b42960e81b815260040160405180910390fd5b600855565b600060608180806118bf8688018861472d565b9250925092506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561191a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193e91906143b7565b90506000600a60009054906101000a90046001600160a01b03166001600160a01b03166383307f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015611995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b991906143b7565b600c549091506119ee90839083906064906119df90600160c01b900461ffff168a614766565b6119e9919061477d565b613b05565b15611a2b5760006040518060400160405280600f81526020016e41554d20697320696e2072616e676560881b815250965096505050505050611bd1565b600c54611a4e90839083906064906119df90600160c01b900461ffff1689614766565b158015611a655750600c54600160d01b900460ff16155b15611b16578215611aa357505060408051600060208201819052818301528151808203830181526060909101909152600195509350611bd192505050565b6040805160006020820181905281830152815180820383018152606082019092526001913091634585e33b91611adb9160840161479f565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050965096505050505050611bd1565b6000611b2283836147b2565b90508315611b5e576040805160016020820181905291810183905260600160405160208183030381529060405297509750505050505050611bd1565b604080516001602082018190529181018390523090634585e33b9060600160408051601f1981840301815290829052611b999160240161479f565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050975097505050505050505b9250929050565b6000546001600160a01b03163314611c02576040516282b42960e81b815260040160405180910390fd5b60005b8181101561126757600060056000858585818110611c2557611c2561434f565b9050602002016020810190611c3a9190613e4a565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055828282818110611c7457611c7461434f565b9050602002016020810190611c899190613e4a565b6001600160a01b03167fe9dce8c992623ce791725b21e857e33248d1f190a25b5168313420eebdaae99d60405160405180910390a2611cc78161437b565b9050611c05565b6001546001600160a01b03163314611cf8576040516282b42960e81b815260040160405180910390fd5b60008054600180546001600160a01b038082166001600160a01b031980861682178755909216909255604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6000546001600160a01b03163314611d7c576040516282b42960e81b815260040160405180910390fd5b600a8161ffff161080611d9457506103e88161ffff16115b15611db257604051636d4d4a6760e11b815260040160405180910390fd5b600c805461ffff909216600160c01b0261ffff60c01b19909216919091179055565b600c54600160d81b900460ff1615611dff576040516318c0a57b60e31b815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff16158015611e4a57503360009081526006602052604090205460ff16155b15611e67576040516282b42960e81b815260040160405180910390fd5b6002546001600160a01b031615801590611e8c57506002546001600160a01b03163314155b15611ea9576040516282b42960e81b815260040160405180910390fd5b604080516001808252818301909252600091602080830190803683375050604080516001808252818301909252929350600092915060208083019080368337505060408051600180825281830190925292935060009291506020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508784600081518110611f4857611f4861434f565b60200260200101906001600160a01b031690816001600160a01b0316815250508683600081518110611f7c57611f7c61434f565b6020026020010181815250508582600081518110611f9c57611f9c61434f565b6001600160a01b039092166020928302919091018201526040805161010081018252600c805463ffffffff600160a01b909104168083523094830194909452918101879052606081018690526080810185905260a08101849052600060c082015260e081018890529190601461201183614394565b91906101000a81548163ffffffff021916908363ffffffff160217905550506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612085573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a991906143b7565b60408051600280825260608201835292935060009290916020830190803683370190505090508a816000815181106120e3576120e361434f565b60200260200101906001600160a01b031690816001600160a01b03168152505088816001815181106121175761211761434f565b60200260200101906001600160a01b031690816001600160a01b0316815250506121408161375c565b600c54604084015180516000926001600160a01b03169163f58f951091849061216b5761216b61434f565b6020026020010151866060015160008151811061218a5761218a61434f565b602002602001015187608001516000815181106121a9576121a961434f565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201526024810192909252919091166044820152606481018690526084016040805180830381865afa15801561220f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223391906147d9565b509050612271333086606001516000815181106122525761225261434f565b60200260200101518760400151600081518110610d2157610d2161434f565b600a54604051633d655c3760e11b81526001600160a01b0390911690637acab86e906122a39086908890600401614633565b6020604051808303816000875af11580156122c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e691906143b7565b506000866000815181106122fc576122fc61434f565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561234c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237091906143b7565b905080821161237f5781612381565b805b91508460e001518210156123a857604051635b688e4760e01b815260040160405180910390fd5b6123e4338387608001516000815181106123c4576123c461434f565b60200260200101516001600160a01b0316613b4d9092919063ffffffff16565b84516040517fabbffc9fb8ca979e43d12dbd0d18675156cfa9a4e18e808eeb893fa05e46f5a1916124169188906146ba565b60405180910390a161242882826146a1565b8860008151811061243b5761243b61434f565b60200260200101818152505060008860008151811061245c5761245c61434f565b6020026020010151111561263b576040805161010081018252600c54600160a01b900463ffffffff168152306020820152908101889052606081018990526080810160006040519080825280602002602001820160405280156124c9578160200160208202803683370190505b50815260200160006040519080825280602002602001820160405280156124fa578160200160208202803683370190505b508152600060208201819052604090910152600c8054919650600160a01b90910463ffffffff1690601461252d83614394565b91906101000a81548163ffffffff021916908363ffffffff16021790555050600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561259f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c391906143b7565b600a54604051632d58fd7560e01b81529195506001600160a01b031690632d58fd75906125f69087908990600401614633565b6020604051808303816000875af1158015612615573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263991906143b7565b505b61264361398c565b50505050505050505050505050565b6000546001600160a01b0316331461267c576040516282b42960e81b815260040160405180910390fd5b6001546040516001600160a01b03909116907f6ecd4842251bedd053b09547c0fabaab9ec98506ebf24469e8dd5560412ed37f90600090a2600180546001600160a01b0319169055565b6000546001600160a01b031633146126f0576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260076020526040808220805460ff19166001179055517ff7de8a78655219727a7c0d0db42a97c024f91cb131c5713063c555ce7d7c56529190a250565b6000546001600160a01b03163314612766576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260066020526040808220805460ff19166001179055517f459edbd4f641bfd6cb8eba5ac1b9e7a4629853efd00cc505d055fd3b051867e09190a250565b600c54600160d01b900460ff16156127dd576040516318c0a57b60e31b815260040160405180910390fd5b6000805260056020527f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc5460ff1615801561282857503360009081526005602052604090205460ff16155b15612845576040516282b42960e81b815260040160405180910390fd5b6002546001600160a01b03161580159061286a57506002546001600160a01b03163314155b15612887576040516282b42960e81b815260040160405180910390fd5b6000826001600160401b038111156128a1576128a1613fe8565b6040519080825280602002602001820160405280156128ca578160200160208202803683370190505b5090506000836001600160401b038111156128e7576128e7613fe8565b604051908082528060200260200182016040528015612910578160200160208202803683370190505b50905060005b848110156129c3578585828181106129305761293061434f565b6129469260206040909202019081019150613e4a565b8382815181106129585761295861434f565b60200260200101906001600160a01b031690816001600160a01b03168152505085858281811061298a5761298a61434f565b905060400201602001358282815181106129a6576129a661434f565b6020908102919091010152806129bb8161437b565b915050612916565b506129cd826135d9565b6040805161010081018252600c54600160a01b900463ffffffff168152306020820152600091810182604051908082528060200260200182016040528015612a1f578160200160208202803683370190505b5081526020016000604051908082528060200260200182016040528015612a50578160200160208202803683370190505b508152602081018590526040810184905260006060820152608001859052600c8054919250600160a01b90910463ffffffff16906014612a8f83614394565b91906101000a81548163ffffffff021916908363ffffffff160217905550506000600a60009054906101000a90046001600160a01b03166001600160a01b0316638be859ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2791906143b7565b9050612b328461375c565b600c54604051634b1163ab60e11b81526000916001600160a01b031690639622c75690612b6590869086906004016144fe565b600060405180830381865afa158015612b82573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612baa91908101906147fd565b5050509150508260e00151811115612bd557604051635b688e4760e01b815260040160405180910390fd5b600a546040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b03909116906323b872dd906064016020604051808303816000875af1158015612c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c509190614684565b50600a54604051633ea1a23f60e11b81526001600160a01b0390911690637d43447e90612c839085908790600401614633565b6020604051808303816000875af1158015612ca2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc691906143b7565b5060005b836080015151811015612d1f57612d0f338560a001518381518110612cf157612cf161434f565b6020026020010151866080015184815181106123c4576123c461434f565b612d188161437b565b9050612cca565b50612d2861398c565b82516040517fbd24668b5d3b2d8e900a72a66a182591f8c9dd2c8b0493785b5f6e385eb964a991612d5a9186906146ba565b60405180910390a15050505050505050565b6000546001600160a01b03163314612d96576040516282b42960e81b815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314612de2576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260036020526040808220805460ff19169055517f59926e0a78d12238b668b31c8e3f6ece235a59a00ede111d883e255b68c4d0489190a250565b3360009081526003602052604090205460ff16612e5a576040516282b42960e81b815260040160405180910390fd5b600854816001600160801b03161015612e9657604051632797027760e01b81526001600160801b03821660048201526024015b60405180910390fd5b6000612ea2824261485e565b6001600160a01b0384166000908152600960205260409020549091506001600160801b039081169082168110612efe57604051630a4dc5d360e31b81526001600160801b03808316600483015283166024820152604401612e8d565b6001600160a01b03841660008181526009602090815260409182902080546001600160801b0319166001600160801b0387169081179091558251938452908301527f6a8b3a105d0f4bca0c6d25f6f59282c2cac3e2acdd3f3466dabe9725f3299703910160405180910390a150505050565b3360009081526003602052604090205460ff16612f9f576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166000908152600960205260409020546001600160801b0342811691161015612fef57604051637407be0b60e11b81526001600160a01b0382166004820152602401612e8d565b6001600160a01b03811660008181526009602090815260409182902080546001600160801b031916905590519182527f975fea2c466fdf1d3e8dd9969713fbfde0822e5b3921c18c0003e033f216bf5a910160405180910390a150565b6000546001600160a01b03163314613076576040516282b42960e81b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146130c2576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260076020526040808220805460ff19169055517f4d6789b83afc897fab8472d33d3f7cc1fba254215a1cd007ce51f3c5bf6f57729190a250565b6000546001600160a01b03163314613135576040516282b42960e81b815260040160405180910390fd5b60005b81811015611267576001600560008585858181106131585761315861434f565b905060200201602081019061316d9190613e4a565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558282828181106131a7576131a761434f565b90506020020160208101906131bc9190613e4a565b6001600160a01b03167f19ef9a4877199f89440a26acb26895ec02ed86f2df1aeaa90dc18041b892f71f60405160405180910390a26131fa8161437b565b9050613138565b3360009081526003602052604090205460ff16613230576040516282b42960e81b815260040160405180910390fd5b600c805460ff60d01b1916600160d01b1790556040517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d906111ce9042815260200190565b6000546001600160a01b0316331461329f576040516282b42960e81b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517fc720a84179457777bd6ab883473f5ae8b0d37c9d100fd66f070ddcbd35af020f90600090a250565b6000546001600160a01b03163314613313576040516282b42960e81b815260040160405180910390fd5b6112676001600160a01b0384168383613b4d565b3360009081526004602052604090205460ff16613356576040516282b42960e81b815260040160405180910390fd5b600a546040516339e1f2a960e21b8152600481018390526001600160a01b039091169063e787caa490602401600060405180830381600087803b15801561339c57600080fd5b505af1158015611409573d6000803e3d6000fd5b6000546001600160a01b031633146133da576040516282b42960e81b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b3360009081526003602052604090205460ff1661342b576040516282b42960e81b815260040160405180910390fd5b600c805460ff60d81b1916600160d81b1790556040517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d906111ce9042815260200190565b6000546001600160a01b0316331461349a576040516282b42960e81b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270090600090a350565b6000805b82518110156135695761353a8382815181106135085761350861434f565b60200260200101516001600160a01b03166000908152600960205260409020546001600160801b034281169116101590565b15613561578281815181106135515761355161434f565b6020026020010151915050919050565b6001016134ea565b50600092915050565b6000546001600160a01b0316331461359c576040516282b42960e81b815260040160405180910390fd5b600c805460ff60d01b191690556040514281527faaa520fdd7d2c83061d632fa017b0432407e798818af63ea908589fceda39ab7906020016111ce565b60005b600182516135ea91906146a1565b8110156136935760006135fe82600161487e565b90505b82518110156136805782818151811061361c5761361c61434f565b60200260200101516001600160a01b031683838151811061363f5761363f61434f565b60200260200101516001600160a01b03160361366e57604051630df7483960e41b815260040160405180910390fd5b806136788161437b565b915050613601565b508061368b8161437b565b9150506135dc565b5050565b60405163eb2fea2d60e01b81526000906001600160a01b037f000000000000000000000000c6f50903a058f3807111619bd4b24ca64b8239e1169063eb2fea2d906136e6908590600401614891565b602060405180830381865afa158015613703573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613727919061465c565b90506001600160a01b038116156136935760405163b3ef117360e01b81526001600160a01b0382166004820152602401612e8d565b600081516001600160401b0381111561377757613777613fe8565b6040519080825280602002602001820160405280156137de57816020015b6040805160e08101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282526000199092019101816137955790505b50905060005b82518110156138b857600a5483516001600160a01b0390911690638b0dcb4e908590849081106138165761381661434f565b60200260200101516040518263ffffffff1660e01b815260040161384991906001600160a01b0391909116815260200190565b60e060405180830381865afa158015613866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061388a91906148c7565b82828151811061389c5761389c61434f565b6020026020010181905250806138b19061437b565b90506137e4565b50600b54604051637c9bd2a160e01b81526001600160a01b0390911690637c9bd2a1906138eb9085908590600401614969565b600060405180830381600087803b15801561390557600080fd5b505af1158015613919573d6000803e3d6000fd5b505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905261140b9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613b7d565b600b60009054906101000a90046001600160a01b03166001600160a01b03166305778fdf6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156139dc57600080fd5b505af115801561140b573d6000803e3d6000fd5b801580613a6a5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6891906143b7565b155b613ad55760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401612e8d565b6040516001600160a01b03831660248201526044810182905261126790849063095ea7b360e01b90606401613955565b600080613b128584613c52565b90506000613b208685613c83565b905081851080613b2f57508085115b15613b3f57600092505050613b46565b6001925050505b9392505050565b6040516001600160a01b03831660248201526044810182905261126790849063a9059cbb60e01b90606401613955565b6000613bd2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613ca29092919063ffffffff16565b9050805160001480613bf3575080806020019051810190613bf39190614684565b6112675760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401612e8d565b61271081810390821161138819829004841182021715613c7157600080fd5b61271092026113880191909104919050565b61271081016127101982116113881982900484111715613c7157600080fd5b6060613cb18484600085613cb9565b949350505050565b606082471015613d1a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401612e8d565b600080866001600160a01b03168587604051613d369190614a33565b60006040518083038185875af1925050503d8060008114613d73576040519150601f19603f3d011682016040523d82523d6000602084013e613d78565b606091505b5091509150613d8987838387613d94565b979650505050505050565b60608315613e03578251600003613dfc576001600160a01b0385163b613dfc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612e8d565b5081613cb1565b613cb18383815115613e185781518083602001fd5b8060405162461bcd60e51b8152600401612e8d919061479f565b6001600160a01b0381168114613e4757600080fd5b50565b600060208284031215613e5c57600080fd5b8135613b4681613e32565b60008083601f840112613e7957600080fd5b5081356001600160401b03811115613e9057600080fd5b6020830191508360208260061b8501011115611bd157600080fd5b8015158114613e4757600080fd5b60008060008060608587031215613ecf57600080fd5b84356001600160401b03811115613ee557600080fd5b613ef187828801613e67565b9095509350506020850135613f0581613eab565b9396929550929360400135925050565b60008060208385031215613f2857600080fd5b82356001600160401b0380821115613f3f57600080fd5b818501915085601f830112613f5357600080fd5b813581811115613f6257600080fd5b8660208260051b8501011115613f7757600080fd5b60209290920196919550909350505050565b60008060208385031215613f9c57600080fd5b82356001600160401b0380821115613fb357600080fd5b818501915085601f830112613fc757600080fd5b813581811115613fd657600080fd5b866020828501011115613f7757600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b038111828210171561402057614020613fe8565b60405290565b604051601f8201601f191681016001600160401b038111828210171561404e5761404e613fe8565b604052919050565b6000806000838503608081121561406c57600080fd5b604081121561407a57600080fd5b50604051604081018181106001600160401b038211171561409d5761409d613fe8565b60405284356140ab81613e32565b815260208581013590820152925060408401356140c781613e32565b929592945050506060919091013590565b6000602082840312156140ea57600080fd5b5035919050565b60005b8381101561410c5781810151838201526020016140f4565b50506000910152565b6000815180845261412d8160208601602086016140f1565b601f01601f19169290920160200192915050565b8215158152604060208201526000613cb16040830184614115565b60006020828403121561416e57600080fd5b813561ffff81168114613b4657600080fd5b6000806000806080858703121561419657600080fd5b84356141a181613e32565b93506020850135925060408501356141b881613e32565b9396929550929360600135925050565b6000806000604084860312156141dd57600080fd5b83356001600160401b038111156141f357600080fd5b6141ff86828701613e67565b909790965060209590950135949350505050565b6000806040838503121561422657600080fd5b823561423181613e32565b915060208301356001600160801b038116811461424d57600080fd5b809150509250929050565b60008060006060848603121561426d57600080fd5b833561427881613e32565b9250602084013561428881613e32565b929592945050506040919091013590565b60006001600160401b038211156142b2576142b2613fe8565b5060051b60200190565b600060208083850312156142cf57600080fd5b82356001600160401b038111156142e557600080fd5b8301601f810185136142f657600080fd5b803561430961430482614299565b614026565b81815260059190911b8201830190838101908783111561432857600080fd5b928401925b82841015613d8957833561434081613e32565b8252928401929084019061432d565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161438d5761438d614365565b5060010190565b600063ffffffff8083168181036143ad576143ad614365565b6001019392505050565b6000602082840312156143c957600080fd5b5051919050565b600081518084526020808501945080840160005b838110156144095781516001600160a01b0316875295820195908201906001016143e4565b509495945050505050565b600081518084526020808501945080840160005b8381101561440957815187529582019590820190600101614428565b805163ffffffff1682526000610100602083015161446d60208601826001600160a01b03169052565b506040830151816040860152614485828601826143d0565b9150506060830151848203606086015261449f8282614414565b915050608083015184820360808601526144b982826143d0565b91505060a083015184820360a08601526144d38282614414565b91505060c08301516144e960c086018215159052565b5060e083015160e08501528091505092915050565b6040815260006145116040830185614444565b90508260208301529392505050565b600082601f83011261453157600080fd5b8151602061454161430483614299565b82815260e0928302850182019282820191908785111561456057600080fd5b8387015b858110156145cf5781818a03121561457c5760008081fd5b614584613ffe565b81518152858201518682015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c080830151908201528452928401928101614564565b5090979650505050505050565b600080600080608085870312156145f257600080fd5b84516001600160401b0381111561460857600080fd5b61461487828801614520565b6020870151604088015160609098015191999098509095509350505050565b828152604060208201526000613cb16040830184614444565b805161465781613e32565b919050565b60006020828403121561466e57600080fd5b8151613b4681613e32565b805161465781613eab565b60006020828403121561469657600080fd5b8151613b4681613eab565b818103818111156146b4576146b4614365565b92915050565b63ffffffff83168152604060208201526000613cb16040830184614444565b600080604083850312156146ec57600080fd5b82356146f781613eab565b946020939093013593505050565b808201828112600083128015821682158216171561472557614725614365565b505092915050565b60008060006060848603121561474257600080fd5b8335925060208401359150604084013561475b81613eab565b809150509250925092565b80820281158282048414176146b4576146b4614365565b60008261479a57634e487b7160e01b600052601260045260246000fd5b500490565b602081526000613b466020830184614115565b81810360008312801583831316838312821617156147d2576147d2614365565b5092915050565b600080604083850312156147ec57600080fd5b505080516020909101519092909150565b600080600080600060a0868803121561481557600080fd5b85516001600160401b0381111561482b57600080fd5b61483788828901614520565b6020880151604089015160608a01516080909a0151929b919a509897509095509350505050565b6001600160801b038181168382160190808211156147d2576147d2614365565b808201808211156146b4576146b4614365565b602081526000613b4660208301846143d0565b8051600881900b811461465757600080fd5b805160ff8116811461465757600080fd5b600060e082840312156148d957600080fd5b6148e1613ffe565b825168ffffffffffffffffff811681146148fa57600080fd5b81526149086020840161464c565b6020820152614919604084016148a4565b604082015261492a606084016148b6565b606082015261493b608084016148b6565b608082015261494c60a0840161464c565b60a082015261495d60c08401614679565b60c08201529392505050565b6000604080835261497c818401866143d0565b83810360208581019190915285518083528682019282019060005b81811015614a25578451805168ffffffffffffffffff168452848101516001600160a01b0316858501528681015160080b8785015260608082015160ff908116918601919091526080808301519091169085015260a080820151614a05828701826001600160a01b03169052565b505060c0908101511515908401529383019360e090920191600101614997565b509098975050505050505050565b60008251614a458184602087016140f1565b919091019291505056fea2646970667358221220c87174f0c894151860a1e227ff037e959d1c5d845988d8e5d63c758ec670d13264736f6c63430008130033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000e8e40fd4ddab26b44b1fb2d6d73833cb0a33b736000000000000000000000000c6f50903a058f3807111619bd4b24ca64b8239e10000000000000000000000000000000000000000000000000000000000000064

-----Decoded View---------------
Arg [0] : _oracleModule (address): 0xe8e40Fd4DdAb26B44b1fb2D6d73833Cb0A33B736
Arg [1] : _govModule (address): 0xc6F50903a058f3807111619bD4B24cA64b8239E1
Arg [2] : _deviationThreshold (uint8): 100

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000e8e40fd4ddab26b44b1fb2d6d73833cb0a33b736
Arg [1] : 000000000000000000000000c6f50903a058f3807111619bd4b24ca64b8239e1
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000064


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.