ETH Price: $2,617.81 (+0.98%)

Contract

0x2a49Eae5CCa3f050eBEC729Cf90CC910fADAf7A2
 
Transaction Hash
Method
Block
From
To
0x60806040134611952021-10-21 13:08:511091 days ago1634821731IN
 Create: MultiplyProxyActions
0 ETH0.3533294287.73952292

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
209585722024-10-13 18:54:232 days ago1728845663
0x2a49Eae5...0fADAf7A2
108.30211777 ETH
209585722024-10-13 18:54:232 days ago1728845663
0x2a49Eae5...0fADAf7A2
108.30211777 ETH
209478452024-10-12 6:49:474 days ago1728715787
0x2a49Eae5...0fADAf7A2
6.32764363 ETH
209478452024-10-12 6:49:474 days ago1728715787
0x2a49Eae5...0fADAf7A2
6.32764363 ETH
209426602024-10-11 13:24:595 days ago1728653099
0x2a49Eae5...0fADAf7A2
18.33306396 ETH
209426602024-10-11 13:24:595 days ago1728653099
0x2a49Eae5...0fADAf7A2
18.33306396 ETH
208745442024-10-02 1:31:5914 days ago1727832719
0x2a49Eae5...0fADAf7A2
62.31428307 ETH
208745442024-10-02 1:31:5914 days ago1727832719
0x2a49Eae5...0fADAf7A2
62.31428307 ETH
207884192024-09-20 1:07:3526 days ago1726794455
0x2a49Eae5...0fADAf7A2
2.45224028 ETH
207884192024-09-20 1:07:3526 days ago1726794455
0x2a49Eae5...0fADAf7A2
2.45224028 ETH
207770842024-09-18 11:08:3528 days ago1726657715
0x2a49Eae5...0fADAf7A2
17.7730292 ETH
207770842024-09-18 11:08:3528 days ago1726657715
0x2a49Eae5...0fADAf7A2
17.7730292 ETH
207483612024-09-14 10:50:3532 days ago1726311035
0x2a49Eae5...0fADAf7A2
36.82717034 ETH
207483612024-09-14 10:50:3532 days ago1726311035
0x2a49Eae5...0fADAf7A2
36.82717034 ETH
207383992024-09-13 1:26:5933 days ago1726190819
0x2a49Eae5...0fADAf7A2
29.78381734 ETH
207383992024-09-13 1:26:5933 days ago1726190819
0x2a49Eae5...0fADAf7A2
29.78381734 ETH
207383412024-09-13 1:15:2333 days ago1726190123
0x2a49Eae5...0fADAf7A2
38.75924757 ETH
207383412024-09-13 1:15:2333 days ago1726190123
0x2a49Eae5...0fADAf7A2
38.75924757 ETH
206835772024-09-05 9:46:2341 days ago1725529583
0x2a49Eae5...0fADAf7A2
3.93348767 ETH
206835772024-09-05 9:46:2341 days ago1725529583
0x2a49Eae5...0fADAf7A2
3.93348767 ETH
206731312024-09-03 22:46:1142 days ago1725403571
0x2a49Eae5...0fADAf7A2
2.56499306 ETH
206731312024-09-03 22:46:1142 days ago1725403571
0x2a49Eae5...0fADAf7A2
2.56499306 ETH
206568542024-09-01 16:15:5945 days ago1725207359
0x2a49Eae5...0fADAf7A2
15.25012858 ETH
206568542024-09-01 16:15:5945 days ago1725207359
0x2a49Eae5...0fADAf7A2
15.25012858 ETH
206227322024-08-27 21:52:3549 days ago1724795555
0x2a49Eae5...0fADAf7A2
0.19055181 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MultiplyProxyActions

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 14 : MultiplyProxyActions.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

/// MultiplyProxyActions.sol

// Copyright (C) 2021-2021 Oazo Apps Limited

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

import {IERC20} from "../interfaces/IERC20.sol";
import "../utils/SafeMath.sol";
import "../interfaces/IWETH.sol";
import "../interfaces/mcd/IJoin.sol";
import "../interfaces/mcd/IManager.sol";
import "../interfaces/mcd/IVat.sol";
import "../interfaces/mcd/IJug.sol";
import "../interfaces/mcd/IDaiJoin.sol";
import "../interfaces/exchange/IExchange.sol";
import "./ExchangeData.sol";

import "./../flashMint/interface/IERC3156FlashBorrower.sol";
import "./../flashMint/interface/IERC3156FlashLender.sol";

pragma solidity >=0.7.6;
pragma abicoder v2;

struct CdpData {
  address gemJoin;
  address payable fundsReceiver;
  uint256 cdpId;
  bytes32 ilk;
  uint256 requiredDebt;
  uint256 borrowCollateral;
  uint256 withdrawCollateral;
  uint256 withdrawDai;
  uint256 depositDai;
  uint256 depositCollateral;
  bool skipFL;
  string methodName;
}

struct AddressRegistry {
  address jug;
  address manager;
  address multiplyProxyActions;
  address lender;
  address exchange;
}

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// WARNING: These functions meant to be used as a a library for a DSProxy. Some are unsafe if you call them directly.
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

contract MultiplyProxyActions is IERC3156FlashBorrower {
  using SafeMath for uint256;

  uint256 constant RAY = 10**27;

  address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
  address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
  address public constant DAIJOIN = 0x9759A6Ac90977b93B58547b4A71c78317f391A28;

  modifier logMethodName(
    string memory name,
    CdpData memory data,
    address destination
  ) {
    if (bytes(data.methodName).length == 0) {
      data.methodName = name;
    }
    _;
    data.methodName = "";
  }

  function takeAFlashLoan(
    AddressRegistry memory addressRegistry,
    CdpData memory cdpData,
    bytes memory paramsData
  ) internal {
    IManager(addressRegistry.manager).cdpAllow(
      cdpData.cdpId,
      addressRegistry.multiplyProxyActions,
      1
    );

    IERC3156FlashLender(addressRegistry.lender).flashLoan(
      IERC3156FlashBorrower(addressRegistry.multiplyProxyActions),
      DAI,
      cdpData.requiredDebt,
      paramsData
    );

    IManager(addressRegistry.manager).cdpAllow(
      cdpData.cdpId,
      addressRegistry.multiplyProxyActions,
      0
    );
  }

  function toInt256(uint256 x) internal pure returns (int256 y) {
    y = int256(x);
    require(y >= 0, "int256-overflow");
  }

  function convertTo18(address gemJoin, uint256 amt) internal returns (uint256 wad) {
    // For those collaterals that have less than 18 decimals precision we need to do the conversion before passing to frob function
    // Adapters will automatically handle the difference of precision
    wad = amt.mul(10**(18 - IJoin(gemJoin).dec()));
  }

  function _getDrawDart(
    address vat,
    address jug,
    address urn,
    bytes32 ilk,
    uint256 wad
  ) internal returns (int256 dart) {
    // Updates stability fee rate
    uint256 rate = IJug(jug).drip(ilk);

    // Gets DAI balance of the urn in the vat
    uint256 dai = IVat(vat).dai(urn);

    // If there was already enough DAI in the vat balance, just exits it without adding more debt
    if (dai < wad.mul(RAY)) {
      // Calculates the needed dart so together with the existing dai in the vat is enough to exit wad amount of DAI tokens
      dart = toInt256(wad.mul(RAY).sub(dai) / rate);
      // This is neeeded due lack of precision. It might need to sum an extra dart wei (for the given DAI wad amount)
      dart = uint256(dart).mul(rate) < wad.mul(RAY) ? dart + 1 : dart;
    }
  }

  function openMultiplyVault(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  )
    public
    payable
    logMethodName("openMultiplyVault", cdpData, addressRegistry.multiplyProxyActions)
  {
    cdpData.ilk = IJoin(cdpData.gemJoin).ilk();
    cdpData.cdpId = IManager(addressRegistry.manager).open(cdpData.ilk, address(this));
    increaseMultipleDepositCollateral(exchangeData, cdpData, addressRegistry);
  }

  function increaseMultipleDepositCollateral(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  )
    public
    payable
    logMethodName(
      "increaseMultipleDepositCollateral",
      cdpData,
      addressRegistry.multiplyProxyActions
    )
  {
    IGem gem = IJoin(cdpData.gemJoin).gem();

    if (address(gem) == WETH) {
      gem.deposit{value: msg.value}();
      if (cdpData.skipFL == false) {
        gem.transfer(addressRegistry.multiplyProxyActions, msg.value);
      }
    } else {
      if (cdpData.skipFL == false) {
        gem.transferFrom(
          msg.sender,
          addressRegistry.multiplyProxyActions,
          cdpData.depositCollateral
        );
      } else {
        gem.transferFrom(msg.sender, address(this), cdpData.depositCollateral);
      }
    }
    increaseMultipleInternal(exchangeData, cdpData, addressRegistry);
  }

  function toRad(uint256 wad) internal pure returns (uint256 rad) {
    rad = wad.mul(10**27);
  }

  function drawDaiDebt(
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry,
    uint256 amount
  ) internal {
    address urn = IManager(addressRegistry.manager).urns(cdpData.cdpId);
    address vat = IManager(addressRegistry.manager).vat();
    IManager(addressRegistry.manager).frob(
      cdpData.cdpId,
      0,
      _getDrawDart(vat, addressRegistry.jug, urn, cdpData.ilk, amount)
    );
    IManager(addressRegistry.manager).move(cdpData.cdpId, address(this), toRad(amount));
    if (IVat(vat).can(address(this), address(DAIJOIN)) == 0) {
      IVat(vat).hope(DAIJOIN);
    }

    IJoin(DAIJOIN).exit(address(this), amount);
  }

  function increaseMultipleDepositDai(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  )
    public
    logMethodName("increaseMultipleDepositDai", cdpData, addressRegistry.multiplyProxyActions)
  {
    if (cdpData.skipFL) {
      IERC20(DAI).transferFrom(msg.sender, address(this), cdpData.depositDai);
    } else {
      IERC20(DAI).transferFrom(
        msg.sender,
        addressRegistry.multiplyProxyActions,
        cdpData.depositDai
      );
    }
    increaseMultipleInternal(exchangeData, cdpData, addressRegistry);
  }

  function increaseMultiple(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  ) public logMethodName("increaseMultiple", cdpData, addressRegistry.multiplyProxyActions) {
    increaseMultipleInternal(exchangeData, cdpData, addressRegistry);
  }

  function increaseMultipleInternal(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  ) internal {
    cdpData.ilk = IJoin(cdpData.gemJoin).ilk();

    bytes memory paramsData = abi.encode(1, exchangeData, cdpData, addressRegistry);

    if (cdpData.skipFL) {
      //we want to draw our own DAI and use them in the exchange to buy collateral
      IGem gem = IJoin(cdpData.gemJoin).gem();
      uint256 collBalance = IERC20(address(gem)).balanceOf(address(this));
      if (collBalance > 0) {
        //if someone provided some collateral during increase
        //add it to vault and draw DAI
        joinDrawDebt(cdpData, cdpData.requiredDebt, addressRegistry.manager, addressRegistry.jug);
      } else {
        //just draw DAI
        drawDaiDebt(cdpData, addressRegistry, cdpData.requiredDebt);
      }
      _increaseMP(exchangeData, cdpData, addressRegistry, 0);
    } else {
      takeAFlashLoan(addressRegistry, cdpData, paramsData);
    }
  }

  function decreaseMultiple(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  ) public logMethodName("decreaseMultiple", cdpData, addressRegistry.multiplyProxyActions) {
    decreaseMultipleInternal(exchangeData, cdpData, addressRegistry);
  }

  function decreaseMultipleInternal(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  ) internal {
    cdpData.ilk = IJoin(cdpData.gemJoin).ilk();

    bytes memory paramsData = abi.encode(0, exchangeData, cdpData, addressRegistry);

    if (cdpData.skipFL) {
      _decreaseMP(exchangeData, cdpData, addressRegistry, 0);
    } else {
      takeAFlashLoan(addressRegistry, cdpData, paramsData);
    }
  }

  function decreaseMultipleWithdrawCollateral(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  )
    public
    logMethodName(
      "decreaseMultipleWithdrawCollateral",
      cdpData,
      addressRegistry.multiplyProxyActions
    )
  {
    decreaseMultipleInternal(exchangeData, cdpData, addressRegistry);
  }

  function decreaseMultipleWithdrawDai(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  )
    public
    logMethodName("decreaseMultipleWithdrawDai", cdpData, addressRegistry.multiplyProxyActions)
  {
    decreaseMultipleInternal(exchangeData, cdpData, addressRegistry);
  }

  function closeVaultExitGeneric(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry,
    uint8 mode
  ) private {
    cdpData.ilk = IJoin(cdpData.gemJoin).ilk();

    address urn = IManager(addressRegistry.manager).urns(cdpData.cdpId);
    address vat = IManager(addressRegistry.manager).vat();

    uint256 wadD = _getWipeAllWad(vat, urn, urn, cdpData.ilk);
    cdpData.requiredDebt = wadD;

    bytes memory paramsData = abi.encode(mode, exchangeData, cdpData, addressRegistry);

    if (cdpData.skipFL == false) {
      takeAFlashLoan(addressRegistry, cdpData, paramsData);
    } else {
      if (mode == 2) {
        _closeWithdrawCollateralSkipFL(
          exchangeData,
          cdpData,
          addressRegistry,
          cdpData.borrowCollateral
        );
      } else {
        require(false, "this code should be unreachable");
      }
    }
  }

  function closeVaultExitCollateral(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  )
    public
    logMethodName("closeVaultExitCollateral", cdpData, addressRegistry.multiplyProxyActions)
  {
    closeVaultExitGeneric(exchangeData, cdpData, addressRegistry, 2);
  }

  function closeVaultExitDai(
    ExchangeData calldata exchangeData,
    CdpData memory cdpData,
    AddressRegistry calldata addressRegistry
  ) public logMethodName("closeVaultExitDai", cdpData, addressRegistry.multiplyProxyActions) {
    require(cdpData.skipFL == false, "cannot close to DAI if FL not used");
    closeVaultExitGeneric(exchangeData, cdpData, addressRegistry, 3);
  }

  function joinDrawDebt(
    CdpData memory cdpData,
    uint256 borrowedDai,
    address manager,
    address jug
  ) private {
    IGem gem = IJoin(cdpData.gemJoin).gem();

    uint256 balance = IERC20(address(gem)).balanceOf(address(this));
    gem.approve(address(cdpData.gemJoin), balance);

    address urn = IManager(manager).urns(cdpData.cdpId);
    address vat = IManager(manager).vat();

    IJoin(cdpData.gemJoin).join(urn, balance);

    IManager(manager).frob(
      cdpData.cdpId,
      toInt256(convertTo18(cdpData.gemJoin, balance)),
      _getDrawDart(vat, jug, urn, cdpData.ilk, borrowedDai)
    );
    IManager(manager).move(cdpData.cdpId, address(this), borrowedDai.mul(RAY));

    IVat(vat).hope(DAIJOIN);

    IJoin(DAIJOIN).exit(address(this), borrowedDai);
  }

  function getInk(address manager, CdpData memory cdpData) internal view returns (uint256) {
    address urn = IManager(manager).urns(cdpData.cdpId);
    address vat = IManager(manager).vat();

    (uint256 ink, ) = IVat(vat).urns(cdpData.ilk, urn);
    return ink;
  }

  function _getWipeDart(
    address vat,
    uint256 dai,
    address urn,
    bytes32 ilk
  ) internal view returns (int256 dart) {
    // Gets actual rate from the vat
    (, uint256 rate, , , ) = IVat(vat).ilks(ilk);
    // Gets actual art value of the urn
    (, uint256 art) = IVat(vat).urns(ilk, urn);

    // Uses the whole dai balance in the vat to reduce the debt
    dart = toInt256(dai / rate);
    // Checks the calculated dart is not higher than urn.art (total debt), otherwise uses its value
    dart = uint256(dart) <= art ? -dart : -toInt256(art);
  }

  function _getWipeAllWad(
    address vat,
    address usr,
    address urn,
    bytes32 ilk
  ) internal view returns (uint256 wad) {
    // Gets actual rate from the vat
    (, uint256 rate, , , ) = IVat(vat).ilks(ilk);
    // Gets actual art value of the urn
    (, uint256 art) = IVat(vat).urns(ilk, urn);
    // Gets actual dai amount in the urn
    uint256 dai = IVat(vat).dai(usr);

    uint256 rad = art.mul(rate).sub(dai);
    wad = rad / RAY;

    // If the rad precision has some dust, it will need to request for 1 extra wad wei
    wad = wad.mul(RAY) < rad ? wad + 1 : wad;
  }

  function wipeAndFreeGem(
    address manager,
    address gemJoin,
    uint256 cdp,
    uint256 borrowedDai,
    uint256 collateralDraw
  ) internal {
    address vat = IManager(manager).vat();
    address urn = IManager(manager).urns(cdp);
    bytes32 ilk = IManager(manager).ilks(cdp);

    IERC20(DAI).approve(DAIJOIN, borrowedDai);
    IDaiJoin(DAIJOIN).join(urn, borrowedDai);

    uint256 wadC = convertTo18(gemJoin, collateralDraw);

    IManager(manager).frob(cdp, -toInt256(wadC), _getWipeDart(vat, IVat(vat).dai(urn), urn, ilk));

    IManager(manager).flux(cdp, address(this), wadC);
    IJoin(gemJoin).exit(address(this), collateralDraw);
  }

  function _withdrawGem(
    address gemJoin,
    address payable destination,
    uint256 amount
  ) private {
    IGem gem = IJoin(gemJoin).gem();

    if (address(gem) == WETH) {
      gem.withdraw(amount);
      destination.transfer(amount);
    } else {
      IERC20(address(gem)).transfer(destination, amount);
    }
  }

  function _increaseMP(
    ExchangeData memory exchangeData,
    CdpData memory cdpData,
    AddressRegistry memory addressRegistry,
    uint256 premium
  ) private {
    IExchange exchange = IExchange(addressRegistry.exchange);
    uint256 borrowedDai = cdpData.requiredDebt.add(premium);
    if (cdpData.skipFL) {
      borrowedDai = 0; //this DAI are not borrowed and shal not stay after this method execution
    }
    require(
      IERC20(DAI).approve(address(exchange), exchangeData.fromTokenAmount.add(cdpData.depositDai)),
      "MPA / Could not approve Exchange for DAI"
    );
    exchange.swapDaiForToken(
      exchangeData.toTokenAddress,
      exchangeData.fromTokenAmount.add(cdpData.depositDai),
      exchangeData.minToTokenAmount,
      exchangeData.exchangeAddress,
      exchangeData._exchangeCalldata
    );
    //here we add collateral we got from exchange, if skipFL then borrowedDai = 0
    joinDrawDebt(cdpData, borrowedDai, addressRegistry.manager, addressRegistry.jug);
    //if some DAI are left after exchange return them to the user
    uint256 daiLeft = IERC20(DAI).balanceOf(address(this)).sub(borrowedDai);
    emit MultipleActionCalled(
      cdpData.methodName,
      cdpData.cdpId,
      exchangeData.minToTokenAmount,
      exchangeData.toTokenAmount,
      0,
      daiLeft
    );

    if (daiLeft > 0) {
      IERC20(DAI).transfer(cdpData.fundsReceiver, daiLeft);
    }
  }

  function _decreaseMP(
    ExchangeData memory exchangeData,
    CdpData memory cdpData,
    AddressRegistry memory addressRegistry,
    uint256 premium
  ) private {
    IExchange exchange = IExchange(addressRegistry.exchange);

    uint256 debtToBeWiped = cdpData.skipFL ? 0 : cdpData.requiredDebt.sub(cdpData.withdrawDai);

    wipeAndFreeGem(
      addressRegistry.manager,
      cdpData.gemJoin,
      cdpData.cdpId,
      debtToBeWiped,
      cdpData.borrowCollateral.add(cdpData.withdrawCollateral)
    );

    require(
      IERC20(exchangeData.fromTokenAddress).approve(
        address(exchange),
        exchangeData.fromTokenAmount
      ),
      "MPA / Could not approve Exchange for Token"
    );

    exchange.swapTokenForDai(
      exchangeData.fromTokenAddress,
      exchangeData.fromTokenAmount,
      cdpData.requiredDebt.add(premium),
      exchangeData.exchangeAddress,
      exchangeData._exchangeCalldata
    );

    uint256 collateralLeft = IERC20(exchangeData.fromTokenAddress).balanceOf(address(this));

    uint256 daiLeft = 0;
    if (cdpData.skipFL) {
      wipeAndFreeGem(
        addressRegistry.manager,
        cdpData.gemJoin,
        cdpData.cdpId,
        IERC20(DAI).balanceOf(address(this)).sub(cdpData.withdrawDai),
        0
      );
      daiLeft = cdpData.withdrawDai;
    } else {
      daiLeft = IERC20(DAI).balanceOf(address(this)).sub(cdpData.requiredDebt.add(premium));
    }
    emit MultipleActionCalled(
      cdpData.methodName,
      cdpData.cdpId,
      exchangeData.minToTokenAmount,
      exchangeData.toTokenAmount,
      collateralLeft,
      daiLeft
    );

    if (daiLeft > 0) {
      IERC20(DAI).transfer(cdpData.fundsReceiver, daiLeft);
    }
    if (collateralLeft > 0) {
      _withdrawGem(cdpData.gemJoin, cdpData.fundsReceiver, collateralLeft);
    }
  }

  function _closeWithdrawCollateralSkipFL(
    ExchangeData memory exchangeData,
    CdpData memory cdpData,
    AddressRegistry memory addressRegistry,
    uint256 ink
  ) private {
    IExchange exchange = IExchange(addressRegistry.exchange);
    address gemAddress = address(IJoin(cdpData.gemJoin).gem());

    wipeAndFreeGem(
      addressRegistry.manager,
      cdpData.gemJoin,
      cdpData.cdpId,
      0,
      exchangeData.fromTokenAmount
    );
    require(
      IERC20(exchangeData.fromTokenAddress).approve(address(exchange), ink),
      "MPA / Could not approve Exchange for Token"
    );
    exchange.swapTokenForDai(
      exchangeData.fromTokenAddress,
      exchangeData.fromTokenAmount,
      exchangeData.minToTokenAmount,
      exchangeData.exchangeAddress,
      exchangeData._exchangeCalldata
    );

    uint256 daiLeft = IERC20(DAI).balanceOf(address(this));

    require(cdpData.requiredDebt <= daiLeft, "cannot repay all debt");
    
    wipeAndFreeGem(
      addressRegistry.manager,
      cdpData.gemJoin,
      cdpData.cdpId,
      cdpData.requiredDebt,
      cdpData.withdrawCollateral
    );
    daiLeft = IERC20(DAI).balanceOf(address(this));

    uint256 collateralLeft = IERC20(gemAddress).balanceOf(address(this));

    if (daiLeft > 0) {
      IERC20(DAI).transfer(cdpData.fundsReceiver, daiLeft);
    }
    if (collateralLeft > 0) {
      _withdrawGem(cdpData.gemJoin, cdpData.fundsReceiver, collateralLeft);
    }
    emit MultipleActionCalled(
      cdpData.methodName,
      cdpData.cdpId,
      exchangeData.minToTokenAmount,
      exchangeData.toTokenAmount,
      collateralLeft,
      daiLeft
    );
  }

  function _closeWithdrawCollateral(
    ExchangeData memory exchangeData,
    CdpData memory cdpData,
    AddressRegistry memory addressRegistry,
    uint256 borrowedDaiAmount,
    uint256 ink
  ) private {
    IExchange exchange = IExchange(addressRegistry.exchange);
    address gemAddress = address(IJoin(cdpData.gemJoin).gem());

    wipeAndFreeGem(
      addressRegistry.manager,
      cdpData.gemJoin,
      cdpData.cdpId,
      cdpData.requiredDebt,
      ink
    );

    require(
      IERC20(exchangeData.fromTokenAddress).approve(address(exchange), ink),
      "MPA / Could not approve Exchange for Token"
    );
    exchange.swapTokenForDai(
      exchangeData.fromTokenAddress,
      exchangeData.fromTokenAmount,
      exchangeData.minToTokenAmount,
      exchangeData.exchangeAddress,
      exchangeData._exchangeCalldata
    );

    uint256 daiLeft = IERC20(DAI).balanceOf(address(this)).sub(borrowedDaiAmount);
    uint256 collateralLeft = IERC20(gemAddress).balanceOf(address(this));

    if (daiLeft > 0) {
      IERC20(DAI).transfer(cdpData.fundsReceiver, daiLeft);
    }
    if (collateralLeft > 0) {
      _withdrawGem(cdpData.gemJoin, cdpData.fundsReceiver, collateralLeft);
    }
    emit MultipleActionCalled(
      cdpData.methodName,
      cdpData.cdpId,
      exchangeData.minToTokenAmount,
      exchangeData.toTokenAmount,
      collateralLeft,
      daiLeft
    );
  }

  function _closeWithdrawDai(
    ExchangeData memory exchangeData,
    CdpData memory cdpData,
    AddressRegistry memory addressRegistry,
    uint256 borrowedDaiAmount,
    uint256 ink
  ) private {
    IExchange exchange = IExchange(addressRegistry.exchange);
    address gemAddress = address(IJoin(cdpData.gemJoin).gem());

    wipeAndFreeGem(
      addressRegistry.manager,
      cdpData.gemJoin,
      cdpData.cdpId,
      cdpData.requiredDebt,
      ink
    );

    require(
      IERC20(exchangeData.fromTokenAddress).approve(
        address(exchange),
        IERC20(gemAddress).balanceOf(address(this))
      ),
      "MPA / Could not approve Exchange for Token"
    );
    exchange.swapTokenForDai(
      exchangeData.fromTokenAddress,
      ink,
      exchangeData.minToTokenAmount,
      exchangeData.exchangeAddress,
      exchangeData._exchangeCalldata
    );

    uint256 daiLeft = IERC20(DAI).balanceOf(address(this)).sub(borrowedDaiAmount);

    if (daiLeft > 0) {
      IERC20(DAI).transfer(cdpData.fundsReceiver, daiLeft);
    }
    uint256 collateralLeft = IERC20(gemAddress).balanceOf(address(this));
    /*
    if (collateralLeft > 0) {
      _withdrawGem(cdpData.gemJoin, cdpData.fundsReceiver, collateralLeft);
    }*/
    emit MultipleActionCalled(
      cdpData.methodName,
      cdpData.cdpId,
      exchangeData.minToTokenAmount,
      exchangeData.toTokenAmount,
      collateralLeft,
      daiLeft
    );
  }

  function onFlashLoan(
    address initiator,
    address token,
    uint256 amount,
    uint256 fee,
    bytes calldata params
  ) public override returns (bytes32) {
    (
      uint8 mode,
      ExchangeData memory exchangeData,
      CdpData memory cdpData,
      AddressRegistry memory addressRegistry
    ) = abi.decode(params, (uint8, ExchangeData, CdpData, AddressRegistry));

    require(msg.sender == address(addressRegistry.lender), "mpa-untrusted-lender");

    uint256 borrowedDaiAmount = amount.add(fee);
    emit FLData(IERC20(DAI).balanceOf(address(this)).sub(cdpData.depositDai), borrowedDaiAmount);

    require(
      cdpData.requiredDebt.add(cdpData.depositDai) <= IERC20(DAI).balanceOf(address(this)),
      "mpa-receive-requested-amount-mismatch"
    );

    if (mode == 0) {
      _decreaseMP(exchangeData, cdpData, addressRegistry, fee);
    }
    if (mode == 1) {
      _increaseMP(exchangeData, cdpData, addressRegistry, fee);
    }
    if (mode == 2) {
      _closeWithdrawCollateral(
        exchangeData,
        cdpData,
        addressRegistry,
        borrowedDaiAmount,
        cdpData.borrowCollateral
      );
    }
    if (mode == 3) {
      _closeWithdrawDai(
        exchangeData,
        cdpData,
        addressRegistry,
        borrowedDaiAmount,
        cdpData.borrowCollateral
      );
    }

    IERC20(token).approve(addressRegistry.lender, borrowedDaiAmount);

    return keccak256("ERC3156FlashBorrower.onFlashLoan");
  }

  event FLData(uint256 borrowed, uint256 due);
  event MultipleActionCalled(
    string methodName,
    uint256 indexed cdpId,
    uint256 swapMinAmount,
    uint256 swapOptimistAmount,
    uint256 collateralLeft,
    uint256 daiLeft
  );

  fallback() external payable {}
}

File 2 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

interface IERC20 {
  function totalSupply() external view returns (uint256 supply);

  function balanceOf(address _owner) external view returns (uint256 balance);

  function transfer(address _to, uint256 _value) external returns (bool success);

  function transferFrom(
    address _from,
    address _to,
    uint256 _value
  ) external returns (bool success);

  function approve(address _spender, uint256 _value) external returns (bool success);

  function allowance(address _owner, address _spender) external view returns (uint256 remaining);

  function decimals() external view returns (uint256 digits);

  event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

File 3 of 14 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.7.6;

library SafeMath {
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a, 'SafeMath: addition overflow');

    return c;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    return sub(a, b, 'SafeMath: subtraction overflow');
  }

  function sub(
    uint256 a,
    uint256 b,
    string memory errorMessage
  ) internal pure returns (uint256) {
    require(b <= a, errorMessage);
    uint256 c = a - b;

    return c;
  }

  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b, 'SafeMath: multiplication overflow');

    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    return div(a, b, 'SafeMath: division by zero');
  }

  function div(
    uint256 a,
    uint256 b,
    string memory errorMessage
  ) internal pure returns (uint256) {
    require(b > 0, errorMessage);
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    return mod(a, b, 'SafeMath: modulo by zero');
  }

  function mod(
    uint256 a,
    uint256 b,
    string memory errorMessage
  ) internal pure returns (uint256) {
    require(b != 0, errorMessage);
    return a % b;
  }
}

File 4 of 14 : IWETH.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import './IERC20.sol';

abstract contract IWETH {
  function allowance(address, address) public virtual returns (uint256);

  function balanceOf(address) public virtual returns (uint256);

  function approve(address, uint256) public virtual;

  function transfer(address, uint256) public virtual returns (bool);

  function transferFrom(
    address,
    address,
    uint256
  ) public virtual returns (bool);

  function deposit() public payable virtual;

  function withdraw(uint256) public virtual;
}

File 5 of 14 : IJoin.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import './IGem.sol';

abstract contract IJoin {
  bytes32 public ilk;

  function dec() public view virtual returns (uint256);

  function gem() public view virtual returns (IGem);

  function join(address, uint256) public payable virtual;

  function exit(address, uint256) public virtual;
}

File 6 of 14 : IManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

abstract contract IManager {
  function last(address) public virtual returns (uint256);

  function cdpCan(
    address,
    uint256,
    address
  ) public view virtual returns (uint256);

  function ilks(uint256) public view virtual returns (bytes32);

  function owns(uint256) public view virtual returns (address);

  function urns(uint256) public view virtual returns (address);

  function vat() public view virtual returns (address);

  function open(bytes32, address) public virtual returns (uint256);

  function give(uint256, address) public virtual;

  function cdpAllow(
    uint256,
    address,
    uint256
  ) public virtual;

  function urnAllow(address, uint256) public virtual;

  function frob(
    uint256,
    int256,
    int256
  ) public virtual;

  function flux(
    uint256,
    address,
    uint256
  ) public virtual;

  function move(
    uint256,
    address,
    uint256
  ) public virtual;

  function exit(
    address,
    uint256,
    address,
    uint256
  ) public virtual;

  function quit(uint256, address) public virtual;

  function enter(address, uint256) public virtual;

  function shift(uint256, uint256) public virtual;
}

File 7 of 14 : IVat.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

abstract contract IVat {
  struct Urn {
    uint256 ink; // Locked Collateral  [wad]
    uint256 art; // Normalised Debt    [wad]
  }

  struct Ilk {
    uint256 Art; // Total Normalised Debt     [wad]
    uint256 rate; // Accumulated Rates         [ray]
    uint256 spot; // Price with Safety Margin  [ray]
    uint256 line; // Debt Ceiling              [rad]
    uint256 dust; // Urn Debt Floor            [rad]
  }

  mapping(bytes32 => mapping(address => Urn)) public urns;
  mapping(bytes32 => Ilk) public ilks;
  mapping(bytes32 => mapping(address => uint256)) public gem; // [wad]

  function can(address, address) public view virtual returns (uint256);

  function dai(address) public view virtual returns (uint256);

  function frob(
    bytes32,
    address,
    address,
    address,
    int256,
    int256
  ) public virtual;

  function hope(address) public virtual;

  function move(
    address,
    address,
    uint256
  ) public virtual;

  function fork(
    bytes32,
    address,
    address,
    int256,
    int256
  ) public virtual;
}

File 8 of 14 : IJug.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

abstract contract IJug {
  struct Ilk {
    uint256 duty;
    uint256 rho;
  }

  mapping(bytes32 => Ilk) public ilks;

  function drip(bytes32) public virtual returns (uint256);
}

File 9 of 14 : IDaiJoin.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import './IVat.sol';
import './IGem.sol';

abstract contract IDaiJoin {
  function vat() public virtual returns (IVat);

  function dai() public virtual returns (IGem);

  function join(address, uint256) public payable virtual;

  function exit(address, uint256) public virtual;
}

File 10 of 14 : IExchange.sol
pragma solidity >=0.7.0;

abstract contract IExchange {
  function swapDaiForToken(
    address asset,
    uint256 amount,
    uint256 receiveAtLeast,
    address callee,
    bytes calldata withData
  ) external virtual;

  function swapTokenForDai(
    address asset,
    uint256 amount,
    uint256 receiveAtLeast,
    address callee,
    bytes calldata withData
  ) external virtual;
}

File 11 of 14 : ExchangeData.sol
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity >=0.7.6;

struct ExchangeData {
  address fromTokenAddress;
  address toTokenAddress;
  uint256 fromTokenAmount;
  uint256 toTokenAmount;
  uint256 minToTokenAmount;
  address exchangeAddress;
  bytes _exchangeCalldata;
}

File 12 of 14 : IERC3156FlashBorrower.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2021 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;

interface IERC3156FlashBorrower {

    /**
     * @dev Receive a flash loan.
     * @param initiator The initiator of the loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param fee The additional amount of tokens to repay.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
     */
    function onFlashLoan(
        address initiator,
        address token,
        uint256 amount,
        uint256 fee,
        bytes calldata data
    ) external returns (bytes32);
}

File 13 of 14 : IERC3156FlashLender.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2021 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;

import "./IERC3156FlashBorrower.sol";

interface IERC3156FlashLender {

    /**
     * @dev The amount of currency available to be lent.
     * @param token The loan currency.
     * @return The amount of `token` that can be borrowed.
     */
    function maxFlashLoan(
        address token
    ) external view returns (uint256);

    /**
     * @dev The fee to be charged for a given loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function flashFee(
        address token,
        uint256 amount
    ) external view returns (uint256);

    /**
     * @dev Initiate a flash loan.
     * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     */
    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external returns (bool);
}

File 14 of 14 : IGem.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

abstract contract IGem {
  function dec() public virtual returns (uint256);

  function gem() public virtual returns (IGem);

  function join(address, uint256) public payable virtual;

  function exit(address, uint256) public virtual;

  function approve(address, uint256) public virtual;

  function transfer(address, uint256) public virtual returns (bool);

  function transferFrom(
    address,
    address,
    uint256
  ) public virtual returns (bool);

  function deposit() public payable virtual;

  function withdraw(uint256) public virtual;

  function allowance(address, address) public virtual returns (uint256);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"borrowed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"due","type":"uint256"}],"name":"FLData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"methodName","type":"string"},{"indexed":true,"internalType":"uint256","name":"cdpId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapMinAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapOptimistAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralLeft","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"daiLeft","type":"uint256"}],"name":"MultipleActionCalled","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DAI","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAIJOIN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"closeVaultExitCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"closeVaultExitDai","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"decreaseMultiple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"decreaseMultipleWithdrawCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"decreaseMultipleWithdrawDai","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"increaseMultiple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"increaseMultipleDepositCollateral","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"increaseMultipleDepositDai","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"onFlashLoan","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"fromTokenAmount","type":"uint256"},{"internalType":"uint256","name":"toTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minToTokenAmount","type":"uint256"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"_exchangeCalldata","type":"bytes"}],"internalType":"struct ExchangeData","name":"exchangeData","type":"tuple"},{"components":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address payable","name":"fundsReceiver","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"requiredDebt","type":"uint256"},{"internalType":"uint256","name":"borrowCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawCollateral","type":"uint256"},{"internalType":"uint256","name":"withdrawDai","type":"uint256"},{"internalType":"uint256","name":"depositDai","type":"uint256"},{"internalType":"uint256","name":"depositCollateral","type":"uint256"},{"internalType":"bool","name":"skipFL","type":"bool"},{"internalType":"string","name":"methodName","type":"string"}],"internalType":"struct CdpData","name":"cdpData","type":"tuple"},{"components":[{"internalType":"address","name":"jug","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"multiplyProxyActions","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"exchange","type":"address"}],"internalType":"struct AddressRegistry","name":"addressRegistry","type":"tuple"}],"name":"openMultiplyVault","outputs":[],"stateMutability":"payable","type":"function"}]

608060405234801561001057600080fd5b506147e8806100206000396000f3fe6080604052600436106100c25760003560e01c80634a9b4e0c1161007f578063ad5c464811610059578063ad5c4648146101ed578063cedee4ef1461020f578063e0bab4c414610222578063f85c2ce314610237576100c2565b80634a9b4e0c1461019a57806371ae86a5146101ba57806399e13c1a146101da576100c2565b80630521a3c7146100c45780631c9ea1e0146100e45780631f41f7b61461010457806323e30c8b1461012457806334f674731461015a5780633b9b4d951461017a575b005b3480156100d057600080fd5b506100c26100df366004613f4c565b61024c565b3480156100f057600080fd5b506100c26100ff366004613f4c565b6102b2565b34801561011057600080fd5b506100c261011f366004613f4c565b6102eb565b34801561013057600080fd5b5061014461013f366004613e58565b610372565b60405161015191906143d4565b60405180910390f35b34801561016657600080fd5b506100c2610175366004613f4c565b61066f565b34801561018657600080fd5b506100c2610195366004613f4c565b6106b5565b3480156101a657600080fd5b506100c26101b5366004613f4c565b61071c565b3480156101c657600080fd5b506100c26101d5366004613f4c565b610774565b6100c26101e8366004613f4c565b610912565b3480156101f957600080fd5b50610202610a7d565b604051610151919061432f565b6100c261021d366004613f4c565b610a95565b34801561022e57600080fd5b50610202610d68565b34801561024357600080fd5b50610202610d7a565b60405180606001604052806022815260200161470f60229139826102766060840160408501613e20565b6101608201515161028a5761016082018390525b610295868686610d92565b506040805160208101909152600081526101609091015250505050565b604080518082018252601081526f64656372656173654d756c7469706c6560801b60208201529083906102769060608501908501613e20565b6040805180820182526011815270636c6f73655661756c744578697444616960781b60208201529083906103259060608501908501613e20565b610160820151516103395761016082018390525b610140850151156103655760405162461bcd60e51b815260040161035c90614516565b60405180910390fd5b6102958686866003610e89565b60008080808061038486880188614031565b935093509350935080606001516001600160a01b0316336001600160a01b0316146103c15760405162461bcd60e51b815260040161035c90614610565b60006103cd8a8a6110df565b90507f9c6641b21946115d10f3f55df9bec5752ec06d40dc9250b1cc6560549764600e6104898461010001516000805160206147518339815191526001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610433919061432f565b60206040518083038186803b15801561044b57600080fd5b505afa15801561045f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104839190613f19565b90611142565b826040516104989291906146aa565b60405180910390a16040516370a0823160e01b8152600080516020614751833981519152906370a08231906104d190309060040161432f565b60206040518083038186803b1580156104e957600080fd5b505afa1580156104fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105219190613f19565b6101008401516080850151610535916110df565b11156105535760405162461bcd60e51b815260040161035c906145cb565b60ff8516610567576105678484848c611184565b8460ff166001141561057f5761057f8484848c611534565b8460ff166002141561059c5761059c848484848760a001516117da565b8460ff16600314156105b9576105b9848484848760a00151611b40565b606082015160405163095ea7b360e01b81526001600160a01b038d169163095ea7b3916105eb91908590600401614381565b602060405180830381600087803b15801561060557600080fd5b505af1158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190613efd565b507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd99c9b505050505050505050505050565b604080518082018252601b81527f64656372656173654d756c7469706c655769746864726177446169000000000060208201529083906102769060608501908501613e20565b604080518082018252601881527f636c6f73655661756c7445786974436f6c6c61746572616c000000000000000060208201529083906106fb9060608501908501613e20565b6101608201515161070f5761016082018390525b6102958686866002610e89565b604080518082018252601081526f696e6372656173654d756c7469706c6560801b60208201529083906107559060608501908501613e20565b610160820151516107695761016082018390525b610295868686611ef3565b604080518082018252601a81527f696e6372656173654d756c7469706c654465706f73697444616900000000000060208201529083906107ba9060608501908501613e20565b610160820151516107ce5761016082018390525b8461014001511561086b576101008501516040516323b872dd60e01b8152600080516020614751833981519152916323b872dd9161081391339130919060040161435d565b602060405180830381600087803b15801561082d57600080fd5b505af1158015610841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108659190613efd565b50610769565b6000805160206147518339815191526323b872dd336108906060880160408901613e20565b8861010001516040518463ffffffff1660e01b81526004016108b49392919061435d565b602060405180830381600087803b1580156108ce57600080fd5b505af11580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190613efd565b50610295868686611ef3565b60408051808201825260118152701bdc195b935d5b1d1a5c1b1e55985d5b1d607a1b602082015290839061094c9060608501908501613e20565b610160820151516109605761016082018390525b84600001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561099d57600080fd5b505afa1580156109b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d59190613f19565b60608601526109ea6040850160208601613e20565b6001600160a01b0316636090dec58660600151306040518363ffffffff1660e01b8152600401610a1b9291906143dd565b602060405180830381600087803b158015610a3557600080fd5b505af1158015610a49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6d9190613f19565b6040860152610295868686610a95565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6040518060600160405280602181526020016147716021913982610abf6060840160408501613e20565b61016082015151610ad35761016082018390525b600085600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1257600080fd5b505afa158015610b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4a9190613e3c565b90506001600160a01b03811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415610c6857806001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610bac57600080fd5b505af1158015610bc0573d6000803e3d6000fd5b5050505061014087015115159050610c63576001600160a01b03811663a9059cbb610bf16060880160408901613e20565b346040518363ffffffff1660e01b8152600401610c0f929190614381565b602060405180830381600087803b158015610c2957600080fd5b505af1158015610c3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c619190613efd565b505b610d3f565b610140860151610cb6576001600160a01b0381166323b872dd33610c926060890160408a01613e20565b8961012001516040518463ffffffff1660e01b8152600401610c0f9392919061435d565b6101208601516040516323b872dd60e01b81526001600160a01b038316916323b872dd91610ceb91339130919060040161435d565b602060405180830381600087803b158015610d0557600080fd5b505af1158015610d19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3d9190613efd565b505b610d4a878787611ef3565b50506040805160208101909152600081526101609091015250505050565b60008051602061475183398151915281565b739759a6ac90977b93b58547b4a71c78317f391a2881565b81600001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dcf57600080fd5b505afa158015610de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e079190613f19565b6060830152604051600090610e26908290869086908690602001614427565b604051602081830303815290604052905082610140015115610e6a57610e65610e4e856146dc565b84610e5e36869003860186613f31565b6000611184565b610e83565b610e83610e7c36849003840184613f31565b848361210e565b50505050565b82600001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ec657600080fd5b505afa158015610eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610efe9190613f19565b60608401526000610f156040840160208501613e20565b6001600160a01b0316632726b07385604001516040518263ffffffff1660e01b8152600401610f4491906143d4565b60206040518083038186803b158015610f5c57600080fd5b505afa158015610f70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f949190613e3c565b90506000610fa86040850160208601613e20565b6001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b158015610fe057600080fd5b505afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613e3c565b9050600061102c8284858960600151612287565b608087018190526040519091506000906110509086908a908a908a90602001614427565b60408051601f1981840301815291905261014088015190915061108b5761108661107f36889003880188613f31565b888361210e565b6110d5565b8460ff16600214156110bd576110866110a3896146dc565b886110b3368a90038a018a613f31565b8a60a00151612463565b60405162461bcd60e51b815260040161035c9061463e565b5050505050505050565b600082820183811015611139576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600061113983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506128db565b60808201516101408401516000906111ae5760e085015160808601516111a991611142565b6111b1565b60005b90506111e6846020015186600001518760400151846111e18a60c001518b60a001516110df90919063ffffffff16565b612972565b8551604080880151905163095ea7b360e01b81526001600160a01b039092169163095ea7b39161121b91869190600401614381565b602060405180830381600087803b15801561123557600080fd5b505af1158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d9190613efd565b6112895760405162461bcd60e51b815260040161035c90614558565b816001600160a01b031663c723c87f876000015188604001516112b9878a608001516110df90919063ffffffff16565b8a60a001518b60c001516040518663ffffffff1660e01b81526004016112e395949392919061439a565b600060405180830381600087803b1580156112fd57600080fd5b505af1158015611311573d6000803e3d6000fd5b505087516040516370a0823160e01b8152600093506001600160a01b0390911691506370a082319061134790309060040161432f565b60206040518083038186803b15801561135f57600080fd5b505afa158015611373573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113979190613f19565b905060008661014001511561140457602086015187516040808a015160e08b015191516370a0823160e01b81526113f99493926113f291600080516020614751833981519152906370a082319061043390309060040161432f565b6000612972565b5060e086015161144b565b60808701516114489061141790876110df565b6040516370a0823160e01b8152600080516020614751833981519152906370a082319061043390309060040161432f565b90505b86604001516000805160206147318339815191528861016001518a608001518b606001518686604051611482959493929190614468565b60405180910390a2801561151b57602087015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb916114c791908590600401614381565b602060405180830381600087803b1580156114e157600080fd5b505af11580156114f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115199190613efd565b505b81156110d5576110d58760000151886020015184612dbb565b6080808301519084015160009061154b90846110df565b90508461014001511561155c575060005b6000805160206147518339815191526001600160a01b031663095ea7b3836115968861010001518a604001516110df90919063ffffffff16565b6040518363ffffffff1660e01b81526004016115b3929190614381565b602060405180830381600087803b1580156115cd57600080fd5b505af11580156115e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116059190613efd565b6116215760405162461bcd60e51b815260040161035c9061449f565b816001600160a01b031663bc6f02b287602001516116518861010001518a604001516110df90919063ffffffff16565b89608001518a60a001518b60c001516040518663ffffffff1660e01b815260040161168095949392919061439a565b600060405180830381600087803b15801561169a57600080fd5b505af11580156116ae573d6000803e3d6000fd5b505050506116c6858286602001518760000151612f76565b6040516370a0823160e01b8152600090611700908390600080516020614751833981519152906370a082319061043390309060040161432f565b9050856040015160008051602061473183398151915287610160015189608001518a6060015160008660405161173a959493929190614468565b60405180910390a280156117d157602086015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb9161177f91908590600401614381565b602060405180830381600087803b15801561179957600080fd5b505af11580156117ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d59190613efd565b50505050505050565b600083608001519050600085600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b15801561182257600080fd5b505afa158015611836573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185a9190613e3c565b9050611879856020015187600001518860400151896080015187612972565b865160405163095ea7b360e01b81526001600160a01b039091169063095ea7b3906118aa9085908790600401614381565b602060405180830381600087803b1580156118c457600080fd5b505af11580156118d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118fc9190613efd565b6119185760405162461bcd60e51b815260040161035c90614558565b865160408089015160808a015160a08b015160c08c0151935163c723c87f60e01b81526001600160a01b0388169563c723c87f9561195e9591949193919260040161439a565b600060405180830381600087803b15801561197857600080fd5b505af115801561198c573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506119ca91508690600080516020614751833981519152906370a082319061043390309060040161432f565b90506000826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016119fa919061432f565b60206040518083038186803b158015611a1257600080fd5b505afa158015611a26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4a9190613f19565b90508115611add57602088015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb91611a8991908690600401614381565b602060405180830381600087803b158015611aa357600080fd5b505af1158015611ab7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adb9190613efd565b505b8015611af657611af68860000151896020015183612dbb565b87604001516000805160206147318339815191528961016001518b608001518c606001518587604051611b2d959493929190614468565b60405180910390a2505050505050505050565b600083608001519050600085600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015611b8857600080fd5b505afa158015611b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc09190613e3c565b9050611bdf856020015187600001518860400151896080015187612972565b86600001516001600160a01b031663095ea7b383836001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611c1f919061432f565b60206040518083038186803b158015611c3757600080fd5b505afa158015611c4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6f9190613f19565b6040518363ffffffff1660e01b8152600401611c8c929190614381565b602060405180830381600087803b158015611ca657600080fd5b505af1158015611cba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cde9190613efd565b611cfa5760405162461bcd60e51b815260040161035c90614558565b8651608088015160a089015160c08a015160405163c723c87f60e01b81526001600160a01b0387169463c723c87f94611d3c9491938a9391929160040161439a565b600060405180830381600087803b158015611d5657600080fd5b505af1158015611d6a573d6000803e3d6000fd5b50506040516370a0823160e01b815260009250611da891508690600080516020614751833981519152906370a082319061043390309060040161432f565b90508015611e3b57602087015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb91611de791908590600401614381565b602060405180830381600087803b158015611e0157600080fd5b505af1158015611e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e399190613efd565b505b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190611e6a90309060040161432f565b60206040518083038186803b158015611e8257600080fd5b505afa158015611e96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eba9190613f19565b905087604001516000805160206147318339815191528961016001518b608001518c606001518587604051611b2d959493929190614468565b81600001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f3057600080fd5b505afa158015611f44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f689190613f19565b6060830152604051600090611f8890600190869086908690602001614427565b604051602081830303815290604052905082610140015115610e6a57600083600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015611fe357600080fd5b505afa158015611ff7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201b9190613e3c565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161204b919061432f565b60206040518083038186803b15801561206357600080fd5b505afa158015612077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209b9190613f19565b905080156120d55760808501516120d09086906120be6040880160208901613e20565b6120cb6020890189613e20565b612f76565b6120e4565b6120e485858760800151613419565b6121076120f0876146dc565b8661210036889003880188613f31565b6000611534565b5050610e83565b82602001516001600160a01b0316630b63fb628360400151856040015160016040518463ffffffff1660e01b815260040161214b93929190614675565b600060405180830381600087803b15801561216557600080fd5b505af1158015612179573d6000803e3d6000fd5b505050606084015160408086015160808601519151632e7ff4ef60e11b81526001600160a01b039093169350635cffe9de926121c9926000805160206147518339815191529187906004016143f4565b602060405180830381600087803b1580156121e357600080fd5b505af11580156121f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221b9190613efd565b5082602001516001600160a01b0316630b63fb628360400151856040015160006040518463ffffffff1660e01b815260040161225993929190614675565b600060405180830381600087803b15801561227357600080fd5b505af11580156117d1573d6000803e3d6000fd5b600080856001600160a01b031663d9638d36846040518263ffffffff1660e01b81526004016122b691906143d4565b60a06040518083038186803b1580156122ce57600080fd5b505afa1580156122e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123069190613ff2565b5050509150506000866001600160a01b0316632424be5c85876040518363ffffffff1660e01b815260040161233c9291906143dd565b604080518083038186803b15801561235357600080fd5b505afa158015612367573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238b9190613fcf565b9150506000876001600160a01b0316636c25b346886040518263ffffffff1660e01b81526004016123bc919061432f565b60206040518083038186803b1580156123d457600080fd5b505afa1580156123e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240c9190613f19565b9050600061241e8261048385876137c1565b9050676765c793fa10079d601b1b810494508061244686676765c793fa10079d601b1b6137c1565b106124515784612456565b846001015b9998505050505050505050565b600082608001519050600084600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b1580156124ab57600080fd5b505afa1580156124bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e39190613e3c565b905061250384602001518660000151876040015160008a60400151612972565b855160405163095ea7b360e01b81526001600160a01b039091169063095ea7b3906125349085908790600401614381565b602060405180830381600087803b15801561254e57600080fd5b505af1158015612562573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125869190613efd565b6125a25760405162461bcd60e51b815260040161035c90614558565b8551604080880151608089015160a08a015160c08b0151935163c723c87f60e01b81526001600160a01b0388169563c723c87f956125e89591949193919260040161439a565b600060405180830381600087803b15801561260257600080fd5b505af1158015612616573d6000803e3d6000fd5b50506040516370a0823160e01b81526000925060008051602061475183398151915291506370a082319061264e90309060040161432f565b60206040518083038186803b15801561266657600080fd5b505afa15801561267a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269e9190613f19565b905080866080015111156126c45760405162461bcd60e51b815260040161035c906144e7565b6126e585602001518760000151886040015189608001518a60c00151612972565b6040516370a0823160e01b8152600080516020614751833981519152906370a082319061271690309060040161432f565b60206040518083038186803b15801561272e57600080fd5b505afa158015612742573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127669190613f19565b90506000826001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612796919061432f565b60206040518083038186803b1580156127ae57600080fd5b505afa1580156127c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e69190613f19565b9050811561287957602087015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb9161282591908690600401614381565b602060405180830381600087803b15801561283f57600080fd5b505af1158015612853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128779190613efd565b505b8015612892576128928760000151886020015183612dbb565b86604001516000805160206147318339815191528861016001518a608001518b6060015185876040516128c9959493929190614468565b60405180910390a25050505050505050565b6000818484111561296a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561292f578181015183820152602001612917565b50505050905090810190601f16801561295c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000856001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b1580156129ad57600080fd5b505afa1580156129c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e59190613e3c565b90506000866001600160a01b0316632726b073866040518263ffffffff1660e01b8152600401612a1591906143d4565b60206040518083038186803b158015612a2d57600080fd5b505afa158015612a41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a659190613e3c565b90506000876001600160a01b0316632c2cb9fd876040518263ffffffff1660e01b8152600401612a9591906143d4565b60206040518083038186803b158015612aad57600080fd5b505afa158015612ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae59190613f19565b60405163095ea7b360e01b81529091506000805160206147518339815191529063095ea7b390612b2f90739759a6ac90977b93b58547b4a71c78317f391a28908990600401614381565b602060405180830381600087803b158015612b4957600080fd5b505af1158015612b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b819190613efd565b50604051633b4da69f60e01b8152739759a6ac90977b93b58547b4a71c78317f391a2890633b4da69f90612bbb9085908990600401614381565b600060405180830381600087803b158015612bd557600080fd5b505af1158015612be9573d6000803e3d6000fd5b505050506000612bf9888661381a565b9050886001600160a01b03166345e6bdcd88612c148461389d565b600003612c9e88896001600160a01b0316636c25b3468a6040518263ffffffff1660e01b8152600401612c47919061432f565b60206040518083038186803b158015612c5f57600080fd5b505afa158015612c73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c979190613f19565b89896138c4565b6040518463ffffffff1660e01b8152600401612cbc93929190614694565b600060405180830381600087803b158015612cd657600080fd5b505af1158015612cea573d6000803e3d6000fd5b50506040516313771f0760e31b81526001600160a01b038c169250639bb8f8389150612d1e908a9030908690600401614675565b600060405180830381600087803b158015612d3857600080fd5b505af1158015612d4c573d6000803e3d6000fd5b505060405163ef693bed60e01b81526001600160a01b038b16925063ef693bed9150612d7e9030908990600401614381565b600060405180830381600087803b158015612d9857600080fd5b505af1158015612dac573d6000803e3d6000fd5b50505050505050505050505050565b6000836001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015612df657600080fd5b505afa158015612e0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e2e9190613e3c565b90506001600160a01b03811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415612eef57604051632e1a7d4d60e01b81526001600160a01b03821690632e1a7d4d90612e819085906004016143d4565b600060405180830381600087803b158015612e9b57600080fd5b505af1158015612eaf573d6000803e3d6000fd5b50506040516001600160a01b038616925084156108fc02915084906000818181858888f19350505050158015612ee9573d6000803e3d6000fd5b50610e83565b60405163a9059cbb60e01b81526001600160a01b0382169063a9059cbb90612f1d9086908690600401614381565b602060405180830381600087803b158015612f3757600080fd5b505af1158015612f4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6f9190613efd565b5050505050565b600084600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015612fb557600080fd5b505afa158015612fc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fed9190613e3c565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161301d919061432f565b60206040518083038186803b15801561303557600080fd5b505afa158015613049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061306d9190613f19565b865160405163095ea7b360e01b81529192506001600160a01b0384169163095ea7b39161309e918590600401614381565b600060405180830381600087803b1580156130b857600080fd5b505af11580156130cc573d6000803e3d6000fd5b505050506000846001600160a01b0316632726b07388604001516040518263ffffffff1660e01b815260040161310291906143d4565b60206040518083038186803b15801561311a57600080fd5b505afa15801561312e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131529190613e3c565b90506000856001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b15801561318f57600080fd5b505afa1580156131a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131c79190613e3c565b8851604051633b4da69f60e01b81529192506001600160a01b031690633b4da69f906131f99085908790600401614381565b600060405180830381600087803b15801561321357600080fd5b505af1158015613227573d6000803e3d6000fd5b50505050856001600160a01b03166345e6bdcd89604001516132556132508c600001518861381a565b61389d565b613266858a888f606001518f613a08565b6040518463ffffffff1660e01b815260040161328493929190614694565b600060405180830381600087803b15801561329e57600080fd5b505af11580156132b2573d6000803e3d6000fd5b50505060408901516001600160a01b038816915063f9f30db690306132e28b676765c793fa10079d601b1b6137c1565b6040518463ffffffff1660e01b815260040161330093929190614675565b600060405180830381600087803b15801561331a57600080fd5b505af115801561332e573d6000803e3d6000fd5b50506040516328ec8bf160e21b81526001600160a01b038416925063a3b22fc4915061337290739759a6ac90977b93b58547b4a71c78317f391a289060040161432f565b600060405180830381600087803b15801561338c57600080fd5b505af11580156133a0573d6000803e3d6000fd5b505060405163ef693bed60e01b8152739759a6ac90977b93b58547b4a71c78317f391a28925063ef693bed91506133dd9030908b90600401614381565b600060405180830381600087803b1580156133f757600080fd5b505af115801561340b573d6000803e3d6000fd5b505050505050505050505050565b600061342b6040840160208501613e20565b6001600160a01b0316632726b07385604001516040518263ffffffff1660e01b815260040161345a91906143d4565b60206040518083038186803b15801561347257600080fd5b505afa158015613486573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134aa9190613e3c565b905060006134be6040850160208601613e20565b6001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b1580156134f657600080fd5b505afa15801561350a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352e9190613e3c565b90506135406040850160208601613e20565b6001600160a01b03166345e6bdcd866040015160006135788589600001602081019061356c9190613e20565b888c606001518b613a08565b6040518463ffffffff1660e01b815260040161359693929190614694565b600060405180830381600087803b1580156135b057600080fd5b505af11580156135c4573d6000803e3d6000fd5b506135d9925050506040850160208601613e20565b6001600160a01b031663f9f30db68660400151306135f687613b8a565b6040518463ffffffff1660e01b815260040161361493929190614675565b600060405180830381600087803b15801561362e57600080fd5b505af1158015613642573d6000803e3d6000fd5b5050604051634538c4eb60e01b81526001600160a01b0384169250634538c4eb9150613688903090739759a6ac90977b93b58547b4a71c78317f391a2890600401614343565b60206040518083038186803b1580156136a057600080fd5b505afa1580156136b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d89190613f19565b61374f576040516328ec8bf160e21b81526001600160a01b0382169063a3b22fc49061371c90739759a6ac90977b93b58547b4a71c78317f391a289060040161432f565b600060405180830381600087803b15801561373657600080fd5b505af115801561374a573d6000803e3d6000fd5b505050505b60405163ef693bed60e01b8152739759a6ac90977b93b58547b4a71c78317f391a289063ef693bed906137889030908790600401614381565b600060405180830381600087803b1580156137a257600080fd5b505af11580156137b6573d6000803e3d6000fd5b505050505050505050565b6000826137d05750600061113c565b828202828482816137dd57fe5b04146111395760405162461bcd60e51b81526004018080602001828103825260218152602001806147926021913960400191505060405180910390fd5b6000611139836001600160a01b031663b3bcfa826040518163ffffffff1660e01b815260040160206040518083038186803b15801561385857600080fd5b505afa15801561386c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138909190613f19565b8390601203600a0a6137c1565b8060008112156138bf5760405162461bcd60e51b815260040161035c906145a2565b919050565b600080856001600160a01b031663d9638d36846040518263ffffffff1660e01b81526004016138f391906143d4565b60a06040518083038186803b15801561390b57600080fd5b505afa15801561391f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139439190613ff2565b5050509150506000866001600160a01b0316632424be5c85876040518363ffffffff1660e01b81526004016139799291906143dd565b604080518083038186803b15801561399057600080fd5b505afa1580156139a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139c89190613fcf565b9150506139dd8287816139d757fe5b0461389d565b9250808311156139f8576139f08161389d565b6000036139fd565b826000035b979650505050505050565b600080856001600160a01b03166344e2a5a8856040518263ffffffff1660e01b8152600401613a3791906143d4565b602060405180830381600087803b158015613a5157600080fd5b505af1158015613a65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a899190613f19565b90506000876001600160a01b0316636c25b346876040518263ffffffff1660e01b8152600401613ab9919061432f565b60206040518083038186803b158015613ad157600080fd5b505afa158015613ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b099190613f19565b9050613b2084676765c793fa10079d601b1b6137c1565b811015613b7f57613b4b82613b448361048388676765c793fa10079d601b1b6137c1565b816139d757fe5b9250613b6284676765c793fa10079d601b1b6137c1565b613b6c84846137c1565b10613b775782613b7c565b826001015b92505b505095945050505050565b600061113c82676765c793fa10079d601b1b6137c1565b80356138bf816146e8565b80356138bf81614700565b600082601f830112613bc7578081fd5b813567ffffffffffffffff811115613bdb57fe5b613bee601f8201601f19166020016146b8565b818152846020838601011115613c02578283fd5b816020850160208301379081016020019190915292915050565b600060a08284031215613c2d578081fd5b60405160a0810181811067ffffffffffffffff82111715613c4a57fe5b6040529050808235613c5b816146e8565b81526020830135613c6b816146e8565b60208201526040830135613c7e816146e8565b60408201526060830135613c91816146e8565b60608201526080830135613ca4816146e8565b6080919091015292915050565b6000610180808385031215613cc4578182fd5b613ccd816146b8565b915050613cd982613ba1565b8152613ce760208301613ba1565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e0820152610100808301358183015250610120808301358183015250610140613d4e818401613bac565b908201526101608281013567ffffffffffffffff811115613d6e57600080fd5b613d7a85828601613bb7565b82840152505092915050565b600060e08284031215613d97578081fd5b613da160e06146b8565b9050613dac82613ba1565b8152613dba60208301613ba1565b6020820152604082013560408201526060820135606082015260808201356080820152613de960a08301613ba1565b60a082015260c082013567ffffffffffffffff811115613e0857600080fd5b613e1484828501613bb7565b60c08301525092915050565b600060208284031215613e31578081fd5b8135611139816146e8565b600060208284031215613e4d578081fd5b8151611139816146e8565b60008060008060008060a08789031215613e70578182fd5b8635613e7b816146e8565b95506020870135613e8b816146e8565b94506040870135935060608701359250608087013567ffffffffffffffff80821115613eb5578384fd5b818901915089601f830112613ec8578384fd5b813581811115613ed6578485fd5b8a6020828501011115613ee7578485fd5b6020830194508093505050509295509295509295565b600060208284031215613f0e578081fd5b815161113981614700565b600060208284031215613f2a578081fd5b5051919050565b600060a08284031215613f42578081fd5b6111398383613c1c565b600080600083850360e0811215613f61578182fd5b843567ffffffffffffffff80821115613f78578384fd5b9086019060e08289031215613f8b578384fd5b90945060208601359080821115613fa0578384fd5b50613fad87828801613cb1565b93505060a0603f1982011215613fc1578182fd5b506040840190509250925092565b60008060408385031215613fe1578182fd5b505080516020909101519092909150565b600080600080600060a08688031215614009578283fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b6000806000806101008587031215614047578182fd5b843560ff81168114614057578283fd5b9350602085013567ffffffffffffffff80821115614073578384fd5b61407f88838901613d86565b94506040870135915080821115614094578384fd5b506140a187828801613cb1565b9250506140b18660608701613c1c565b905092959194509250565b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452815b8181101561411e57602081850181015186830182015201614102565b8181111561412f5782602083870101525b50601f01601f19169290920160200192915050565b803561414f816146e8565b6001600160a01b03908116835260208201359061416b826146e8565b9081166020840152604082013590614182826146e8565b9081166040840152606082013590614199826146e8565b90811660608401526080820135906141b0826146e8565b808216608085015250505050565b60006101806141ce8484516140bc565b60208301516141e060208601826140bc565b5060408301516040850152606083015160608501526080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010080840151818601525061012080840151818601525061014080840151614248828701826140c9565b5050610160808401518282870152614262838701826140f9565b9695505050505050565b60008135614279816146e8565b6001600160a01b039081168452602083013590614295826146e8565b808216602086015260408401356040860152606084013560608601526080840135608086015260a084013591506142cb826146e8565b1660a084015260c082013536839003601e190181126142e8578182fd5b8201803567ffffffffffffffff811115614300578283fd5b80360384131561430e578283fd5b60e060c086015261432660e0860182602085016140cf565b95945050505050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03868116825260208201869052604082018590528316606082015260a0608082018190526000906139fd908301846140f9565b90815260200190565b9182526001600160a01b0316602082015260400190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614262908301846140f9565b600061010060ff871683528060208401526144448184018761426c565b9050828103604084015261445881866141be565b9150506143266060830184614144565b600060a0825261447b60a08301886140f9565b90508560208301528460408301528360608301528260808301529695505050505050565b60208082526028908201527f4d5041202f20436f756c64206e6f7420617070726f76652045786368616e676560408201526720666f722044414960c01b606082015260800190565b60208082526015908201527418d85b9b9bdd081c995c185e48185b1b081919589d605a1b604082015260600190565b60208082526022908201527f63616e6e6f7420636c6f736520746f2044414920696620464c206e6f74207573604082015261195960f21b606082015260800190565b6020808252602a908201527f4d5041202f20436f756c64206e6f7420617070726f76652045786368616e6765604082015269103337b9102a37b5b2b760b11b606082015260800190565b6020808252600f908201526e696e743235362d6f766572666c6f7760881b604082015260600190565b60208082526025908201527f6d70612d726563656976652d7265717565737465642d616d6f756e742d6d69736040820152640dac2e8c6d60db1b606082015260800190565b60208082526014908201527336b83096bab73a393ab9ba32b216b632b73232b960611b604082015260600190565b6020808252601f908201527f7468697320636f64652073686f756c6420626520756e726561636861626c6500604082015260600190565b9283526001600160a01b03919091166020830152604082015260600190565b9283526020830191909152604082015260600190565b918252602082015260400190565b60405181810167ffffffffffffffff811182821017156146d457fe5b604052919050565b600061113c3683613d86565b6001600160a01b03811681146146fd57600080fd5b50565b80151581146146fd57600080fdfe64656372656173654d756c7469706c655769746864726177436f6c6c61746572616cead01ff65532b6ee1646408ed4a14f45b5ee091a71e9bb1f579c0a44d59230110000000000000000000000006b175474e89094c44da98b954eedeac495271d0f696e6372656173654d756c7469706c654465706f736974436f6c6c61746572616c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220f80eb6141e0e7d3fc2e5d49a3dfc5c4f794a82b855b832a91ca49631f8197a7a64736f6c63430007060033

Deployed Bytecode

0x6080604052600436106100c25760003560e01c80634a9b4e0c1161007f578063ad5c464811610059578063ad5c4648146101ed578063cedee4ef1461020f578063e0bab4c414610222578063f85c2ce314610237576100c2565b80634a9b4e0c1461019a57806371ae86a5146101ba57806399e13c1a146101da576100c2565b80630521a3c7146100c45780631c9ea1e0146100e45780631f41f7b61461010457806323e30c8b1461012457806334f674731461015a5780633b9b4d951461017a575b005b3480156100d057600080fd5b506100c26100df366004613f4c565b61024c565b3480156100f057600080fd5b506100c26100ff366004613f4c565b6102b2565b34801561011057600080fd5b506100c261011f366004613f4c565b6102eb565b34801561013057600080fd5b5061014461013f366004613e58565b610372565b60405161015191906143d4565b60405180910390f35b34801561016657600080fd5b506100c2610175366004613f4c565b61066f565b34801561018657600080fd5b506100c2610195366004613f4c565b6106b5565b3480156101a657600080fd5b506100c26101b5366004613f4c565b61071c565b3480156101c657600080fd5b506100c26101d5366004613f4c565b610774565b6100c26101e8366004613f4c565b610912565b3480156101f957600080fd5b50610202610a7d565b604051610151919061432f565b6100c261021d366004613f4c565b610a95565b34801561022e57600080fd5b50610202610d68565b34801561024357600080fd5b50610202610d7a565b60405180606001604052806022815260200161470f60229139826102766060840160408501613e20565b6101608201515161028a5761016082018390525b610295868686610d92565b506040805160208101909152600081526101609091015250505050565b604080518082018252601081526f64656372656173654d756c7469706c6560801b60208201529083906102769060608501908501613e20565b6040805180820182526011815270636c6f73655661756c744578697444616960781b60208201529083906103259060608501908501613e20565b610160820151516103395761016082018390525b610140850151156103655760405162461bcd60e51b815260040161035c90614516565b60405180910390fd5b6102958686866003610e89565b60008080808061038486880188614031565b935093509350935080606001516001600160a01b0316336001600160a01b0316146103c15760405162461bcd60e51b815260040161035c90614610565b60006103cd8a8a6110df565b90507f9c6641b21946115d10f3f55df9bec5752ec06d40dc9250b1cc6560549764600e6104898461010001516000805160206147518339815191526001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610433919061432f565b60206040518083038186803b15801561044b57600080fd5b505afa15801561045f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104839190613f19565b90611142565b826040516104989291906146aa565b60405180910390a16040516370a0823160e01b8152600080516020614751833981519152906370a08231906104d190309060040161432f565b60206040518083038186803b1580156104e957600080fd5b505afa1580156104fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105219190613f19565b6101008401516080850151610535916110df565b11156105535760405162461bcd60e51b815260040161035c906145cb565b60ff8516610567576105678484848c611184565b8460ff166001141561057f5761057f8484848c611534565b8460ff166002141561059c5761059c848484848760a001516117da565b8460ff16600314156105b9576105b9848484848760a00151611b40565b606082015160405163095ea7b360e01b81526001600160a01b038d169163095ea7b3916105eb91908590600401614381565b602060405180830381600087803b15801561060557600080fd5b505af1158015610619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063d9190613efd565b507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd99c9b505050505050505050505050565b604080518082018252601b81527f64656372656173654d756c7469706c655769746864726177446169000000000060208201529083906102769060608501908501613e20565b604080518082018252601881527f636c6f73655661756c7445786974436f6c6c61746572616c000000000000000060208201529083906106fb9060608501908501613e20565b6101608201515161070f5761016082018390525b6102958686866002610e89565b604080518082018252601081526f696e6372656173654d756c7469706c6560801b60208201529083906107559060608501908501613e20565b610160820151516107695761016082018390525b610295868686611ef3565b604080518082018252601a81527f696e6372656173654d756c7469706c654465706f73697444616900000000000060208201529083906107ba9060608501908501613e20565b610160820151516107ce5761016082018390525b8461014001511561086b576101008501516040516323b872dd60e01b8152600080516020614751833981519152916323b872dd9161081391339130919060040161435d565b602060405180830381600087803b15801561082d57600080fd5b505af1158015610841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108659190613efd565b50610769565b6000805160206147518339815191526323b872dd336108906060880160408901613e20565b8861010001516040518463ffffffff1660e01b81526004016108b49392919061435d565b602060405180830381600087803b1580156108ce57600080fd5b505af11580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190613efd565b50610295868686611ef3565b60408051808201825260118152701bdc195b935d5b1d1a5c1b1e55985d5b1d607a1b602082015290839061094c9060608501908501613e20565b610160820151516109605761016082018390525b84600001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561099d57600080fd5b505afa1580156109b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d59190613f19565b60608601526109ea6040850160208601613e20565b6001600160a01b0316636090dec58660600151306040518363ffffffff1660e01b8152600401610a1b9291906143dd565b602060405180830381600087803b158015610a3557600080fd5b505af1158015610a49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6d9190613f19565b6040860152610295868686610a95565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6040518060600160405280602181526020016147716021913982610abf6060840160408501613e20565b61016082015151610ad35761016082018390525b600085600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1257600080fd5b505afa158015610b26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4a9190613e3c565b90506001600160a01b03811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415610c6857806001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b158015610bac57600080fd5b505af1158015610bc0573d6000803e3d6000fd5b5050505061014087015115159050610c63576001600160a01b03811663a9059cbb610bf16060880160408901613e20565b346040518363ffffffff1660e01b8152600401610c0f929190614381565b602060405180830381600087803b158015610c2957600080fd5b505af1158015610c3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c619190613efd565b505b610d3f565b610140860151610cb6576001600160a01b0381166323b872dd33610c926060890160408a01613e20565b8961012001516040518463ffffffff1660e01b8152600401610c0f9392919061435d565b6101208601516040516323b872dd60e01b81526001600160a01b038316916323b872dd91610ceb91339130919060040161435d565b602060405180830381600087803b158015610d0557600080fd5b505af1158015610d19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3d9190613efd565b505b610d4a878787611ef3565b50506040805160208101909152600081526101609091015250505050565b60008051602061475183398151915281565b739759a6ac90977b93b58547b4a71c78317f391a2881565b81600001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dcf57600080fd5b505afa158015610de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e079190613f19565b6060830152604051600090610e26908290869086908690602001614427565b604051602081830303815290604052905082610140015115610e6a57610e65610e4e856146dc565b84610e5e36869003860186613f31565b6000611184565b610e83565b610e83610e7c36849003840184613f31565b848361210e565b50505050565b82600001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ec657600080fd5b505afa158015610eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610efe9190613f19565b60608401526000610f156040840160208501613e20565b6001600160a01b0316632726b07385604001516040518263ffffffff1660e01b8152600401610f4491906143d4565b60206040518083038186803b158015610f5c57600080fd5b505afa158015610f70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f949190613e3c565b90506000610fa86040850160208601613e20565b6001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b158015610fe057600080fd5b505afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613e3c565b9050600061102c8284858960600151612287565b608087018190526040519091506000906110509086908a908a908a90602001614427565b60408051601f1981840301815291905261014088015190915061108b5761108661107f36889003880188613f31565b888361210e565b6110d5565b8460ff16600214156110bd576110866110a3896146dc565b886110b3368a90038a018a613f31565b8a60a00151612463565b60405162461bcd60e51b815260040161035c9061463e565b5050505050505050565b600082820183811015611139576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600061113983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506128db565b60808201516101408401516000906111ae5760e085015160808601516111a991611142565b6111b1565b60005b90506111e6846020015186600001518760400151846111e18a60c001518b60a001516110df90919063ffffffff16565b612972565b8551604080880151905163095ea7b360e01b81526001600160a01b039092169163095ea7b39161121b91869190600401614381565b602060405180830381600087803b15801561123557600080fd5b505af1158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d9190613efd565b6112895760405162461bcd60e51b815260040161035c90614558565b816001600160a01b031663c723c87f876000015188604001516112b9878a608001516110df90919063ffffffff16565b8a60a001518b60c001516040518663ffffffff1660e01b81526004016112e395949392919061439a565b600060405180830381600087803b1580156112fd57600080fd5b505af1158015611311573d6000803e3d6000fd5b505087516040516370a0823160e01b8152600093506001600160a01b0390911691506370a082319061134790309060040161432f565b60206040518083038186803b15801561135f57600080fd5b505afa158015611373573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113979190613f19565b905060008661014001511561140457602086015187516040808a015160e08b015191516370a0823160e01b81526113f99493926113f291600080516020614751833981519152906370a082319061043390309060040161432f565b6000612972565b5060e086015161144b565b60808701516114489061141790876110df565b6040516370a0823160e01b8152600080516020614751833981519152906370a082319061043390309060040161432f565b90505b86604001516000805160206147318339815191528861016001518a608001518b606001518686604051611482959493929190614468565b60405180910390a2801561151b57602087015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb916114c791908590600401614381565b602060405180830381600087803b1580156114e157600080fd5b505af11580156114f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115199190613efd565b505b81156110d5576110d58760000151886020015184612dbb565b6080808301519084015160009061154b90846110df565b90508461014001511561155c575060005b6000805160206147518339815191526001600160a01b031663095ea7b3836115968861010001518a604001516110df90919063ffffffff16565b6040518363ffffffff1660e01b81526004016115b3929190614381565b602060405180830381600087803b1580156115cd57600080fd5b505af11580156115e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116059190613efd565b6116215760405162461bcd60e51b815260040161035c9061449f565b816001600160a01b031663bc6f02b287602001516116518861010001518a604001516110df90919063ffffffff16565b89608001518a60a001518b60c001516040518663ffffffff1660e01b815260040161168095949392919061439a565b600060405180830381600087803b15801561169a57600080fd5b505af11580156116ae573d6000803e3d6000fd5b505050506116c6858286602001518760000151612f76565b6040516370a0823160e01b8152600090611700908390600080516020614751833981519152906370a082319061043390309060040161432f565b9050856040015160008051602061473183398151915287610160015189608001518a6060015160008660405161173a959493929190614468565b60405180910390a280156117d157602086015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb9161177f91908590600401614381565b602060405180830381600087803b15801561179957600080fd5b505af11580156117ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d59190613efd565b50505050505050565b600083608001519050600085600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b15801561182257600080fd5b505afa158015611836573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185a9190613e3c565b9050611879856020015187600001518860400151896080015187612972565b865160405163095ea7b360e01b81526001600160a01b039091169063095ea7b3906118aa9085908790600401614381565b602060405180830381600087803b1580156118c457600080fd5b505af11580156118d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118fc9190613efd565b6119185760405162461bcd60e51b815260040161035c90614558565b865160408089015160808a015160a08b015160c08c0151935163c723c87f60e01b81526001600160a01b0388169563c723c87f9561195e9591949193919260040161439a565b600060405180830381600087803b15801561197857600080fd5b505af115801561198c573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506119ca91508690600080516020614751833981519152906370a082319061043390309060040161432f565b90506000826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016119fa919061432f565b60206040518083038186803b158015611a1257600080fd5b505afa158015611a26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4a9190613f19565b90508115611add57602088015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb91611a8991908690600401614381565b602060405180830381600087803b158015611aa357600080fd5b505af1158015611ab7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adb9190613efd565b505b8015611af657611af68860000151896020015183612dbb565b87604001516000805160206147318339815191528961016001518b608001518c606001518587604051611b2d959493929190614468565b60405180910390a2505050505050505050565b600083608001519050600085600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015611b8857600080fd5b505afa158015611b9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc09190613e3c565b9050611bdf856020015187600001518860400151896080015187612972565b86600001516001600160a01b031663095ea7b383836001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611c1f919061432f565b60206040518083038186803b158015611c3757600080fd5b505afa158015611c4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6f9190613f19565b6040518363ffffffff1660e01b8152600401611c8c929190614381565b602060405180830381600087803b158015611ca657600080fd5b505af1158015611cba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cde9190613efd565b611cfa5760405162461bcd60e51b815260040161035c90614558565b8651608088015160a089015160c08a015160405163c723c87f60e01b81526001600160a01b0387169463c723c87f94611d3c9491938a9391929160040161439a565b600060405180830381600087803b158015611d5657600080fd5b505af1158015611d6a573d6000803e3d6000fd5b50506040516370a0823160e01b815260009250611da891508690600080516020614751833981519152906370a082319061043390309060040161432f565b90508015611e3b57602087015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb91611de791908590600401614381565b602060405180830381600087803b158015611e0157600080fd5b505af1158015611e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e399190613efd565b505b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190611e6a90309060040161432f565b60206040518083038186803b158015611e8257600080fd5b505afa158015611e96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eba9190613f19565b905087604001516000805160206147318339815191528961016001518b608001518c606001518587604051611b2d959493929190614468565b81600001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f3057600080fd5b505afa158015611f44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f689190613f19565b6060830152604051600090611f8890600190869086908690602001614427565b604051602081830303815290604052905082610140015115610e6a57600083600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015611fe357600080fd5b505afa158015611ff7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201b9190613e3c565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161204b919061432f565b60206040518083038186803b15801561206357600080fd5b505afa158015612077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209b9190613f19565b905080156120d55760808501516120d09086906120be6040880160208901613e20565b6120cb6020890189613e20565b612f76565b6120e4565b6120e485858760800151613419565b6121076120f0876146dc565b8661210036889003880188613f31565b6000611534565b5050610e83565b82602001516001600160a01b0316630b63fb628360400151856040015160016040518463ffffffff1660e01b815260040161214b93929190614675565b600060405180830381600087803b15801561216557600080fd5b505af1158015612179573d6000803e3d6000fd5b505050606084015160408086015160808601519151632e7ff4ef60e11b81526001600160a01b039093169350635cffe9de926121c9926000805160206147518339815191529187906004016143f4565b602060405180830381600087803b1580156121e357600080fd5b505af11580156121f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221b9190613efd565b5082602001516001600160a01b0316630b63fb628360400151856040015160006040518463ffffffff1660e01b815260040161225993929190614675565b600060405180830381600087803b15801561227357600080fd5b505af11580156117d1573d6000803e3d6000fd5b600080856001600160a01b031663d9638d36846040518263ffffffff1660e01b81526004016122b691906143d4565b60a06040518083038186803b1580156122ce57600080fd5b505afa1580156122e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123069190613ff2565b5050509150506000866001600160a01b0316632424be5c85876040518363ffffffff1660e01b815260040161233c9291906143dd565b604080518083038186803b15801561235357600080fd5b505afa158015612367573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238b9190613fcf565b9150506000876001600160a01b0316636c25b346886040518263ffffffff1660e01b81526004016123bc919061432f565b60206040518083038186803b1580156123d457600080fd5b505afa1580156123e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240c9190613f19565b9050600061241e8261048385876137c1565b9050676765c793fa10079d601b1b810494508061244686676765c793fa10079d601b1b6137c1565b106124515784612456565b846001015b9998505050505050505050565b600082608001519050600084600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b1580156124ab57600080fd5b505afa1580156124bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e39190613e3c565b905061250384602001518660000151876040015160008a60400151612972565b855160405163095ea7b360e01b81526001600160a01b039091169063095ea7b3906125349085908790600401614381565b602060405180830381600087803b15801561254e57600080fd5b505af1158015612562573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125869190613efd565b6125a25760405162461bcd60e51b815260040161035c90614558565b8551604080880151608089015160a08a015160c08b0151935163c723c87f60e01b81526001600160a01b0388169563c723c87f956125e89591949193919260040161439a565b600060405180830381600087803b15801561260257600080fd5b505af1158015612616573d6000803e3d6000fd5b50506040516370a0823160e01b81526000925060008051602061475183398151915291506370a082319061264e90309060040161432f565b60206040518083038186803b15801561266657600080fd5b505afa15801561267a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269e9190613f19565b905080866080015111156126c45760405162461bcd60e51b815260040161035c906144e7565b6126e585602001518760000151886040015189608001518a60c00151612972565b6040516370a0823160e01b8152600080516020614751833981519152906370a082319061271690309060040161432f565b60206040518083038186803b15801561272e57600080fd5b505afa158015612742573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127669190613f19565b90506000826001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612796919061432f565b60206040518083038186803b1580156127ae57600080fd5b505afa1580156127c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e69190613f19565b9050811561287957602087015160405163a9059cbb60e01b81526000805160206147518339815191529163a9059cbb9161282591908690600401614381565b602060405180830381600087803b15801561283f57600080fd5b505af1158015612853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128779190613efd565b505b8015612892576128928760000151886020015183612dbb565b86604001516000805160206147318339815191528861016001518a608001518b6060015185876040516128c9959493929190614468565b60405180910390a25050505050505050565b6000818484111561296a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561292f578181015183820152602001612917565b50505050905090810190601f16801561295c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000856001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b1580156129ad57600080fd5b505afa1580156129c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e59190613e3c565b90506000866001600160a01b0316632726b073866040518263ffffffff1660e01b8152600401612a1591906143d4565b60206040518083038186803b158015612a2d57600080fd5b505afa158015612a41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a659190613e3c565b90506000876001600160a01b0316632c2cb9fd876040518263ffffffff1660e01b8152600401612a9591906143d4565b60206040518083038186803b158015612aad57600080fd5b505afa158015612ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae59190613f19565b60405163095ea7b360e01b81529091506000805160206147518339815191529063095ea7b390612b2f90739759a6ac90977b93b58547b4a71c78317f391a28908990600401614381565b602060405180830381600087803b158015612b4957600080fd5b505af1158015612b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b819190613efd565b50604051633b4da69f60e01b8152739759a6ac90977b93b58547b4a71c78317f391a2890633b4da69f90612bbb9085908990600401614381565b600060405180830381600087803b158015612bd557600080fd5b505af1158015612be9573d6000803e3d6000fd5b505050506000612bf9888661381a565b9050886001600160a01b03166345e6bdcd88612c148461389d565b600003612c9e88896001600160a01b0316636c25b3468a6040518263ffffffff1660e01b8152600401612c47919061432f565b60206040518083038186803b158015612c5f57600080fd5b505afa158015612c73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c979190613f19565b89896138c4565b6040518463ffffffff1660e01b8152600401612cbc93929190614694565b600060405180830381600087803b158015612cd657600080fd5b505af1158015612cea573d6000803e3d6000fd5b50506040516313771f0760e31b81526001600160a01b038c169250639bb8f8389150612d1e908a9030908690600401614675565b600060405180830381600087803b158015612d3857600080fd5b505af1158015612d4c573d6000803e3d6000fd5b505060405163ef693bed60e01b81526001600160a01b038b16925063ef693bed9150612d7e9030908990600401614381565b600060405180830381600087803b158015612d9857600080fd5b505af1158015612dac573d6000803e3d6000fd5b50505050505050505050505050565b6000836001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015612df657600080fd5b505afa158015612e0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e2e9190613e3c565b90506001600160a01b03811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415612eef57604051632e1a7d4d60e01b81526001600160a01b03821690632e1a7d4d90612e819085906004016143d4565b600060405180830381600087803b158015612e9b57600080fd5b505af1158015612eaf573d6000803e3d6000fd5b50506040516001600160a01b038616925084156108fc02915084906000818181858888f19350505050158015612ee9573d6000803e3d6000fd5b50610e83565b60405163a9059cbb60e01b81526001600160a01b0382169063a9059cbb90612f1d9086908690600401614381565b602060405180830381600087803b158015612f3757600080fd5b505af1158015612f4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6f9190613efd565b5050505050565b600084600001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015612fb557600080fd5b505afa158015612fc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fed9190613e3c565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161301d919061432f565b60206040518083038186803b15801561303557600080fd5b505afa158015613049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061306d9190613f19565b865160405163095ea7b360e01b81529192506001600160a01b0384169163095ea7b39161309e918590600401614381565b600060405180830381600087803b1580156130b857600080fd5b505af11580156130cc573d6000803e3d6000fd5b505050506000846001600160a01b0316632726b07388604001516040518263ffffffff1660e01b815260040161310291906143d4565b60206040518083038186803b15801561311a57600080fd5b505afa15801561312e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131529190613e3c565b90506000856001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b15801561318f57600080fd5b505afa1580156131a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131c79190613e3c565b8851604051633b4da69f60e01b81529192506001600160a01b031690633b4da69f906131f99085908790600401614381565b600060405180830381600087803b15801561321357600080fd5b505af1158015613227573d6000803e3d6000fd5b50505050856001600160a01b03166345e6bdcd89604001516132556132508c600001518861381a565b61389d565b613266858a888f606001518f613a08565b6040518463ffffffff1660e01b815260040161328493929190614694565b600060405180830381600087803b15801561329e57600080fd5b505af11580156132b2573d6000803e3d6000fd5b50505060408901516001600160a01b038816915063f9f30db690306132e28b676765c793fa10079d601b1b6137c1565b6040518463ffffffff1660e01b815260040161330093929190614675565b600060405180830381600087803b15801561331a57600080fd5b505af115801561332e573d6000803e3d6000fd5b50506040516328ec8bf160e21b81526001600160a01b038416925063a3b22fc4915061337290739759a6ac90977b93b58547b4a71c78317f391a289060040161432f565b600060405180830381600087803b15801561338c57600080fd5b505af11580156133a0573d6000803e3d6000fd5b505060405163ef693bed60e01b8152739759a6ac90977b93b58547b4a71c78317f391a28925063ef693bed91506133dd9030908b90600401614381565b600060405180830381600087803b1580156133f757600080fd5b505af115801561340b573d6000803e3d6000fd5b505050505050505050505050565b600061342b6040840160208501613e20565b6001600160a01b0316632726b07385604001516040518263ffffffff1660e01b815260040161345a91906143d4565b60206040518083038186803b15801561347257600080fd5b505afa158015613486573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134aa9190613e3c565b905060006134be6040850160208601613e20565b6001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b1580156134f657600080fd5b505afa15801561350a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061352e9190613e3c565b90506135406040850160208601613e20565b6001600160a01b03166345e6bdcd866040015160006135788589600001602081019061356c9190613e20565b888c606001518b613a08565b6040518463ffffffff1660e01b815260040161359693929190614694565b600060405180830381600087803b1580156135b057600080fd5b505af11580156135c4573d6000803e3d6000fd5b506135d9925050506040850160208601613e20565b6001600160a01b031663f9f30db68660400151306135f687613b8a565b6040518463ffffffff1660e01b815260040161361493929190614675565b600060405180830381600087803b15801561362e57600080fd5b505af1158015613642573d6000803e3d6000fd5b5050604051634538c4eb60e01b81526001600160a01b0384169250634538c4eb9150613688903090739759a6ac90977b93b58547b4a71c78317f391a2890600401614343565b60206040518083038186803b1580156136a057600080fd5b505afa1580156136b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d89190613f19565b61374f576040516328ec8bf160e21b81526001600160a01b0382169063a3b22fc49061371c90739759a6ac90977b93b58547b4a71c78317f391a289060040161432f565b600060405180830381600087803b15801561373657600080fd5b505af115801561374a573d6000803e3d6000fd5b505050505b60405163ef693bed60e01b8152739759a6ac90977b93b58547b4a71c78317f391a289063ef693bed906137889030908790600401614381565b600060405180830381600087803b1580156137a257600080fd5b505af11580156137b6573d6000803e3d6000fd5b505050505050505050565b6000826137d05750600061113c565b828202828482816137dd57fe5b04146111395760405162461bcd60e51b81526004018080602001828103825260218152602001806147926021913960400191505060405180910390fd5b6000611139836001600160a01b031663b3bcfa826040518163ffffffff1660e01b815260040160206040518083038186803b15801561385857600080fd5b505afa15801561386c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138909190613f19565b8390601203600a0a6137c1565b8060008112156138bf5760405162461bcd60e51b815260040161035c906145a2565b919050565b600080856001600160a01b031663d9638d36846040518263ffffffff1660e01b81526004016138f391906143d4565b60a06040518083038186803b15801561390b57600080fd5b505afa15801561391f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139439190613ff2565b5050509150506000866001600160a01b0316632424be5c85876040518363ffffffff1660e01b81526004016139799291906143dd565b604080518083038186803b15801561399057600080fd5b505afa1580156139a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139c89190613fcf565b9150506139dd8287816139d757fe5b0461389d565b9250808311156139f8576139f08161389d565b6000036139fd565b826000035b979650505050505050565b600080856001600160a01b03166344e2a5a8856040518263ffffffff1660e01b8152600401613a3791906143d4565b602060405180830381600087803b158015613a5157600080fd5b505af1158015613a65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a899190613f19565b90506000876001600160a01b0316636c25b346876040518263ffffffff1660e01b8152600401613ab9919061432f565b60206040518083038186803b158015613ad157600080fd5b505afa158015613ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b099190613f19565b9050613b2084676765c793fa10079d601b1b6137c1565b811015613b7f57613b4b82613b448361048388676765c793fa10079d601b1b6137c1565b816139d757fe5b9250613b6284676765c793fa10079d601b1b6137c1565b613b6c84846137c1565b10613b775782613b7c565b826001015b92505b505095945050505050565b600061113c82676765c793fa10079d601b1b6137c1565b80356138bf816146e8565b80356138bf81614700565b600082601f830112613bc7578081fd5b813567ffffffffffffffff811115613bdb57fe5b613bee601f8201601f19166020016146b8565b818152846020838601011115613c02578283fd5b816020850160208301379081016020019190915292915050565b600060a08284031215613c2d578081fd5b60405160a0810181811067ffffffffffffffff82111715613c4a57fe5b6040529050808235613c5b816146e8565b81526020830135613c6b816146e8565b60208201526040830135613c7e816146e8565b60408201526060830135613c91816146e8565b60608201526080830135613ca4816146e8565b6080919091015292915050565b6000610180808385031215613cc4578182fd5b613ccd816146b8565b915050613cd982613ba1565b8152613ce760208301613ba1565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e0820152610100808301358183015250610120808301358183015250610140613d4e818401613bac565b908201526101608281013567ffffffffffffffff811115613d6e57600080fd5b613d7a85828601613bb7565b82840152505092915050565b600060e08284031215613d97578081fd5b613da160e06146b8565b9050613dac82613ba1565b8152613dba60208301613ba1565b6020820152604082013560408201526060820135606082015260808201356080820152613de960a08301613ba1565b60a082015260c082013567ffffffffffffffff811115613e0857600080fd5b613e1484828501613bb7565b60c08301525092915050565b600060208284031215613e31578081fd5b8135611139816146e8565b600060208284031215613e4d578081fd5b8151611139816146e8565b60008060008060008060a08789031215613e70578182fd5b8635613e7b816146e8565b95506020870135613e8b816146e8565b94506040870135935060608701359250608087013567ffffffffffffffff80821115613eb5578384fd5b818901915089601f830112613ec8578384fd5b813581811115613ed6578485fd5b8a6020828501011115613ee7578485fd5b6020830194508093505050509295509295509295565b600060208284031215613f0e578081fd5b815161113981614700565b600060208284031215613f2a578081fd5b5051919050565b600060a08284031215613f42578081fd5b6111398383613c1c565b600080600083850360e0811215613f61578182fd5b843567ffffffffffffffff80821115613f78578384fd5b9086019060e08289031215613f8b578384fd5b90945060208601359080821115613fa0578384fd5b50613fad87828801613cb1565b93505060a0603f1982011215613fc1578182fd5b506040840190509250925092565b60008060408385031215613fe1578182fd5b505080516020909101519092909150565b600080600080600060a08688031215614009578283fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b6000806000806101008587031215614047578182fd5b843560ff81168114614057578283fd5b9350602085013567ffffffffffffffff80821115614073578384fd5b61407f88838901613d86565b94506040870135915080821115614094578384fd5b506140a187828801613cb1565b9250506140b18660608701613c1c565b905092959194509250565b6001600160a01b03169052565b15159052565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452815b8181101561411e57602081850181015186830182015201614102565b8181111561412f5782602083870101525b50601f01601f19169290920160200192915050565b803561414f816146e8565b6001600160a01b03908116835260208201359061416b826146e8565b9081166020840152604082013590614182826146e8565b9081166040840152606082013590614199826146e8565b90811660608401526080820135906141b0826146e8565b808216608085015250505050565b60006101806141ce8484516140bc565b60208301516141e060208601826140bc565b5060408301516040850152606083015160608501526080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010080840151818601525061012080840151818601525061014080840151614248828701826140c9565b5050610160808401518282870152614262838701826140f9565b9695505050505050565b60008135614279816146e8565b6001600160a01b039081168452602083013590614295826146e8565b808216602086015260408401356040860152606084013560608601526080840135608086015260a084013591506142cb826146e8565b1660a084015260c082013536839003601e190181126142e8578182fd5b8201803567ffffffffffffffff811115614300578283fd5b80360384131561430e578283fd5b60e060c086015261432660e0860182602085016140cf565b95945050505050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03868116825260208201869052604082018590528316606082015260a0608082018190526000906139fd908301846140f9565b90815260200190565b9182526001600160a01b0316602082015260400190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614262908301846140f9565b600061010060ff871683528060208401526144448184018761426c565b9050828103604084015261445881866141be565b9150506143266060830184614144565b600060a0825261447b60a08301886140f9565b90508560208301528460408301528360608301528260808301529695505050505050565b60208082526028908201527f4d5041202f20436f756c64206e6f7420617070726f76652045786368616e676560408201526720666f722044414960c01b606082015260800190565b60208082526015908201527418d85b9b9bdd081c995c185e48185b1b081919589d605a1b604082015260600190565b60208082526022908201527f63616e6e6f7420636c6f736520746f2044414920696620464c206e6f74207573604082015261195960f21b606082015260800190565b6020808252602a908201527f4d5041202f20436f756c64206e6f7420617070726f76652045786368616e6765604082015269103337b9102a37b5b2b760b11b606082015260800190565b6020808252600f908201526e696e743235362d6f766572666c6f7760881b604082015260600190565b60208082526025908201527f6d70612d726563656976652d7265717565737465642d616d6f756e742d6d69736040820152640dac2e8c6d60db1b606082015260800190565b60208082526014908201527336b83096bab73a393ab9ba32b216b632b73232b960611b604082015260600190565b6020808252601f908201527f7468697320636f64652073686f756c6420626520756e726561636861626c6500604082015260600190565b9283526001600160a01b03919091166020830152604082015260600190565b9283526020830191909152604082015260600190565b918252602082015260400190565b60405181810167ffffffffffffffff811182821017156146d457fe5b604052919050565b600061113c3683613d86565b6001600160a01b03811681146146fd57600080fd5b50565b80151581146146fd57600080fdfe64656372656173654d756c7469706c655769746864726177436f6c6c61746572616cead01ff65532b6ee1646408ed4a14f45b5ee091a71e9bb1f579c0a44d59230110000000000000000000000006b175474e89094c44da98b954eedeac495271d0f696e6372656173654d756c7469706c654465706f736974436f6c6c61746572616c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220f80eb6141e0e7d3fc2e5d49a3dfc5c4f794a82b855b832a91ca49631f8197a7a64736f6c63430007060033

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  ]
[ 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.