Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
To
|
|||
|---|---|---|---|---|---|---|---|
| - | 11879624 | 1713 days ago | 2,351.42279578 ETH | ||||
| - | 11879624 | 1713 days ago | 2,351.42279578 ETH | ||||
| - | 11877863 | 1713 days ago | 122.13528432 ETH | ||||
| - | 11877863 | 1713 days ago | 122.13528432 ETH | ||||
| - | 11877863 | 1713 days ago | 217.87702775 ETH | ||||
| - | 11877863 | 1713 days ago | 0.54605771 ETH | ||||
| - | 11877863 | 1713 days ago | 218.42308547 ETH | ||||
| - | 11874003 | 1714 days ago | 1.90127863 ETH | ||||
| - | 11874003 | 1714 days ago | 1.90127863 ETH | ||||
| - | 11874003 | 1714 days ago | 3.51278241 ETH | ||||
| - | 11874003 | 1714 days ago | 0.00880396 ETH | ||||
| - | 11874003 | 1714 days ago | 3.52158638 ETH | ||||
| - | 11873975 | 1714 days ago | 1,007.90992942 ETH | ||||
| - | 11873975 | 1714 days ago | 1,007.90992942 ETH | ||||
| - | 11873975 | 1714 days ago | 1,785.06896824 ETH | ||||
| - | 11873975 | 1714 days ago | 4.47385706 ETH | ||||
| - | 11873975 | 1714 days ago | 1,789.5428253 ETH | ||||
| - | 11873449 | 1714 days ago | 10.9602339 ETH | ||||
| - | 11873449 | 1714 days ago | 10.9602339 ETH | ||||
| - | 11873449 | 1714 days ago | 15.01476595 ETH | ||||
| - | 11873449 | 1714 days ago | 0.03763099 ETH | ||||
| - | 11873449 | 1714 days ago | 15.05239694 ETH | ||||
| - | 11869353 | 1715 days ago | 107.63791589 ETH | ||||
| - | 11869353 | 1715 days ago | 107.63791589 ETH | ||||
| - | 11869203 | 1715 days ago | 39.3673572 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MCDCloseFlashLoan
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-01-18
*/
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
contract DefisaverLogger {
event LogEvent(
address indexed contractAddress,
address indexed caller,
string indexed logName,
bytes data
);
// solhint-disable-next-line func-name-mixedcase
function Log(address _contract, address _caller, string memory _logName, bytes memory _data)
public
{
emit LogEvent(_contract, _caller, _logName, _data);
}
} contract Discount {
address public owner;
mapping(address => CustomServiceFee) public serviceFees;
uint256 constant MAX_SERVICE_FEE = 400;
struct CustomServiceFee {
bool active;
uint256 amount;
}
constructor() public {
owner = msg.sender;
}
function isCustomFeeSet(address _user) public view returns (bool) {
return serviceFees[_user].active;
}
function getCustomServiceFee(address _user) public view returns (uint256) {
return serviceFees[_user].amount;
}
function setServiceFee(address _user, uint256 _fee) public {
require(msg.sender == owner, "Only owner");
require(_fee >= MAX_SERVICE_FEE || _fee == 0);
serviceFees[_user] = CustomServiceFee({active: true, amount: _fee});
}
function disableServiceFee(address _user) public {
require(msg.sender == owner, "Only owner");
serviceFees[_user] = CustomServiceFee({active: false, amount: 0});
}
} abstract contract PipInterface {
function read() public virtual returns (bytes32);
} abstract contract Spotter {
struct Ilk {
PipInterface pip;
uint256 mat;
}
mapping (bytes32 => Ilk) public ilks;
uint256 public par;
} abstract contract Jug {
struct Ilk {
uint256 duty;
uint256 rho;
}
mapping (bytes32 => Ilk) public ilks;
function drip(bytes32) public virtual returns (uint);
} abstract contract Vat {
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 => uint)) public gem; // [wad]
function can(address, address) virtual public view returns (uint);
function dai(address) virtual public view returns (uint);
function frob(bytes32, address, address, address, int, int) virtual public;
function hope(address) virtual public;
function move(address, address, uint) virtual public;
function fork(bytes32, address, address, int, int) virtual public;
} abstract contract Gem {
function dec() virtual public returns (uint);
function gem() virtual public returns (Gem);
function join(address, uint) virtual public payable;
function exit(address, uint) virtual public;
function approve(address, uint) virtual public;
function transfer(address, uint) virtual public returns (bool);
function transferFrom(address, address, uint) virtual public returns (bool);
function deposit() virtual public payable;
function withdraw(uint) virtual public;
function allowance(address, address) virtual public returns (uint);
} abstract contract DaiJoin {
function vat() public virtual returns (Vat);
function dai() public virtual returns (Gem);
function join(address, uint) public virtual payable;
function exit(address, uint) public virtual;
} abstract contract Join {
bytes32 public ilk;
function dec() virtual public view returns (uint);
function gem() virtual public view returns (Gem);
function join(address, uint) virtual public payable;
function exit(address, uint) virtual public;
} contract DSMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x);
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x);
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x);
}
function div(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x / y;
}
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x <= y ? x : y;
}
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x >= y ? x : y;
}
function imin(int256 x, int256 y) internal pure returns (int256 z) {
return x <= y ? x : y;
}
function imax(int256 x, int256 y) internal pure returns (int256 z) {
return x >= y ? x : y;
}
uint256 constant WAD = 10**18;
uint256 constant RAY = 10**27;
function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, WAD), y / 2) / y;
}
function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, RAY), y / 2) / y;
}
// This famous algorithm is called "exponentiation by squaring"
// and calculates x^n with x as fixed-point and n as regular unsigned.
//
// It's O(log n), instead of O(n) for naive repeated multiplication.
//
// These facts are why it works:
//
// If n is even, then x^n = (x^2)^(n/2).
// If n is odd, then x^n = x * x^(n-1),
// and applying the equation for even x gives
// x^n = x * (x^2)^((n-1) / 2).
//
// Also, EVM division is flooring and
// floor[(n-1) / 2] = floor[n / 2].
//
function rpow(uint256 x, uint256 n) internal pure returns (uint256 z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
} abstract contract DSAuthority {
function canCall(address src, address dst, bytes4 sig) public virtual view returns (bool);
} contract DSAuthEvents {
event LogSetAuthority(address indexed authority);
event LogSetOwner(address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() public {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_) public auth {
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_) public auth {
authority = authority_;
emit LogSetAuthority(address(authority));
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, address(this), sig);
}
}
} contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint256 wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
} abstract contract DSProxy is DSAuth, DSNote {
DSProxyCache public cache; // global cache for contracts
constructor(address _cacheAddr) public {
require(setCache(_cacheAddr));
}
// solhint-disable-next-line no-empty-blocks
receive() external payable {}
// use the proxy to execute calldata _data on contract _code
// function execute(bytes memory _code, bytes memory _data)
// public
// payable
// virtual
// returns (address target, bytes32 response);
function execute(address _target, bytes memory _data)
public
payable
virtual
returns (bytes32 response);
//set new cache
function setCache(address _cacheAddr) public virtual payable returns (bool);
}
contract DSProxyCache {
mapping(bytes32 => address) cache;
function read(bytes memory _code) public view returns (address) {
bytes32 hash = keccak256(_code);
return cache[hash];
}
function write(bytes memory _code) public returns (address target) {
assembly {
target := create(0, add(_code, 0x20), mload(_code))
switch iszero(extcodesize(target))
case 1 {
// throw if contract failed to deploy
revert(0, 0)
}
}
bytes32 hash = keccak256(_code);
cache[hash] = target;
}
} abstract contract Manager {
function last(address) virtual public returns (uint);
function cdpCan(address, uint, address) virtual public view returns (uint);
function ilks(uint) virtual public view returns (bytes32);
function owns(uint) virtual public view returns (address);
function urns(uint) virtual public view returns (address);
function vat() virtual public view returns (address);
function open(bytes32, address) virtual public returns (uint);
function give(uint, address) virtual public;
function cdpAllow(uint, address, uint) virtual public;
function urnAllow(address, uint) virtual public;
function frob(uint, int, int) virtual public;
function flux(uint, address, uint) virtual public;
function move(uint, address, uint) virtual public;
function exit(address, uint, address, uint) virtual public;
function quit(uint, address) virtual public;
function enter(address, uint) virtual public;
function shift(uint, uint) virtual public;
} /// @title Helper methods for MCDSaverProxy
contract MCDSaverProxyHelper is DSMath {
enum ManagerType { MCD, BPROTOCOL }
/// @notice Returns a normalized debt _amount based on the current rate
/// @param _amount Amount of dai to be normalized
/// @param _rate Current rate of the stability fee
/// @param _daiVatBalance Balance od Dai in the Vat for that CDP
function normalizeDrawAmount(uint _amount, uint _rate, uint _daiVatBalance) internal pure returns (int dart) {
if (_daiVatBalance < mul(_amount, RAY)) {
dart = toPositiveInt(sub(mul(_amount, RAY), _daiVatBalance) / _rate);
dart = mul(uint(dart), _rate) < mul(_amount, RAY) ? dart + 1 : dart;
}
}
/// @notice Converts a number to Rad percision
/// @param _wad The input number in wad percision
function toRad(uint _wad) internal pure returns (uint) {
return mul(_wad, 10 ** 27);
}
/// @notice Converts a number to 18 decimal percision
/// @param _joinAddr Join address of the collateral
/// @param _amount Number to be converted
function convertTo18(address _joinAddr, uint256 _amount) internal view returns (uint256) {
return mul(_amount, 10 ** (18 - Join(_joinAddr).dec()));
}
/// @notice Converts a uint to int and checks if positive
/// @param _x Number to be converted
function toPositiveInt(uint _x) internal pure returns (int y) {
y = int(_x);
require(y >= 0, "int-overflow");
}
/// @notice Gets Dai amount in Vat which can be added to Cdp
/// @param _vat Address of Vat contract
/// @param _urn Urn of the Cdp
/// @param _ilk Ilk of the Cdp
function normalizePaybackAmount(address _vat, address _urn, bytes32 _ilk) internal view returns (int amount) {
uint dai = Vat(_vat).dai(_urn);
(, uint rate,,,) = Vat(_vat).ilks(_ilk);
(, uint art) = Vat(_vat).urns(_ilk, _urn);
amount = toPositiveInt(dai / rate);
amount = uint(amount) <= art ? - amount : - toPositiveInt(art);
}
/// @notice Gets the whole debt of the CDP
/// @param _vat Address of Vat contract
/// @param _usr Address of the Dai holder
/// @param _urn Urn of the Cdp
/// @param _ilk Ilk of the Cdp
function getAllDebt(address _vat, address _usr, address _urn, bytes32 _ilk) internal view returns (uint daiAmount) {
(, uint rate,,,) = Vat(_vat).ilks(_ilk);
(, uint art) = Vat(_vat).urns(_ilk, _urn);
uint dai = Vat(_vat).dai(_usr);
uint rad = sub(mul(art, rate), dai);
daiAmount = rad / RAY;
daiAmount = mul(daiAmount, RAY) < rad ? daiAmount + 1 : daiAmount;
}
/// @notice Gets the token address from the Join contract
/// @param _joinAddr Address of the Join contract
function getCollateralAddr(address _joinAddr) internal view returns (address) {
return address(Join(_joinAddr).gem());
}
/// @notice Checks if the join address is one of the Ether coll. types
/// @param _joinAddr Join address to check
function isEthJoinAddr(address _joinAddr) internal view returns (bool) {
// if it's dai_join_addr don't check gem() it will fail
if (_joinAddr == 0x9759A6Ac90977b93B58547b4A71c78317f391A28) return false;
// if coll is weth it's and eth type coll
if (address(Join(_joinAddr).gem()) == 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) {
return true;
}
return false;
}
/// @notice Gets CDP info (collateral, debt)
/// @param _manager Manager contract
/// @param _cdpId Id of the CDP
/// @param _ilk Ilk of the CDP
function getCdpInfo(Manager _manager, uint _cdpId, bytes32 _ilk) public view returns (uint, uint) {
address vat = _manager.vat();
address urn = _manager.urns(_cdpId);
(uint collateral, uint debt) = Vat(vat).urns(_ilk, urn);
(,uint rate,,,) = Vat(vat).ilks(_ilk);
return (collateral, rmul(debt, rate));
}
/// @notice Address that owns the DSProxy that owns the CDP
/// @param _manager Manager contract
/// @param _cdpId Id of the CDP
function getOwner(Manager _manager, uint _cdpId) public view returns (address) {
DSProxy proxy = DSProxy(uint160(_manager.owns(_cdpId)));
return proxy.owner();
}
/// @notice Based on the manager type returns the address
/// @param _managerType Type of vault manager to use
function getManagerAddr(ManagerType _managerType) public pure returns (address) {
if (_managerType == ManagerType.MCD) {
return 0x5ef30b9986345249bc32d8928B7ee64DE9435E39;
} else if (_managerType == ManagerType.BPROTOCOL) {
return 0x3f30c2381CD8B917Dd96EB2f1A4F96D91324BBed;
}
}
} interface ERC20 {
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);
} library Address {
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
} 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;
}
} library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(ERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*/
function safeApprove(ERC20 token, address spender, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(ERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(ERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(ERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
} contract AdminAuth {
using SafeERC20 for ERC20;
address public owner;
address public admin;
modifier onlyOwner() {
require(owner == msg.sender);
_;
}
modifier onlyAdmin() {
require(admin == msg.sender);
_;
}
constructor() public {
owner = msg.sender;
admin = 0x25eFA336886C74eA8E282ac466BdCd0199f85BB9;
}
/// @notice Admin is set by owner first time, after that admin is super role and has permission to change owner
/// @param _admin Address of multisig that becomes admin
function setAdminByOwner(address _admin) public {
require(msg.sender == owner);
require(admin == address(0));
admin = _admin;
}
/// @notice Admin is able to set new admin
/// @param _admin Address of multisig that becomes new admin
function setAdminByAdmin(address _admin) public {
require(msg.sender == admin);
admin = _admin;
}
/// @notice Admin is able to change owner
/// @param _owner Address of new owner
function setOwnerByAdmin(address _owner) public {
require(msg.sender == admin);
owner = _owner;
}
/// @notice Destroy the contract
function kill() public onlyOwner {
selfdestruct(payable(owner));
}
/// @notice withdraw stuck funds
function withdrawStuckFunds(address _token, uint _amount) public onlyOwner {
if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
payable(owner).transfer(_amount);
} else {
ERC20(_token).safeTransfer(owner, _amount);
}
}
} contract BotRegistry is AdminAuth {
mapping (address => bool) public botList;
constructor() public {
botList[0x776B4a13093e30B05781F97F6A4565B6aa8BE330] = true;
botList[0xAED662abcC4FA3314985E67Ea993CAD064a7F5cF] = true;
botList[0xa5d330F6619d6bF892A5B87D80272e1607b3e34D] = true;
botList[0x5feB4DeE5150B589a7f567EA7CADa2759794A90A] = true;
botList[0x7ca06417c1d6f480d3bB195B80692F95A6B66158] = true;
}
function setBot(address _botAddr, bool _state) public onlyOwner {
botList[_botAddr] = _state;
}
} abstract contract TokenInterface {
address public constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
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 virtual payable;
function withdraw(uint256) public virtual;
} interface ExchangeInterfaceV3 {
function sell(address _srcAddr, address _destAddr, uint _srcAmount, bytes memory _additionalData) external payable returns (uint);
function buy(address _srcAddr, address _destAddr, uint _destAmount, bytes memory _additionalData) external payable returns(uint);
function getSellRate(address _srcAddr, address _destAddr, uint _srcAmount, bytes memory _additionalData) external view returns (uint);
function getBuyRate(address _srcAddr, address _destAddr, uint _srcAmount, bytes memory _additionalData) external view returns (uint);
} contract ZrxAllowlist is AdminAuth {
mapping (address => bool) public zrxAllowlist;
mapping(address => bool) private nonPayableAddrs;
constructor() public {
zrxAllowlist[0x6958F5e95332D93D21af0D7B9Ca85B8212fEE0A5] = true;
zrxAllowlist[0x61935CbDd02287B511119DDb11Aeb42F1593b7Ef] = true;
zrxAllowlist[0xDef1C0ded9bec7F1a1670819833240f027b25EfF] = true;
zrxAllowlist[0x080bf510FCbF18b91105470639e9561022937712] = true;
nonPayableAddrs[0x080bf510FCbF18b91105470639e9561022937712] = true;
}
function setAllowlistAddr(address _zrxAddr, bool _state) public onlyOwner {
zrxAllowlist[_zrxAddr] = _state;
}
function isZrxAddr(address _zrxAddr) public view returns (bool) {
return zrxAllowlist[_zrxAddr];
}
function addNonPayableAddr(address _nonPayableAddr) public onlyOwner {
nonPayableAddrs[_nonPayableAddr] = true;
}
function removeNonPayableAddr(address _nonPayableAddr) public onlyOwner {
nonPayableAddrs[_nonPayableAddr] = false;
}
function isNonPayableAddr(address _addr) public view returns(bool) {
return nonPayableAddrs[_addr];
}
}
contract DFSExchangeData {
// first is empty to keep the legacy order in place
enum ExchangeType { _, OASIS, KYBER, UNISWAP, ZEROX }
enum ActionType { SELL, BUY }
struct OffchainData {
address wrapper;
address exchangeAddr;
address allowanceTarget;
uint256 price;
uint256 protocolFee;
bytes callData;
}
struct ExchangeData {
address srcAddr;
address destAddr;
uint256 srcAmount;
uint256 destAmount;
uint256 minPrice;
uint256 dfsFeeDivider; // service fee divider
address user; // user to check special fee
address wrapper;
bytes wrapperData;
OffchainData offchainData;
}
function packExchangeData(ExchangeData memory _exData) public pure returns(bytes memory) {
return abi.encode(_exData);
}
function unpackExchangeData(bytes memory _data) public pure returns(ExchangeData memory _exData) {
_exData = abi.decode(_data, (ExchangeData));
}
} contract DFSExchangeHelper {
string public constant ERR_OFFCHAIN_DATA_INVALID = "Offchain data invalid";
using SafeERC20 for ERC20;
address public constant KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address public constant EXCHANGE_WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address payable public constant WALLET_ID = 0x322d58b9E75a6918f7e7849AEe0fF09369977e08;
address public constant DISCOUNT_ADDRESS = 0x1b14E8D511c9A4395425314f849bD737BAF8208F;
address public constant SAVER_EXCHANGE_REGISTRY = 0x25dd3F51e0C3c3Ff164DDC02A8E4D65Bb9cBB12D;
address public constant ZRX_ALLOWLIST_ADDR = 0x4BA1f38427b33B8ab7Bb0490200dAE1F1C36823F;
function getDecimals(address _token) internal view returns (uint256) {
if (_token == KYBER_ETH_ADDRESS) return 18;
return ERC20(_token).decimals();
}
function getBalance(address _tokenAddr) internal view returns (uint balance) {
if (_tokenAddr == KYBER_ETH_ADDRESS) {
balance = address(this).balance;
} else {
balance = ERC20(_tokenAddr).balanceOf(address(this));
}
}
function sendLeftover(address _srcAddr, address _destAddr, address payable _to) internal {
// send back any leftover ether or tokens
if (address(this).balance > 0) {
_to.transfer(address(this).balance);
}
if (getBalance(_srcAddr) > 0) {
ERC20(_srcAddr).safeTransfer(_to, getBalance(_srcAddr));
}
if (getBalance(_destAddr) > 0) {
ERC20(_destAddr).safeTransfer(_to, getBalance(_destAddr));
}
}
/// @notice Takes a feePercentage and sends it to wallet
/// @param _amount Dai amount of the whole trade
/// @param _user Address of the user
/// @param _token Address of the token
/// @param _dfsFeeDivider Dfs fee divider
/// @return feeAmount Amount in Dai owner earned on the fee
function getFee(uint256 _amount, address _user, address _token, uint256 _dfsFeeDivider) internal returns (uint256 feeAmount) {
if (_dfsFeeDivider != 0 && Discount(DISCOUNT_ADDRESS).isCustomFeeSet(_user)) {
_dfsFeeDivider = Discount(DISCOUNT_ADDRESS).getCustomServiceFee(_user);
}
if (_dfsFeeDivider == 0) {
feeAmount = 0;
} else {
feeAmount = _amount / _dfsFeeDivider;
// fee can't go over 10% of the whole amount
if (feeAmount > (_amount / 10)) {
feeAmount = _amount / 10;
}
if (_token == KYBER_ETH_ADDRESS) {
WALLET_ID.transfer(feeAmount);
} else {
ERC20(_token).safeTransfer(WALLET_ID, feeAmount);
}
}
}
function sliceUint(bytes memory bs, uint256 start) internal pure returns (uint256) {
require(bs.length >= start + 32, "slicing out of range");
uint256 x;
assembly {
x := mload(add(bs, add(0x20, start)))
}
return x;
}
function writeUint256(bytes memory _b, uint256 _index, uint _input) internal pure {
if (_b.length < _index + 32) {
revert(ERR_OFFCHAIN_DATA_INVALID);
}
bytes32 input = bytes32(_input);
_index += 32;
// Read the bytes32 from array memory
assembly {
mstore(add(_b, _index), input)
}
}
/// @notice Converts Kybers Eth address -> Weth
/// @param _src Input address
function ethToWethAddr(address _src) internal pure returns (address) {
return _src == KYBER_ETH_ADDRESS ? EXCHANGE_WETH_ADDRESS : _src;
}
} contract SaverExchangeRegistry is AdminAuth {
mapping(address => bool) private wrappers;
constructor() public {
wrappers[0x880A845A85F843a5c67DB2061623c6Fc3bB4c511] = true;
wrappers[0x4c9B55f2083629A1F7aDa257ae984E03096eCD25] = true;
wrappers[0x42A9237b872368E1bec4Ca8D26A928D7d39d338C] = true;
}
function addWrapper(address _wrapper) public onlyOwner {
wrappers[_wrapper] = true;
}
function removeWrapper(address _wrapper) public onlyOwner {
wrappers[_wrapper] = false;
}
function isWrapper(address _wrapper) public view returns(bool) {
return wrappers[_wrapper];
}
}
abstract contract OffchainWrapperInterface is DFSExchangeData {
function takeOrder(
ExchangeData memory _exData,
ActionType _type
) virtual public payable returns (bool success, uint256);
}
contract DFSExchangeCore is DFSExchangeHelper, DSMath, DFSExchangeData {
string public constant ERR_SLIPPAGE_HIT = "Slippage hit";
string public constant ERR_DEST_AMOUNT_MISSING = "Dest amount missing";
string public constant ERR_WRAPPER_INVALID = "Wrapper invalid";
string public constant ERR_NOT_ZEROX_EXCHANGE = "Zerox exchange invalid";
/// @notice Internal method that preforms a sell on 0x/on-chain
/// @dev Usefull for other DFS contract to integrate for exchanging
/// @param exData Exchange data struct
/// @return (address, uint) Address of the wrapper used and destAmount
function _sell(ExchangeData memory exData) internal returns (address, uint) {
address wrapper;
uint swapedTokens;
bool success;
// if selling eth, convert to weth
if (exData.srcAddr == KYBER_ETH_ADDRESS) {
exData.srcAddr = ethToWethAddr(exData.srcAddr);
TokenInterface(EXCHANGE_WETH_ADDRESS).deposit{value: exData.srcAmount}();
}
exData.srcAmount -= getFee(exData.srcAmount, exData.user, exData.srcAddr, exData.dfsFeeDivider);
// Try 0x first and then fallback on specific wrapper
if (exData.offchainData.price > 0) {
(success, swapedTokens) = takeOrder(exData, ActionType.SELL);
if (success) {
wrapper = exData.offchainData.exchangeAddr;
}
}
// fallback to desired wrapper if 0x failed
if (!success) {
swapedTokens = saverSwap(exData, ActionType.SELL);
wrapper = exData.wrapper;
}
// if anything is left in weth, pull it to user as eth
if (getBalance(EXCHANGE_WETH_ADDRESS) > 0) {
TokenInterface(EXCHANGE_WETH_ADDRESS).withdraw(
TokenInterface(EXCHANGE_WETH_ADDRESS).balanceOf(address(this))
);
}
if (exData.destAddr == EXCHANGE_WETH_ADDRESS) {
require(getBalance(KYBER_ETH_ADDRESS) >= wmul(exData.minPrice, exData.srcAmount), ERR_SLIPPAGE_HIT);
} else {
require(getBalance(exData.destAddr) >= wmul(exData.minPrice, exData.srcAmount), ERR_SLIPPAGE_HIT);
}
return (wrapper, swapedTokens);
}
/// @notice Internal method that preforms a buy on 0x/on-chain
/// @dev Usefull for other DFS contract to integrate for exchanging
/// @param exData Exchange data struct
/// @return (address, uint) Address of the wrapper used and srcAmount
function _buy(ExchangeData memory exData) internal returns (address, uint) {
address wrapper;
uint swapedTokens;
bool success;
require(exData.destAmount != 0, ERR_DEST_AMOUNT_MISSING);
exData.srcAmount -= getFee(exData.srcAmount, exData.user, exData.srcAddr, exData.dfsFeeDivider);
// if selling eth, convert to weth
if (exData.srcAddr == KYBER_ETH_ADDRESS) {
exData.srcAddr = ethToWethAddr(exData.srcAddr);
TokenInterface(EXCHANGE_WETH_ADDRESS).deposit{value: exData.srcAmount}();
}
if (exData.offchainData.price > 0) {
(success, swapedTokens) = takeOrder(exData, ActionType.BUY);
if (success) {
wrapper = exData.offchainData.exchangeAddr;
}
}
// fallback to desired wrapper if 0x failed
if (!success) {
// calculate src amount based on price and add 5%
/// @dev this value in exData object will be changed in parent method as well
exData.srcAmount = div(mul(wdiv(exData.destAmount, exData.minPrice), 105), 100);
swapedTokens = saverSwap(exData, ActionType.BUY);
wrapper = exData.wrapper;
}
// if anything is left in weth, pull it to user as eth
if (getBalance(EXCHANGE_WETH_ADDRESS) > 0) {
TokenInterface(EXCHANGE_WETH_ADDRESS).withdraw(
TokenInterface(EXCHANGE_WETH_ADDRESS).balanceOf(address(this))
);
}
if (exData.destAddr == EXCHANGE_WETH_ADDRESS) {
require(getBalance(KYBER_ETH_ADDRESS) >= exData.destAmount, ERR_SLIPPAGE_HIT);
} else {
require(getBalance(exData.destAddr) >= exData.destAmount, ERR_SLIPPAGE_HIT);
}
return (wrapper, getBalance(exData.destAddr));
}
/// @notice Takes order from 0x and returns bool indicating if it is successful
/// @param _exData Exchange data
function takeOrder(
ExchangeData memory _exData,
ActionType _type
) private returns (bool success, uint256) {
if (!ZrxAllowlist(ZRX_ALLOWLIST_ADDR).isZrxAddr(_exData.offchainData.exchangeAddr)) {
return (false, 0);
}
if (!SaverExchangeRegistry(SAVER_EXCHANGE_REGISTRY).isWrapper(_exData.offchainData.wrapper)) {
return (false, 0);
}
// send src amount
ERC20(_exData.srcAddr).safeTransfer(_exData.offchainData.wrapper, _exData.srcAmount);
return OffchainWrapperInterface(_exData.offchainData.wrapper).takeOrder{value: _exData.offchainData.protocolFee}(_exData, _type);
}
/// @notice Calls wraper contract for exchage to preform an on-chain swap
/// @param _exData Exchange data struct
/// @param _type Type of action SELL|BUY
/// @return swapedTokens For Sell that the destAmount, for Buy thats the srcAmount
function saverSwap(ExchangeData memory _exData, ActionType _type) internal returns (uint swapedTokens) {
require(SaverExchangeRegistry(SAVER_EXCHANGE_REGISTRY).isWrapper(_exData.wrapper), ERR_WRAPPER_INVALID);
ERC20(_exData.srcAddr).safeTransfer(_exData.wrapper, _exData.srcAmount);
if (_type == ActionType.SELL) {
swapedTokens = ExchangeInterfaceV3(_exData.wrapper).
sell(_exData.srcAddr, _exData.destAddr, _exData.srcAmount, _exData.wrapperData);
} else {
swapedTokens = ExchangeInterfaceV3(_exData.wrapper).
buy(_exData.srcAddr, _exData.destAddr, _exData.destAmount, _exData.wrapperData);
}
}
// solhint-disable-next-line no-empty-blocks
receive() external virtual payable {}
}
/// @title Implements Boost and Repay for MCD CDPs
contract MCDSaverProxy is DFSExchangeCore, MCDSaverProxyHelper {
uint public constant MANUAL_SERVICE_FEE = 400; // 0.25% Fee
uint public constant AUTOMATIC_SERVICE_FEE = 333; // 0.3% Fee
bytes32 public constant ETH_ILK = 0x4554482d41000000000000000000000000000000000000000000000000000000;
address public constant VAT_ADDRESS = 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B;
address public constant SPOTTER_ADDRESS = 0x65C79fcB50Ca1594B025960e539eD7A9a6D434A3;
address public constant DAI_JOIN_ADDRESS = 0x9759A6Ac90977b93B58547b4A71c78317f391A28;
address public constant JUG_ADDRESS = 0x19c0976f590D67707E62397C87829d896Dc0f1F1;
address public constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address public constant BOT_REGISTRY_ADDRESS = 0x637726f8b08a7ABE3aE3aCaB01A80E2d8ddeF77B;
Vat public constant vat = Vat(VAT_ADDRESS);
DaiJoin public constant daiJoin = DaiJoin(DAI_JOIN_ADDRESS);
Spotter public constant spotter = Spotter(SPOTTER_ADDRESS);
DefisaverLogger public constant logger = DefisaverLogger(0x5c55B921f590a89C1Ebe84dF170E655a82b62126);
/// @notice Repay - draws collateral, converts to Dai and repays the debt
/// @dev Must be called by the DSProxy contract that owns the CDP
function repay(
ExchangeData memory _exchangeData,
uint _cdpId,
uint _gasCost,
address _joinAddr,
ManagerType _managerType
) public payable {
address managerAddr = getManagerAddr(_managerType);
address user = getOwner(Manager(managerAddr), _cdpId);
bytes32 ilk = Manager(managerAddr).ilks(_cdpId);
drawCollateral(managerAddr, _cdpId, _joinAddr, _exchangeData.srcAmount);
_exchangeData.user = user;
_exchangeData.dfsFeeDivider = isAutomation() ? AUTOMATIC_SERVICE_FEE : MANUAL_SERVICE_FEE;
(, uint daiAmount) = _sell(_exchangeData);
daiAmount -= takeFee(_gasCost, daiAmount);
paybackDebt(managerAddr, _cdpId, ilk, daiAmount, user);
// if there is some eth left (0x fee), return it to user
if (address(this).balance > 0) {
tx.origin.transfer(address(this).balance);
}
logger.Log(address(this), msg.sender, "MCDRepay", abi.encode(_cdpId, user, _exchangeData.srcAmount, daiAmount));
}
/// @notice Boost - draws Dai, converts to collateral and adds to CDP
/// @dev Must be called by the DSProxy contract that owns the CDP
function boost(
ExchangeData memory _exchangeData,
uint _cdpId,
uint _gasCost,
address _joinAddr,
ManagerType _managerType
) public payable {
address managerAddr = getManagerAddr(_managerType);
address user = getOwner(Manager(managerAddr), _cdpId);
bytes32 ilk = Manager(managerAddr).ilks(_cdpId);
uint daiDrawn = drawDai(managerAddr, _cdpId, ilk, _exchangeData.srcAmount);
_exchangeData.user = user;
_exchangeData.dfsFeeDivider = isAutomation() ? AUTOMATIC_SERVICE_FEE : MANUAL_SERVICE_FEE;
_exchangeData.srcAmount = daiDrawn - takeFee(_gasCost, daiDrawn);
(, uint swapedColl) = _sell(_exchangeData);
addCollateral(managerAddr, _cdpId, _joinAddr, swapedColl);
// if there is some eth left (0x fee), return it to user
if (address(this).balance > 0) {
tx.origin.transfer(address(this).balance);
}
logger.Log(address(this), msg.sender, "MCDBoost", abi.encode(_cdpId, user, _exchangeData.srcAmount, swapedColl));
}
/// @notice Draws Dai from the CDP
/// @dev If _daiAmount is bigger than max available we'll draw max
/// @param _managerAddr Address of the CDP Manager
/// @param _cdpId Id of the CDP
/// @param _ilk Ilk of the CDP
/// @param _daiAmount Amount of Dai to draw
function drawDai(address _managerAddr, uint _cdpId, bytes32 _ilk, uint _daiAmount) internal returns (uint) {
uint rate = Jug(JUG_ADDRESS).drip(_ilk);
uint daiVatBalance = vat.dai(Manager(_managerAddr).urns(_cdpId));
uint maxAmount = getMaxDebt(_managerAddr, _cdpId, _ilk);
if (_daiAmount >= maxAmount) {
_daiAmount = sub(maxAmount, 1);
}
Manager(_managerAddr).frob(_cdpId, int(0), normalizeDrawAmount(_daiAmount, rate, daiVatBalance));
Manager(_managerAddr).move(_cdpId, address(this), toRad(_daiAmount));
if (vat.can(address(this), address(DAI_JOIN_ADDRESS)) == 0) {
vat.hope(DAI_JOIN_ADDRESS);
}
DaiJoin(DAI_JOIN_ADDRESS).exit(address(this), _daiAmount);
return _daiAmount;
}
/// @notice Adds collateral to the CDP
/// @param _managerAddr Address of the CDP Manager
/// @param _cdpId Id of the CDP
/// @param _joinAddr Address of the join contract for the CDP collateral
/// @param _amount Amount of collateral to add
function addCollateral(address _managerAddr, uint _cdpId, address _joinAddr, uint _amount) internal {
int convertAmount = 0;
if (isEthJoinAddr(_joinAddr)) {
Join(_joinAddr).gem().deposit{value: _amount}();
convertAmount = toPositiveInt(_amount);
} else {
convertAmount = toPositiveInt(convertTo18(_joinAddr, _amount));
}
ERC20(address(Join(_joinAddr).gem())).safeApprove(_joinAddr, _amount);
Join(_joinAddr).join(address(this), _amount);
vat.frob(
Manager(_managerAddr).ilks(_cdpId),
Manager(_managerAddr).urns(_cdpId),
address(this),
address(this),
convertAmount,
0
);
}
/// @notice Draws collateral and returns it to DSProxy
/// @param _managerAddr Address of the CDP Manager
/// @dev If _amount is bigger than max available we'll draw max
/// @param _cdpId Id of the CDP
/// @param _joinAddr Address of the join contract for the CDP collateral
/// @param _amount Amount of collateral to draw
function drawCollateral(address _managerAddr, uint _cdpId, address _joinAddr, uint _amount) internal returns (uint) {
uint frobAmount = _amount;
if (Join(_joinAddr).dec() != 18) {
frobAmount = _amount * (10 ** (18 - Join(_joinAddr).dec()));
}
Manager(_managerAddr).frob(_cdpId, -toPositiveInt(frobAmount), 0);
Manager(_managerAddr).flux(_cdpId, address(this), frobAmount);
Join(_joinAddr).exit(address(this), _amount);
if (isEthJoinAddr(_joinAddr)) {
Join(_joinAddr).gem().withdraw(_amount); // Weth -> Eth
}
return _amount;
}
/// @notice Paybacks Dai debt
/// @param _managerAddr Address of the CDP Manager
/// @dev If the _daiAmount is bigger than the whole debt, returns extra Dai
/// @param _cdpId Id of the CDP
/// @param _ilk Ilk of the CDP
/// @param _daiAmount Amount of Dai to payback
/// @param _owner Address that owns the DSProxy that owns the CDP
function paybackDebt(address _managerAddr, uint _cdpId, bytes32 _ilk, uint _daiAmount, address _owner) internal {
address urn = Manager(_managerAddr).urns(_cdpId);
uint wholeDebt = getAllDebt(VAT_ADDRESS, urn, urn, _ilk);
if (_daiAmount > wholeDebt) {
ERC20(DAI_ADDRESS).transfer(_owner, sub(_daiAmount, wholeDebt));
_daiAmount = wholeDebt;
}
if (ERC20(DAI_ADDRESS).allowance(address(this), DAI_JOIN_ADDRESS) == 0) {
ERC20(DAI_ADDRESS).approve(DAI_JOIN_ADDRESS, uint(-1));
}
daiJoin.join(urn, _daiAmount);
Manager(_managerAddr).frob(_cdpId, 0, normalizePaybackAmount(VAT_ADDRESS, urn, _ilk));
}
/// @notice Gets the maximum amount of collateral available to draw
/// @param _managerAddr Address of the CDP Manager
/// @param _cdpId Id of the CDP
/// @param _ilk Ilk of the CDP
/// @param _joinAddr Joind address of collateral
/// @dev Substracts 10 wei to aviod rounding error later on
function getMaxCollateral(address _managerAddr, uint _cdpId, bytes32 _ilk, address _joinAddr) public view returns (uint) {
uint price = getPrice(_ilk);
(uint collateral, uint debt) = getCdpInfo(Manager(_managerAddr), _cdpId, _ilk);
(, uint mat) = Spotter(SPOTTER_ADDRESS).ilks(_ilk);
uint maxCollateral = sub(collateral, (div(mul(mat, debt), price)));
uint normalizeMaxCollateral = maxCollateral / (10 ** (18 - Join(_joinAddr).dec()));
// take one percent due to precision issues
return normalizeMaxCollateral * 99 / 100;
}
/// @notice Gets the maximum amount of debt available to generate
/// @param _managerAddr Address of the CDP Manager
/// @param _cdpId Id of the CDP
/// @param _ilk Ilk of the CDP
/// @dev Substracts 10 wei to aviod rounding error later on
function getMaxDebt(address _managerAddr, uint _cdpId, bytes32 _ilk) public virtual view returns (uint) {
uint price = getPrice(_ilk);
(, uint mat) = spotter.ilks(_ilk);
(uint collateral, uint debt) = getCdpInfo(Manager(_managerAddr), _cdpId, _ilk);
return sub(sub(div(mul(collateral, price), mat), debt), 10);
}
/// @notice Gets a price of the asset
/// @param _ilk Ilk of the CDP
function getPrice(bytes32 _ilk) public view returns (uint) {
(, uint mat) = spotter.ilks(_ilk);
(,,uint spot,,) = vat.ilks(_ilk);
return rmul(rmul(spot, spotter.par()), mat);
}
function isAutomation() internal view returns(bool) {
return BotRegistry(BOT_REGISTRY_ADDRESS).botList(tx.origin);
}
function takeFee(uint256 _gasCost, uint _amount) internal returns(uint) {
if (_gasCost > 0) {
uint ethDaiPrice = getPrice(ETH_ILK);
uint feeAmount = rmul(_gasCost, ethDaiPrice);
if (feeAmount > _amount / 10) {
feeAmount = _amount / 10;
}
ERC20(DAI_ADDRESS).transfer(WALLET_ID, feeAmount);
return feeAmount;
}
return 0;
}
} interface IFlashLoanReceiver {
function executeOperation(address _reserve, uint256 _amount, uint256 _fee, bytes calldata _params) external;
}
abstract contract ILendingPoolAddressesProvider {
function getLendingPool() public view virtual returns (address);
function setLendingPoolImpl(address _pool) public virtual;
function getLendingPoolCore() public virtual view returns (address payable);
function setLendingPoolCoreImpl(address _lendingPoolCore) public virtual;
function getLendingPoolConfigurator() public virtual view returns (address);
function setLendingPoolConfiguratorImpl(address _configurator) public virtual;
function getLendingPoolDataProvider() public virtual view returns (address);
function setLendingPoolDataProviderImpl(address _provider) public virtual;
function getLendingPoolParametersProvider() public virtual view returns (address);
function setLendingPoolParametersProviderImpl(address _parametersProvider) public virtual;
function getTokenDistributor() public virtual view returns (address);
function setTokenDistributor(address _tokenDistributor) public virtual;
function getFeeProvider() public virtual view returns (address);
function setFeeProviderImpl(address _feeProvider) public virtual;
function getLendingPoolLiquidationManager() public virtual view returns (address);
function setLendingPoolLiquidationManager(address _manager) public virtual;
function getLendingPoolManager() public virtual view returns (address);
function setLendingPoolManager(address _lendingPoolManager) public virtual;
function getPriceOracle() public virtual view returns (address);
function setPriceOracle(address _priceOracle) public virtual;
function getLendingRateOracle() public view virtual returns (address);
function setLendingRateOracle(address _lendingRateOracle) public virtual;
}
library EthAddressLib {
function ethAddress() internal pure returns(address) {
return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
}
}
abstract contract FlashLoanReceiverBase is IFlashLoanReceiver {
using SafeERC20 for ERC20;
using SafeMath for uint256;
ILendingPoolAddressesProvider public addressesProvider;
constructor(ILendingPoolAddressesProvider _provider) public {
addressesProvider = _provider;
}
receive () external virtual payable {}
function transferFundsBackToPoolInternal(address _reserve, uint256 _amount) internal {
address payable core = addressesProvider.getLendingPoolCore();
transferInternal(core,_reserve, _amount);
}
function transferInternal(address payable _destination, address _reserve, uint256 _amount) internal {
if(_reserve == EthAddressLib.ethAddress()) {
//solium-disable-next-line
_destination.call{value: _amount}("");
return;
}
ERC20(_reserve).safeTransfer(_destination, _amount);
}
function getBalanceInternal(address _target, address _reserve) internal view returns(uint256) {
if(_reserve == EthAddressLib.ethAddress()) {
return _target.balance;
}
return ERC20(_reserve).balanceOf(_target);
}
} abstract contract ILendingPool {
function flashLoan( address payable _receiver, address _reserve, uint _amount, bytes calldata _params) external virtual;
function deposit(address _reserve, uint256 _amount, uint16 _referralCode) external virtual payable;
function setUserUseReserveAsCollateral(address _reserve, bool _useAsCollateral) external virtual;
function borrow(address _reserve, uint256 _amount, uint256 _interestRateMode, uint16 _referralCode) external virtual;
function repay( address _reserve, uint256 _amount, address payable _onBehalfOf) external virtual payable;
function swapBorrowRateMode(address _reserve) external virtual;
function getReserves() external virtual view returns(address[] memory);
/// @param _reserve underlying token address
function getReserveData(address _reserve)
external virtual
view
returns (
uint256 totalLiquidity, // reserve total liquidity
uint256 availableLiquidity, // reserve available liquidity for borrowing
uint256 totalBorrowsStable, // total amount of outstanding borrows at Stable rate
uint256 totalBorrowsVariable, // total amount of outstanding borrows at Variable rate
uint256 liquidityRate, // current deposit APY of the reserve for depositors, in Ray units.
uint256 variableBorrowRate, // current variable rate APY of the reserve pool, in Ray units.
uint256 stableBorrowRate, // current stable rate APY of the reserve pool, in Ray units.
uint256 averageStableBorrowRate, // current average stable borrow rate
uint256 utilizationRate, // expressed as total borrows/total liquidity.
uint256 liquidityIndex, // cumulative liquidity index
uint256 variableBorrowIndex, // cumulative variable borrow index
address aTokenAddress, // aTokens contract address for the specific _reserve
uint40 lastUpdateTimestamp // timestamp of the last update of reserve data
);
/// @param _user users address
function getUserAccountData(address _user)
external virtual
view
returns (
uint256 totalLiquidityETH, // user aggregated deposits across all the reserves. In Wei
uint256 totalCollateralETH, // user aggregated collateral across all the reserves. In Wei
uint256 totalBorrowsETH, // user aggregated outstanding borrows across all the reserves. In Wei
uint256 totalFeesETH, // user aggregated current outstanding fees in ETH. In Wei
uint256 availableBorrowsETH, // user available amount to borrow in ETH
uint256 currentLiquidationThreshold, // user current average liquidation threshold across all the collaterals deposited
uint256 ltv, // user average Loan-to-Value between all the collaterals
uint256 healthFactor // user current Health Factor
);
/// @param _reserve underlying token address
/// @param _user users address
function getUserReserveData(address _reserve, address _user)
external virtual
view
returns (
uint256 currentATokenBalance, // user current reserve aToken balance
uint256 currentBorrowBalance, // user current reserve outstanding borrow balance
uint256 principalBorrowBalance, // user balance of borrowed asset
uint256 borrowRateMode, // user borrow rate mode either Stable or Variable
uint256 borrowRate, // user current borrow rate APY
uint256 liquidityRate, // user current earn rate on _reserve
uint256 originationFee, // user outstanding loan origination fee
uint256 variableBorrowIndex, // user variable cumulative index
uint256 lastUpdateTimestamp, // Timestamp of the last data update
bool usageAsCollateralEnabled // Whether the user's current reserve is enabled as a collateral
);
function getReserveConfigurationData(address _reserve)
external virtual
view
returns (
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus,
address rateStrategyAddress,
bool usageAsCollateralEnabled,
bool borrowingEnabled,
bool stableBorrowRateEnabled,
bool isActive
);
// ------------------ LendingPoolCoreData ------------------------
function getReserveATokenAddress(address _reserve) public virtual view returns (address);
function getReserveConfiguration(address _reserve)
external virtual
view
returns (uint256, uint256, uint256, bool);
function getUserUnderlyingAssetBalance(address _reserve, address _user)
public virtual
view
returns (uint256);
function getReserveCurrentLiquidityRate(address _reserve)
public virtual
view
returns (uint256);
function getReserveCurrentVariableBorrowRate(address _reserve)
public virtual
view
returns (uint256);
function getReserveCurrentStableBorrowRate(address _reserve)
public virtual
view
returns (uint256);
function getReserveTotalLiquidity(address _reserve)
public virtual
view
returns (uint256);
function getReserveAvailableLiquidity(address _reserve)
public virtual
view
returns (uint256);
function getReserveTotalBorrowsVariable(address _reserve)
public virtual
view
returns (uint256);
function getReserveTotalBorrowsStable(address _reserve)
public virtual
view
returns (uint256);
// ---------------- LendingPoolDataProvider ---------------------
function calculateUserGlobalData(address _user)
public virtual
view
returns (
uint256 totalLiquidityBalanceETH,
uint256 totalCollateralBalanceETH,
uint256 totalBorrowBalanceETH,
uint256 totalFeesETH,
uint256 currentLtv,
uint256 currentLiquidationThreshold,
uint256 healthFactor,
bool healthFactorBelowThreshold
);
}
abstract contract IMCDSubscriptions {
function unsubscribe(uint256 _cdpId) external virtual ;
function subscribersPos(uint256 _cdpId) external virtual returns (uint256, bool);
}
contract MCDCloseTaker is MCDSaverProxyHelper {
address public constant SUBSCRIPTION_ADDRESS_NEW = 0xC45d4f6B6bf41b6EdAA58B01c4298B8d9078269a;
address public constant DEFISAVER_LOGGER = 0x5c55B921f590a89C1Ebe84dF170E655a82b62126;
ILendingPool public constant lendingPool = ILendingPool(0x398eC7346DcD622eDc5ae82352F02bE94C62d119);
address public constant SPOTTER_ADDRESS = 0x65C79fcB50Ca1594B025960e539eD7A9a6D434A3;
address public constant VAT_ADDRESS = 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B;
address public constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
// solhint-disable-next-line const-name-snakecase
DefisaverLogger public constant logger = DefisaverLogger(DEFISAVER_LOGGER);
struct CloseData {
uint cdpId;
address joinAddr;
uint collAmount;
uint daiAmount;
uint minAccepted;
bool wholeDebt;
bool toDai;
ManagerType managerType;
}
Vat public constant vat = Vat(VAT_ADDRESS);
Spotter public constant spotter = Spotter(SPOTTER_ADDRESS);
function closeWithLoan(
DFSExchangeData.ExchangeData memory _exchangeData,
CloseData memory _closeData,
address payable mcdCloseFlashLoan
) public payable {
mcdCloseFlashLoan.transfer(msg.value); // 0x fee
address managerAddr = getManagerAddr(_closeData.managerType);
if (_closeData.wholeDebt) {
_closeData.daiAmount = getAllDebt(
VAT_ADDRESS,
Manager(managerAddr).urns(_closeData.cdpId),
Manager(managerAddr).urns(_closeData.cdpId),
Manager(managerAddr).ilks(_closeData.cdpId)
);
(_closeData.collAmount, )
= getCdpInfo(Manager(managerAddr), _closeData.cdpId, Manager(managerAddr).ilks(_closeData.cdpId));
}
Manager(managerAddr).cdpAllow(_closeData.cdpId, mcdCloseFlashLoan, 1);
bytes memory packedData = _packData(_closeData, _exchangeData);
bytes memory paramsData = abi.encode(address(this), packedData);
lendingPool.flashLoan(mcdCloseFlashLoan, DAI_ADDRESS, _closeData.daiAmount, paramsData);
Manager(managerAddr).cdpAllow(_closeData.cdpId, mcdCloseFlashLoan, 0);
// If sub. to automatic protection unsubscribe
unsubscribe(SUBSCRIPTION_ADDRESS_NEW, _closeData.cdpId);
logger.Log(address(this), msg.sender, "MCDClose", abi.encode(_closeData.cdpId, _closeData.collAmount, _closeData.daiAmount, _closeData.toDai));
}
/// @notice Gets the maximum amount of debt available to generate
/// @param _managerAddr Address of the CDP Manager
/// @param _cdpId Id of the CDP
/// @param _ilk Ilk of the CDP
function getMaxDebt(address _managerAddr, uint256 _cdpId, bytes32 _ilk) public view returns (uint256) {
uint256 price = getPrice(_ilk);
(, uint256 mat) = spotter.ilks(_ilk);
(uint256 collateral, uint256 debt) = getCdpInfo(Manager(_managerAddr), _cdpId, _ilk);
return sub(wdiv(wmul(collateral, price), mat), debt);
}
/// @notice Gets a price of the asset
/// @param _ilk Ilk of the CDP
function getPrice(bytes32 _ilk) public view returns (uint256) {
(, uint256 mat) = spotter.ilks(_ilk);
(, , uint256 spot, , ) = vat.ilks(_ilk);
return rmul(rmul(spot, spotter.par()), mat);
}
function unsubscribe(address _subContract, uint _cdpId) internal {
(, bool isSubscribed) = IMCDSubscriptions(_subContract).subscribersPos(_cdpId);
if (isSubscribed) {
IMCDSubscriptions(_subContract).unsubscribe(_cdpId);
}
}
function _packData(
CloseData memory _closeData,
DFSExchangeData.ExchangeData memory _exchangeData
) internal pure returns (bytes memory) {
return abi.encode(_closeData, _exchangeData);
}
}
contract MCDCloseFlashLoan is DFSExchangeCore, MCDSaverProxyHelper, FlashLoanReceiverBase, AdminAuth {
ILendingPoolAddressesProvider public LENDING_POOL_ADDRESS_PROVIDER = ILendingPoolAddressesProvider(0x24a42fD28C976A61Df5D00D0599C34c4f90748c8);
uint public constant SERVICE_FEE = 400; // 0.25% Fee
bytes32 internal constant ETH_ILK = 0x4554482d41000000000000000000000000000000000000000000000000000000;
address public constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address public constant DAI_JOIN_ADDRESS = 0x9759A6Ac90977b93B58547b4A71c78317f391A28;
address public constant SPOTTER_ADDRESS = 0x65C79fcB50Ca1594B025960e539eD7A9a6D434A3;
address public constant VAT_ADDRESS = 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B;
DaiJoin public constant daiJoin = DaiJoin(DAI_JOIN_ADDRESS);
Spotter public constant spotter = Spotter(SPOTTER_ADDRESS);
Vat public constant vat = Vat(VAT_ADDRESS);
struct CloseData {
uint cdpId;
uint collAmount;
uint daiAmount;
uint minAccepted;
address joinAddr;
address proxy;
uint flFee;
bool toDai;
address reserve;
uint amount;
}
constructor() FlashLoanReceiverBase(LENDING_POOL_ADDRESS_PROVIDER) public {}
function executeOperation(
address _reserve,
uint256 _amount,
uint256 _fee,
bytes calldata _params)
external override {
(address proxy, bytes memory packedData) = abi.decode(_params, (address,bytes));
(MCDCloseTaker.CloseData memory closeDataSent, ExchangeData memory exchangeData) = abi.decode(packedData, (MCDCloseTaker.CloseData,ExchangeData));
CloseData memory closeData = CloseData({
cdpId: closeDataSent.cdpId,
collAmount: closeDataSent.collAmount,
daiAmount: closeDataSent.daiAmount,
minAccepted: closeDataSent.minAccepted,
joinAddr: closeDataSent.joinAddr,
proxy: proxy,
flFee: _fee,
toDai: closeDataSent.toDai,
reserve: _reserve,
amount: _amount
});
address user = DSProxy(payable(closeData.proxy)).owner();
exchangeData.dfsFeeDivider = SERVICE_FEE;
exchangeData.user = user;
address managerAddr = getManagerAddr(closeDataSent.managerType);
closeCDP(closeData, exchangeData, user, managerAddr);
}
function closeCDP(
CloseData memory _closeData,
ExchangeData memory _exchangeData,
address _user,
address _managerAddr
) internal {
paybackDebt(_managerAddr, _closeData.cdpId, Manager(_managerAddr).ilks(_closeData.cdpId), _closeData.daiAmount); // payback whole debt
uint drawnAmount = drawMaxCollateral(_managerAddr, _closeData.cdpId, _closeData.joinAddr, _closeData.collAmount); // draw whole collateral
uint daiSwaped = 0;
if (_closeData.toDai) {
_exchangeData.srcAmount = drawnAmount;
(, daiSwaped) = _sell(_exchangeData);
} else {
_exchangeData.destAmount = (_closeData.daiAmount + _closeData.flFee);
(, daiSwaped) = _buy(_exchangeData);
}
address tokenAddr = getVaultCollAddr(_closeData.joinAddr);
if (_closeData.toDai) {
tokenAddr = DAI_ADDRESS;
}
require(getBalance(tokenAddr) >= _closeData.minAccepted, "Below min. number of eth specified");
transferFundsBackToPoolInternal(_closeData.reserve, _closeData.amount.add(_closeData.flFee));
sendLeftover(tokenAddr, DAI_ADDRESS, payable(_user));
}
function drawMaxCollateral(address _managerAddr, uint _cdpId, address _joinAddr, uint _amount) internal returns (uint) {
Manager(_managerAddr).frob(_cdpId, -toPositiveInt(_amount), 0);
Manager(_managerAddr).flux(_cdpId, address(this), _amount);
uint joinAmount = _amount;
if (Join(_joinAddr).dec() != 18) {
joinAmount = _amount / (10 ** (18 - Join(_joinAddr).dec()));
}
Join(_joinAddr).exit(address(this), joinAmount);
if (isEthJoinAddr(_joinAddr)) {
Join(_joinAddr).gem().withdraw(joinAmount); // Weth -> Eth
}
return joinAmount;
}
function paybackDebt(address _managerAddr, uint _cdpId, bytes32 _ilk, uint _daiAmount) internal {
address urn = Manager(_managerAddr).urns(_cdpId);
daiJoin.dai().approve(DAI_JOIN_ADDRESS, _daiAmount);
daiJoin.join(urn, _daiAmount);
Manager(_managerAddr).frob(_cdpId, 0, normalizePaybackAmount(VAT_ADDRESS, urn, _ilk));
}
function getVaultCollAddr(address _joinAddr) internal view returns (address) {
address tokenAddr = address(Join(_joinAddr).gem());
if (tokenAddr == EXCHANGE_WETH_ADDRESS) {
return KYBER_ETH_ADDRESS;
}
return tokenAddr;
}
function getPrice(bytes32 _ilk) public view returns (uint256) {
(, uint256 mat) = spotter.ilks(_ilk);
(, , uint256 spot, , ) = vat.ilks(_ilk);
return rmul(rmul(spot, spotter.par()), mat);
}
receive() external override(FlashLoanReceiverBase, DFSExchangeCore) payable {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DAI_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DAI_JOIN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISCOUNT_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_DEST_AMOUNT_MISSING","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_NOT_ZEROX_EXCHANGE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_OFFCHAIN_DATA_INVALID","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_SLIPPAGE_HIT","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_WRAPPER_INVALID","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXCHANGE_WETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KYBER_ETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LENDING_POOL_ADDRESS_PROVIDER","outputs":[{"internalType":"contract ILendingPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SAVER_EXCHANGE_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SERVICE_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SPOTTER_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAT_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WALLET_ID","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZRX_ALLOWLIST_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"addressesProvider","outputs":[{"internalType":"contract ILendingPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"daiJoin","outputs":[{"internalType":"contract DaiJoin","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_reserve","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"bytes","name":"_params","type":"bytes"}],"name":"executeOperation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Manager","name":"_manager","type":"address"},{"internalType":"uint256","name":"_cdpId","type":"uint256"},{"internalType":"bytes32","name":"_ilk","type":"bytes32"}],"name":"getCdpInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum MCDSaverProxyHelper.ManagerType","name":"_managerType","type":"uint8"}],"name":"getManagerAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract Manager","name":"_manager","type":"address"},{"internalType":"uint256","name":"_cdpId","type":"uint256"}],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_ilk","type":"bytes32"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"srcAddr","type":"address"},{"internalType":"address","name":"destAddr","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"dfsFeeDivider","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"bytes","name":"wrapperData","type":"bytes"},{"components":[{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"address","name":"exchangeAddr","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct DFSExchangeData.OffchainData","name":"offchainData","type":"tuple"}],"internalType":"struct DFSExchangeData.ExchangeData","name":"_exData","type":"tuple"}],"name":"packExchangeData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdminByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdminByOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwnerByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"spotter","outputs":[{"internalType":"contract Spotter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"unpackExchangeData","outputs":[{"components":[{"internalType":"address","name":"srcAddr","type":"address"},{"internalType":"address","name":"destAddr","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"dfsFeeDivider","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"bytes","name":"wrapperData","type":"bytes"},{"components":[{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"address","name":"exchangeAddr","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct DFSExchangeData.OffchainData","name":"offchainData","type":"tuple"}],"internalType":"struct DFSExchangeData.ExchangeData","name":"_exData","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"vat","outputs":[{"internalType":"contract Vat","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawStuckFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6080604052600380546001600160a01b0319167324a42fd28c976a61df5d00d0599c34c4f90748c817905534801561003657600080fd5b50600354600080546001600160a01b03199081166001600160a01b0390931692909217905560018054821633179055600280549091167325efa336886c74ea8e282ac466bdcd0199f85bb9179055613aea806100936000396000f3fe6080604052600436106102085760003560e01c806381b9428011610118578063c50ebaf8116100a0578063cfac57c71161006f578063cfac57c7146104bc578063d3661fa514610510578063deca5f8814610525578063ee87255814610545578063f851a440146105655761020f565b8063c50ebaf8146104d1578063c72c4d10146104e6578063cc694d48146104fb578063cf786f8f1461032f5761020f565b8063a3b8e5d1116100e7578063a3b8e5d114610445578063a46a66c914610472578063a7304bf714610487578063ae08fd10146104a7578063c11645bc146104bc5761020f565b806381b94280146103f15780638c8a7958146104065780638da5cb5b1461041b57806398ab3d49146104305761020f565b806331d98b3f1161019b57806341c0e1b51161016a57806341c0e1b514610392578063449b9ffa146103a75780634d93667e146103bc57806350c86de5146103dc5780636738929f146102b85761020f565b806331d98b3f1461030257806336569e771461032f5780633a128322146103445780634115fe6b146103645761020f565b80632a4c0a1a116101d75780632a4c0a1a146102a35780632e77468d146102b85780632f634a90146102cd578063314b6332146102ed5761020f565b806308d4f52a146102145780631e48907b1461024a578063278d58311461026c57806329f7fc9e146102815761020f565b3661020f57005b600080fd5b34801561022057600080fd5b5061023461022f3660046134e6565b61057a565b604051610241919061385f565b60405180910390f35b34801561025657600080fd5b5061026a6102653660046131ba565b6105a4565b005b34801561027857600080fd5b506102346105dd565b34801561028d57600080fd5b50610296610605565b60405161024191906137df565b3480156102af57600080fd5b5061029661061d565b3480156102c457600080fd5b50610296610635565b3480156102d957600080fd5b506102966102e8366004613240565b61064d565b3480156102f957600080fd5b50610296610749565b34801561030e57600080fd5b5061032261031d366004613348565b610761565b604051610241919061383f565b34801561033b57600080fd5b5061029661091f565b34801561035057600080fd5b5061026a61035f366004613240565b610937565b34801561037057600080fd5b5061038461037f3660046133ab565b6109d1565b604051610241929190613a06565b34801561039e57600080fd5b5061026a610bed565b3480156103b357600080fd5b50610234610c12565b3480156103c857600080fd5b506102966103d736600461340c565b610c44565b3480156103e857600080fd5b50610322610ca3565b3480156103fd57600080fd5b50610296610ca9565b34801561041257600080fd5b50610296610cc1565b34801561042757600080fd5b50610296610cd9565b34801561043c57600080fd5b50610296610ce8565b34801561045157600080fd5b50610465610460366004613378565b610cf7565b6040516102419190613992565b34801561047e57600080fd5b50610296610d13565b34801561049357600080fd5b5061026a6104a23660046131ba565b610d2b565b3480156104b357600080fd5b50610234610d64565b3480156104c857600080fd5b50610296610d95565b3480156104dd57600080fd5b50610234610dad565b3480156104f257600080fd5b50610296610ddc565b34801561050757600080fd5b50610234610deb565b34801561051c57600080fd5b50610296610e16565b34801561053157600080fd5b5061026a6105403660046131ba565b610e2e565b34801561055157600080fd5b5061026a61056036600461326b565b610e5b565b34801561057157600080fd5b50610296610fda565b60608160405160200161058d9190613992565b60405160208183030381529060405290505b919050565b6002546001600160a01b031633146105bb57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525081565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b736b175474e89094c44da98b954eedeac495271d0f81565b7365c79fcb50ca1594b025960e539ed7a9a6d434a381565b600080836001600160a01b0316638161b120846040518263ffffffff1660e01b815260040161067c919061383f565b60206040518083038186803b15801561069457600080fd5b505afa1580156106a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106cc91906131d6565b9050806001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561070757600080fd5b505afa15801561071b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073f91906131d6565b9150505b92915050565b7325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d81565b604051636cb1c69b60e11b815260009081907365c79fcb50ca1594b025960e539ed7a9a6d434a39063d9638d369061079d90869060040161383f565b604080518083038186803b1580156107b457600080fd5b505afa1580156107c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ec91906133df565b604051636cb1c69b60e11b8152909250600091507335d1b3f3d7966a1dfe207aa4514c12a259a0492b9063d9638d369061082a90879060040161383f565b60a06040518083038186803b15801561084257600080fd5b505afa158015610856573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087a9190613644565b505092505050610917610911827365c79fcb50ca1594b025960e539ed7a9a6d434a36001600160a01b031663495d32cb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108d457600080fd5b505afa1580156108e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090c9190613360565b610fe9565b83610fe9565b949350505050565b7335d1b3f3d7966a1dfe207aa4514c12a259a0492b81565b6001546001600160a01b0316331461094e57600080fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03831614156109b3576001546040516001600160a01b039091169082156108fc029083906000818181858888f193505050501580156109ad573d6000803e3d6000fd5b506109cd565b6001546109cd906001600160a01b0384811691168361102a565b5050565b6000806000856001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b158015610a0f57600080fd5b505afa158015610a23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4791906131d6565b90506000866001600160a01b0316632726b073876040518263ffffffff1660e01b8152600401610a77919061383f565b60206040518083038186803b158015610a8f57600080fd5b505afa158015610aa3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac791906131d6565b9050600080836001600160a01b0316632424be5c88856040518363ffffffff1660e01b8152600401610afa929190613848565b604080518083038186803b158015610b1157600080fd5b505afa158015610b25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b499190613621565b915091506000846001600160a01b031663d9638d36896040518263ffffffff1660e01b8152600401610b7b919061383f565b60a06040518083038186803b158015610b9357600080fd5b505afa158015610ba7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bcb9190613644565b50505091505082610bdc8383610fe9565b965096505050505050935093915050565b6001546001600160a01b03163314610c0457600080fd5b6001546001600160a01b0316ff5b6040518060400160405280601681526020017516995c9bde08195e18da185b99d9481a5b9d985b1a5960521b81525081565b600080826001811115610c5357fe5b1415610c745750735ef30b9986345249bc32d8928b7ee64de9435e3961059f565b6001826001811115610c8257fe5b141561059f5750733f30c2381cd8b917dd96eb2f1a4f96d91324bbed61059f565b61019081565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b734ba1f38427b33b8ab7bb0490200dae1f1c36823f81565b6001546001600160a01b031681565b6003546001600160a01b031681565b610cff612d5d565b8180602001905181019061074391906135ee565b731b14e8d511c9a4395425314f849bd737baf8208f81565b6002546001600160a01b03163314610d4257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6040518060400160405280601581526020017413d99998da185a5b8819185d18481a5b9d985b1a59605a1b81525081565b739759a6ac90977b93b58547b4a71c78317f391a2881565b604051806040016040528060138152602001724465737420616d6f756e74206d697373696e6760681b81525081565b6000546001600160a01b031681565b6040518060400160405280600f81526020016e15dc985c1c195c881a5b9d985b1a59608a1b81525081565b73322d58b9e75a6918f7e7849aee0ff09369977e0881565b6001546001600160a01b03163314610e4557600080fd5b6002546001600160a01b031615610d4257600080fd5b60006060610e6b838501856131f2565b91509150610e77612dd9565b610e7f612d5d565b82806020019051810190610e939190613428565b91509150610e9f612e1d565b6040518061014001604052808460000151815260200184604001518152602001846060015181526020018460800151815260200184602001516001600160a01b03168152602001866001600160a01b031681526020018981526020018460c00151151581526020018b6001600160a01b031681526020018a815250905060008160a001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f5b57600080fd5b505afa158015610f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9391906131d6565b61019060a08501526001600160a01b03811660c085015260e0850151909150600090610fbe90610c44565b9050610fcc83858484611085565b505050505050505050505050565b6002546001600160a01b031681565b60006b033b2e3c9fd0803ce800000061101b611005858561122a565b60026b033b2e3c9fd0803ce80000005b0461124e565b8161102257fe5b049392505050565b6110808363a9059cbb60e01b84846040516024016110499291906137f3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261125e565b505050565b8351604051632c2cb9fd60e01b81526111139183916001600160a01b03831690632c2cb9fd906110b990849060040161383f565b60206040518083038186803b1580156110d157600080fd5b505afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111099190613360565b87604001516112ed565b600061112d8286600001518760800151886020015161155b565b905060008560e0015115611154576040850182905261114b85611873565b91506111719050565b60c0860151604087015101606086015261116d85611bba565b9150505b60006111808760800151611f69565b90508660e00151156111a35750736b175474e89094c44da98b954eedeac495271d0f5b86606001516111b182612021565b10156111d85760405162461bcd60e51b81526004016111cf90613872565b60405180910390fd5b6112028761010001516111fd8960c001518a61012001516120cb90919063ffffffff16565b6120f7565b61122181736b175474e89094c44da98b954eedeac495271d0f8761218b565b50505050505050565b60008115806112455750508082028282828161124257fe5b04145b61074357600080fd5b8082018281101561074357600080fd5b60606112b3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122269092919063ffffffff16565b80519091501561108057808060200190518101906112d191906132fc565b6110805760405162461bcd60e51b81526004016111cf90613922565b604051632726b07360e01b81526000906001600160a01b03861690632726b0739061131c90879060040161383f565b60206040518083038186803b15801561133457600080fd5b505afa158015611348573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136c91906131d6565b9050739759a6ac90977b93b58547b4a71c78317f391a286001600160a01b031663f4b9fa756040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156113bd57600080fd5b505af11580156113d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f591906131d6565b6001600160a01b031663095ea7b3739759a6ac90977b93b58547b4a71c78317f391a28846040518363ffffffff1660e01b81526004016114369291906137f3565b600060405180830381600087803b15801561145057600080fd5b505af1158015611464573d6000803e3d6000fd5b5050604051633b4da69f60e01b8152739759a6ac90977b93b58547b4a71c78317f391a289250633b4da69f91506114a190849086906004016137f3565b600060405180830381600087803b1580156114bb57600080fd5b505af11580156114cf573d6000803e3d6000fd5b50505050846001600160a01b03166345e6bdcd8560006115047335d1b3f3d7966a1dfe207aa4514c12a259a0492b8689612235565b6040518463ffffffff1660e01b8152600401611522939291906139f0565b600060405180830381600087803b15801561153c57600080fd5b505af1158015611550573d6000803e3d6000fd5b505050505050505050565b6000846001600160a01b03166345e6bdcd85611576856123f9565b60000360006040518463ffffffff1660e01b8152600401611599939291906139f0565b600060405180830381600087803b1580156115b357600080fd5b505af11580156115c7573d6000803e3d6000fd5b50506040516313771f0760e31b81526001600160a01b0388169250639bb8f83891506115fb908790309087906004016139d1565b600060405180830381600087803b15801561161557600080fd5b505af1158015611629573d6000803e3d6000fd5b505050506000829050836001600160a01b031663b3bcfa826040518163ffffffff1660e01b815260040160206040518083038186803b15801561166b57600080fd5b505afa15801561167f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a39190613360565b60121461172d57836001600160a01b031663b3bcfa826040518163ffffffff1660e01b815260040160206040518083038186803b1580156116e357600080fd5b505afa1580156116f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171b9190613360565b601203600a0a838161172957fe5b0490505b60405163ef693bed60e01b81526001600160a01b0385169063ef693bed9061175b90309085906004016137f3565b600060405180830381600087803b15801561177557600080fd5b505af1158015611789573d6000803e3d6000fd5b505050506117968461241b565b1561186a57836001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b1580156117d457600080fd5b505afa1580156117e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180c91906131d6565b6001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b8152600401611837919061383f565b600060405180830381600087803b15801561185157600080fd5b505af1158015611865573d6000803e3d6000fd5b505050505b95945050505050565b600080600080600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b031686600001516001600160a01b0316141561192e5785516118b8906124f8565b6001600160a01b031686526040808701518151630d0e30db60e41b8152915173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29263d0e30db09291600480830192600092919082900301818588803b15801561191457600080fd5b505af1158015611928573d6000803e3d6000fd5b50505050505b61194a86604001518760c0015188600001518960a0015161253f565b60408701805191909103905261012086015160600151156119875761197086600061271f565b925090508015611987578561012001516020015192505b806119a15761199786600061291d565b91508560e0015192505b60006119c073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2612021565b1115611aa6576040516370a0823160e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d9082906370a0823190611a059030906004016137df565b602060405180830381600087803b158015611a1f57600080fd5b505af1158015611a33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a579190613360565b6040518263ffffffff1660e01b8152600401611a73919061383f565b600060405180830381600087803b158015611a8d57600080fd5b505af1158015611aa1573d6000803e3d6000fd5b505050505b60208601516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415611b4957611ae186608001518760400151612b5f565b611afe73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee612021565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525090611b435760405162461bcd60e51b81526004016111cf919061385f565b50611baf565b611b5b86608001518760400151612b5f565b611b688760200151612021565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525090611bad5760405162461bcd60e51b81526004016111cf919061385f565b505b509092509050915091565b6000806000806000856060015160001415604051806040016040528060138152602001724465737420616d6f756e74206d697373696e6760681b81525090611c155760405162461bcd60e51b81526004016111cf919061385f565b50611c3286604001518760c0015188600001518960a0015161253f565b60408701805191909103905285516001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415611ce5578551611c6f906124f8565b6001600160a01b031686526040808701518151630d0e30db60e41b8152915173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29263d0e30db09291600480830192600092919082900301818588803b158015611ccb57600080fd5b505af1158015611cdf573d6000803e3d6000fd5b50505050505b6101208601516060015115611d1657611cff86600161271f565b925090508015611d16578561012001516020015192505b80611d5b57611d41611d3a611d3388606001518960800151612b87565b606961122a565b6064612ba7565b6040870152611d5186600161291d565b91508560e0015192505b6000611d7a73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2612021565b1115611e60576040516370a0823160e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d9082906370a0823190611dbf9030906004016137df565b602060405180830381600087803b158015611dd957600080fd5b505af1158015611ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e119190613360565b6040518263ffffffff1660e01b8152600401611e2d919061383f565b600060405180830381600087803b158015611e4757600080fd5b505af1158015611e5b573d6000803e3d6000fd5b505050505b60208601516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415611ef6578560600151611eab73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee612021565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525090611ef05760405162461bcd60e51b81526004016111cf919061385f565b50611f4f565b8560600151611f088760200151612021565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525090611f4d5760405162461bcd60e51b81526004016111cf919061385f565b505b82611f5d8760200151612021565b94509450505050915091565b600080826001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015611fa557600080fd5b505afa158015611fb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fdd91906131d6565b90506001600160a01b03811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214156107435773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee91505061059f565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561204f57504761059f565b6040516370a0823160e01b81526001600160a01b038316906370a082319061207b9030906004016137df565b60206040518083038186803b15801561209357600080fd5b505afa1580156120a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107439190613360565b6000828201838110156120f05760405162461bcd60e51b81526004016111cf906138b4565b9392505050565b60008060009054906101000a90046001600160a01b03166001600160a01b031663ed6ff7606040518163ffffffff1660e01b815260040160206040518083038186803b15801561214657600080fd5b505afa15801561215a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217e91906131d6565b9050611080818484612bb2565b47156121c8576040516001600160a01b038216904780156108fc02916000818181858888f193505050501580156121c6573d6000803e3d6000fd5b505b60006121d384612021565b11156121f7576121f7816121e685612021565b6001600160a01b038616919061102a565b600061220283612021565b1115611080576110808161221584612021565b6001600160a01b038516919061102a565b60606109178484600085612c48565b600080846001600160a01b0316636c25b346856040518263ffffffff1660e01b815260040161226491906137df565b60206040518083038186803b15801561227c57600080fd5b505afa158015612290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b49190613360565b90506000856001600160a01b031663d9638d36856040518263ffffffff1660e01b81526004016122e4919061383f565b60a06040518083038186803b1580156122fc57600080fd5b505afa158015612310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123349190613644565b5050509150506000866001600160a01b0316632424be5c86886040518363ffffffff1660e01b815260040161236a929190613848565b604080518083038186803b15801561238157600080fd5b505afa158015612395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b99190613621565b9150506123ce8284816123c857fe5b046123f9565b9350808411156123e9576123e1816123f9565b6000036123ee565b836000035b979650505050505050565b80600081121561059f5760405162461bcd60e51b81526004016111cf9061396c565b6000739759a6ac90977b93b58547b4a71c78317f391a286001600160a01b038316141561244a5750600061059f565b816001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b15801561248357600080fd5b505afa158015612497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124bb91906131d6565b6001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031614156124f05750600161059f565b506000919050565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146125245781610743565b5073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2919050565b600081158015906125d25750604051632cdc77ab60e21b8152731b14e8d511c9a4395425314f849bd737baf8208f9063b371deac906125829087906004016137df565b60206040518083038186803b15801561259a57600080fd5b505afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d291906132fc565b1561266157604051636eeb543160e01b8152731b14e8d511c9a4395425314f849bd737baf8208f90636eeb54319061260e9087906004016137df565b60206040518083038186803b15801561262657600080fd5b505afa15801561263a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265e9190613360565b91505b8161266e57506000610917565b81858161267757fe5b049050600a850481111561268b5750600a84045b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156126f75760405173322d58b9e75a6918f7e7849aee0ff09369977e089082156108fc029083906000818181858888f193505050501580156126f1573d6000803e3d6000fd5b50610917565b6109176001600160a01b03841673322d58b9e75a6918f7e7849aee0ff09369977e088361102a565b610120820151602001516040516302f5cc7960e11b81526000918291734ba1f38427b33b8ab7bb0490200dae1f1c36823f916305eb98f29161276491906004016137df565b60206040518083038186803b15801561277c57600080fd5b505afa158015612790573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b491906132fc565b6127c357506000905080612916565b6101208401515160405163e0aa279760e01b81527325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d9163e0aa27979161280091906004016137df565b60206040518083038186803b15801561281857600080fd5b505afa15801561282c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285091906132fc565b61285f57506000905080612916565b6101208401515160408501518551612882926001600160a01b039091169161102a565b610120840151805160809091015160405163097396a160e31b81526001600160a01b0390921691634b9cb50891906128c090889088906004016139a5565b60408051808303818588803b1580156128d857600080fd5b505af11580156128ec573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612911919061331c565b915091505b9250929050565b60e082015160405163e0aa279760e01b81526000917325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d9163e0aa27979161295a916004016137df565b60206040518083038186803b15801561297257600080fd5b505afa158015612986573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129aa91906132fc565b6040518060400160405280600f81526020016e15dc985c1c195c881a5b9d985b1a59608a1b815250906129f05760405162461bcd60e51b81526004016111cf919061385f565b5060e083015160408401518451612a12926001600160a01b039091169161102a565b6000826001811115612a2057fe5b1415612ac6578260e001516001600160a01b0316635b6f36fc8460000151856020015186604001518761010001516040518563ffffffff1660e01b8152600401612a6d949392919061380c565b602060405180830381600087803b158015612a8757600080fd5b505af1158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190613360565b9050610743565b8260e001516001600160a01b0316633924db668460000151856020015186606001518761010001516040518563ffffffff1660e01b8152600401612b0d949392919061380c565b602060405180830381600087803b158015612b2757600080fd5b505af1158015612b3b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f09190613360565b6000670de0b6b3a764000061101b612b77858561122a565b6002670de0b6b3a7640000611015565b60008161101b612b9f85670de0b6b3a764000061122a565b600285611015565b600081838161102257fe5b612bba612d0c565b6001600160a01b0316826001600160a01b03161415612c3457826001600160a01b031681604051612bea906137dc565b60006040518083038185875af1925050503d8060008114612c27576040519150601f19603f3d011682016040523d82523d6000602084013e612c2c565b606091505b505050611080565b6110806001600160a01b038316848361102a565b6060612c5385612d24565b612c6f5760405162461bcd60e51b81526004016111cf906138eb565b60006060866001600160a01b03168587604051612c8c91906137c0565b60006040518083038185875af1925050503d8060008114612cc9576040519150601f19603f3d011682016040523d82523d6000602084013e612cce565b606091505b50915091508115612ce25791506109179050565b805115612cf25780518082602001fd5b8360405162461bcd60e51b81526004016111cf919061385f565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610917575050151592915050565b60405180610140016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160608152602001612dd4612e8d565b905290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529060e0820190612dd4565b6040518061014001604052806000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160001515815260200160006001600160a01b03168152602001600081525090565b6040518060c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001606081525090565b803561074381613a8f565b805161074381613a8f565b8051801515811461074357600080fd5b600082601f830112612f14578081fd5b8135612f27612f2282613a3b565b613a14565b9150808252836020828501011115612f3e57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112612f67578081fd5b8151612f75612f2282613a3b565b9150808252836020828501011115612f8c57600080fd5b612f9d816020840160208601613a5f565b5092915050565b805161074381613aa7565b6000610140808385031215612fc2578182fd5b612fcb81613a14565b915050612fd88383612ee9565b8152612fe78360208401612ee9565b602082015260408201516040820152606082015160608201526080820151608082015260a082015160a08201526130218360c08401612ee9565b60c08201526130338360e08401612ee9565b60e08201526101008083015167ffffffffffffffff8082111561305557600080fd5b61306186838701612f57565b8385015261012092508285015191508082111561307d57600080fd5b5061308a8582860161312e565b82840152505092915050565b600060c082840312156130a7578081fd5b6130b160c0613a14565b905081356130be81613a8f565b815260208201356130ce81613a8f565b602082015260408201356130e181613a8f565b80604083015250606082013560608201526080820135608082015260a082013567ffffffffffffffff81111561311657600080fd5b61312284828501612f04565b60a08301525092915050565b600060c0828403121561313f578081fd5b61314960c0613a14565b9050815161315681613a8f565b8152602082015161316681613a8f565b6020820152604082015161317981613a8f565b80604083015250606082015160608201526080820151608082015260a082015167ffffffffffffffff8111156131ae57600080fd5b61312284828501612f57565b6000602082840312156131cb578081fd5b81356120f081613a8f565b6000602082840312156131e7578081fd5b81516120f081613a8f565b60008060408385031215613204578081fd5b823561320f81613a8f565b9150602083013567ffffffffffffffff81111561322a578182fd5b61323685828601612f04565b9150509250929050565b60008060408385031215613252578182fd5b823561325d81613a8f565b946020939093013593505050565b600080600080600060808688031215613282578081fd5b853561328d81613a8f565b94506020860135935060408601359250606086013567ffffffffffffffff808211156132b7578283fd5b818801915088601f8301126132ca578283fd5b8135818111156132d8578384fd5b8960208285010111156132e9578384fd5b9699959850939650602001949392505050565b60006020828403121561330d578081fd5b815180151581146120f0578182fd5b6000806040838503121561332e578182fd5b6133388484612ef4565b9150602083015190509250929050565b600060208284031215613359578081fd5b5035919050565b600060208284031215613371578081fd5b5051919050565b600060208284031215613389578081fd5b813567ffffffffffffffff81111561339f578182fd5b61073f84828501612f04565b6000806000606084860312156133bf578081fd5b83356133ca81613a8f565b95602085013595506040909401359392505050565b600080604083850312156133f1578182fd5b82516133fc81613a8f565b6020939093015192949293505050565b60006020828403121561341d578081fd5b81356120f081613aa7565b60008082840361012081121561343c578283fd5b6101008082121561344b578384fd5b61345481613a14565b9150845182526134678660208701612ee9565b60208301526040850151604083015260608501516060830152608085015160808301526134978660a08701612ef4565b60a08301526134a98660c08701612ef4565b60c08301526134bb8660e08701612fa4565b60e083015284015190925067ffffffffffffffff8111156134da578182fd5b61323685828601612faf565b6000602082840312156134f7578081fd5b813567ffffffffffffffff8082111561350e578283fd5b8184019150610140808387031215613524578384fd5b61352d81613a14565b90506135398684612ede565b81526135488660208501612ede565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a08201526135828660c08501612ede565b60c08201526135948660e08501612ede565b60e082015261010080840135838111156135ac578586fd5b6135b888828701612f04565b82840152505061012080840135838111156135d1578586fd5b6135dd88828701613096565b918301919091525095945050505050565b6000602082840312156135ff578081fd5b815167ffffffffffffffff811115613615578182fd5b61073f84828501612faf565b60008060408385031215613633578182fd5b505080516020909101519092909150565b600080600080600060a0868803121561365b578283fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b6001600160a01b03169052565b600081518084526136a8816020860160208601613a5f565b601f01601f19169290920160200192915050565b60006101406136cc848451613683565b60208301516136de6020860182613683565b5060408301516040850152606083015160608501526080830151608085015260a083015160a085015260c083015161371960c0860182613683565b5060e083015161372c60e0860182613683565b5061010080840151828287015261374583870182613690565b925050506101208084015185830382870152613761838261376b565b9695505050505050565b600060018060a01b0380835116845280602084015116602085015280604084015116604085015250606082015160608401526080820151608084015260a082015160c060a085015261073f60c0850182613690565b600082516137d2818460208701613a5f565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061376190830184613690565b90815260200190565b9182526001600160a01b0316602082015260400190565b6000602082526120f06020830184613690565b60208082526022908201527f42656c6f77206d696e2e206e756d626572206f66206574682073706563696669604082015261195960f21b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600c908201526b696e742d6f766572666c6f7760a01b604082015260600190565b6000602082526120f060208301846136bc565b6000604082526139b860408301856136bc565b9050600283106139c457fe5b8260208301529392505050565b9283526001600160a01b03919091166020830152604082015260600190565b9283526020830191909152604082015260600190565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715613a3357600080fd5b604052919050565b600067ffffffffffffffff821115613a51578081fd5b50601f01601f191660200190565b60005b83811015613a7a578181015183820152602001613a62565b83811115613a89576000848401525b50505050565b6001600160a01b0381168114613aa457600080fd5b50565b60028110613aa457600080fdfea2646970667358221220ae5c0a93345d2902744b9dd637cd6ce74d9c233a15f9ca75cf839132f8befb0964736f6c634300060c0033
Deployed Bytecode
0x6080604052600436106102085760003560e01c806381b9428011610118578063c50ebaf8116100a0578063cfac57c71161006f578063cfac57c7146104bc578063d3661fa514610510578063deca5f8814610525578063ee87255814610545578063f851a440146105655761020f565b8063c50ebaf8146104d1578063c72c4d10146104e6578063cc694d48146104fb578063cf786f8f1461032f5761020f565b8063a3b8e5d1116100e7578063a3b8e5d114610445578063a46a66c914610472578063a7304bf714610487578063ae08fd10146104a7578063c11645bc146104bc5761020f565b806381b94280146103f15780638c8a7958146104065780638da5cb5b1461041b57806398ab3d49146104305761020f565b806331d98b3f1161019b57806341c0e1b51161016a57806341c0e1b514610392578063449b9ffa146103a75780634d93667e146103bc57806350c86de5146103dc5780636738929f146102b85761020f565b806331d98b3f1461030257806336569e771461032f5780633a128322146103445780634115fe6b146103645761020f565b80632a4c0a1a116101d75780632a4c0a1a146102a35780632e77468d146102b85780632f634a90146102cd578063314b6332146102ed5761020f565b806308d4f52a146102145780631e48907b1461024a578063278d58311461026c57806329f7fc9e146102815761020f565b3661020f57005b600080fd5b34801561022057600080fd5b5061023461022f3660046134e6565b61057a565b604051610241919061385f565b60405180910390f35b34801561025657600080fd5b5061026a6102653660046131ba565b6105a4565b005b34801561027857600080fd5b506102346105dd565b34801561028d57600080fd5b50610296610605565b60405161024191906137df565b3480156102af57600080fd5b5061029661061d565b3480156102c457600080fd5b50610296610635565b3480156102d957600080fd5b506102966102e8366004613240565b61064d565b3480156102f957600080fd5b50610296610749565b34801561030e57600080fd5b5061032261031d366004613348565b610761565b604051610241919061383f565b34801561033b57600080fd5b5061029661091f565b34801561035057600080fd5b5061026a61035f366004613240565b610937565b34801561037057600080fd5b5061038461037f3660046133ab565b6109d1565b604051610241929190613a06565b34801561039e57600080fd5b5061026a610bed565b3480156103b357600080fd5b50610234610c12565b3480156103c857600080fd5b506102966103d736600461340c565b610c44565b3480156103e857600080fd5b50610322610ca3565b3480156103fd57600080fd5b50610296610ca9565b34801561041257600080fd5b50610296610cc1565b34801561042757600080fd5b50610296610cd9565b34801561043c57600080fd5b50610296610ce8565b34801561045157600080fd5b50610465610460366004613378565b610cf7565b6040516102419190613992565b34801561047e57600080fd5b50610296610d13565b34801561049357600080fd5b5061026a6104a23660046131ba565b610d2b565b3480156104b357600080fd5b50610234610d64565b3480156104c857600080fd5b50610296610d95565b3480156104dd57600080fd5b50610234610dad565b3480156104f257600080fd5b50610296610ddc565b34801561050757600080fd5b50610234610deb565b34801561051c57600080fd5b50610296610e16565b34801561053157600080fd5b5061026a6105403660046131ba565b610e2e565b34801561055157600080fd5b5061026a61056036600461326b565b610e5b565b34801561057157600080fd5b50610296610fda565b60608160405160200161058d9190613992565b60405160208183030381529060405290505b919050565b6002546001600160a01b031633146105bb57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525081565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b736b175474e89094c44da98b954eedeac495271d0f81565b7365c79fcb50ca1594b025960e539ed7a9a6d434a381565b600080836001600160a01b0316638161b120846040518263ffffffff1660e01b815260040161067c919061383f565b60206040518083038186803b15801561069457600080fd5b505afa1580156106a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106cc91906131d6565b9050806001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561070757600080fd5b505afa15801561071b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073f91906131d6565b9150505b92915050565b7325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d81565b604051636cb1c69b60e11b815260009081907365c79fcb50ca1594b025960e539ed7a9a6d434a39063d9638d369061079d90869060040161383f565b604080518083038186803b1580156107b457600080fd5b505afa1580156107c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ec91906133df565b604051636cb1c69b60e11b8152909250600091507335d1b3f3d7966a1dfe207aa4514c12a259a0492b9063d9638d369061082a90879060040161383f565b60a06040518083038186803b15801561084257600080fd5b505afa158015610856573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087a9190613644565b505092505050610917610911827365c79fcb50ca1594b025960e539ed7a9a6d434a36001600160a01b031663495d32cb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108d457600080fd5b505afa1580156108e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090c9190613360565b610fe9565b83610fe9565b949350505050565b7335d1b3f3d7966a1dfe207aa4514c12a259a0492b81565b6001546001600160a01b0316331461094e57600080fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03831614156109b3576001546040516001600160a01b039091169082156108fc029083906000818181858888f193505050501580156109ad573d6000803e3d6000fd5b506109cd565b6001546109cd906001600160a01b0384811691168361102a565b5050565b6000806000856001600160a01b03166336569e776040518163ffffffff1660e01b815260040160206040518083038186803b158015610a0f57600080fd5b505afa158015610a23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4791906131d6565b90506000866001600160a01b0316632726b073876040518263ffffffff1660e01b8152600401610a77919061383f565b60206040518083038186803b158015610a8f57600080fd5b505afa158015610aa3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac791906131d6565b9050600080836001600160a01b0316632424be5c88856040518363ffffffff1660e01b8152600401610afa929190613848565b604080518083038186803b158015610b1157600080fd5b505afa158015610b25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b499190613621565b915091506000846001600160a01b031663d9638d36896040518263ffffffff1660e01b8152600401610b7b919061383f565b60a06040518083038186803b158015610b9357600080fd5b505afa158015610ba7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bcb9190613644565b50505091505082610bdc8383610fe9565b965096505050505050935093915050565b6001546001600160a01b03163314610c0457600080fd5b6001546001600160a01b0316ff5b6040518060400160405280601681526020017516995c9bde08195e18da185b99d9481a5b9d985b1a5960521b81525081565b600080826001811115610c5357fe5b1415610c745750735ef30b9986345249bc32d8928b7ee64de9435e3961059f565b6001826001811115610c8257fe5b141561059f5750733f30c2381cd8b917dd96eb2f1a4f96d91324bbed61059f565b61019081565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b734ba1f38427b33b8ab7bb0490200dae1f1c36823f81565b6001546001600160a01b031681565b6003546001600160a01b031681565b610cff612d5d565b8180602001905181019061074391906135ee565b731b14e8d511c9a4395425314f849bd737baf8208f81565b6002546001600160a01b03163314610d4257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6040518060400160405280601581526020017413d99998da185a5b8819185d18481a5b9d985b1a59605a1b81525081565b739759a6ac90977b93b58547b4a71c78317f391a2881565b604051806040016040528060138152602001724465737420616d6f756e74206d697373696e6760681b81525081565b6000546001600160a01b031681565b6040518060400160405280600f81526020016e15dc985c1c195c881a5b9d985b1a59608a1b81525081565b73322d58b9e75a6918f7e7849aee0ff09369977e0881565b6001546001600160a01b03163314610e4557600080fd5b6002546001600160a01b031615610d4257600080fd5b60006060610e6b838501856131f2565b91509150610e77612dd9565b610e7f612d5d565b82806020019051810190610e939190613428565b91509150610e9f612e1d565b6040518061014001604052808460000151815260200184604001518152602001846060015181526020018460800151815260200184602001516001600160a01b03168152602001866001600160a01b031681526020018981526020018460c00151151581526020018b6001600160a01b031681526020018a815250905060008160a001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f5b57600080fd5b505afa158015610f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9391906131d6565b61019060a08501526001600160a01b03811660c085015260e0850151909150600090610fbe90610c44565b9050610fcc83858484611085565b505050505050505050505050565b6002546001600160a01b031681565b60006b033b2e3c9fd0803ce800000061101b611005858561122a565b60026b033b2e3c9fd0803ce80000005b0461124e565b8161102257fe5b049392505050565b6110808363a9059cbb60e01b84846040516024016110499291906137f3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261125e565b505050565b8351604051632c2cb9fd60e01b81526111139183916001600160a01b03831690632c2cb9fd906110b990849060040161383f565b60206040518083038186803b1580156110d157600080fd5b505afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111099190613360565b87604001516112ed565b600061112d8286600001518760800151886020015161155b565b905060008560e0015115611154576040850182905261114b85611873565b91506111719050565b60c0860151604087015101606086015261116d85611bba565b9150505b60006111808760800151611f69565b90508660e00151156111a35750736b175474e89094c44da98b954eedeac495271d0f5b86606001516111b182612021565b10156111d85760405162461bcd60e51b81526004016111cf90613872565b60405180910390fd5b6112028761010001516111fd8960c001518a61012001516120cb90919063ffffffff16565b6120f7565b61122181736b175474e89094c44da98b954eedeac495271d0f8761218b565b50505050505050565b60008115806112455750508082028282828161124257fe5b04145b61074357600080fd5b8082018281101561074357600080fd5b60606112b3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122269092919063ffffffff16565b80519091501561108057808060200190518101906112d191906132fc565b6110805760405162461bcd60e51b81526004016111cf90613922565b604051632726b07360e01b81526000906001600160a01b03861690632726b0739061131c90879060040161383f565b60206040518083038186803b15801561133457600080fd5b505afa158015611348573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136c91906131d6565b9050739759a6ac90977b93b58547b4a71c78317f391a286001600160a01b031663f4b9fa756040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156113bd57600080fd5b505af11580156113d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f591906131d6565b6001600160a01b031663095ea7b3739759a6ac90977b93b58547b4a71c78317f391a28846040518363ffffffff1660e01b81526004016114369291906137f3565b600060405180830381600087803b15801561145057600080fd5b505af1158015611464573d6000803e3d6000fd5b5050604051633b4da69f60e01b8152739759a6ac90977b93b58547b4a71c78317f391a289250633b4da69f91506114a190849086906004016137f3565b600060405180830381600087803b1580156114bb57600080fd5b505af11580156114cf573d6000803e3d6000fd5b50505050846001600160a01b03166345e6bdcd8560006115047335d1b3f3d7966a1dfe207aa4514c12a259a0492b8689612235565b6040518463ffffffff1660e01b8152600401611522939291906139f0565b600060405180830381600087803b15801561153c57600080fd5b505af1158015611550573d6000803e3d6000fd5b505050505050505050565b6000846001600160a01b03166345e6bdcd85611576856123f9565b60000360006040518463ffffffff1660e01b8152600401611599939291906139f0565b600060405180830381600087803b1580156115b357600080fd5b505af11580156115c7573d6000803e3d6000fd5b50506040516313771f0760e31b81526001600160a01b0388169250639bb8f83891506115fb908790309087906004016139d1565b600060405180830381600087803b15801561161557600080fd5b505af1158015611629573d6000803e3d6000fd5b505050506000829050836001600160a01b031663b3bcfa826040518163ffffffff1660e01b815260040160206040518083038186803b15801561166b57600080fd5b505afa15801561167f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a39190613360565b60121461172d57836001600160a01b031663b3bcfa826040518163ffffffff1660e01b815260040160206040518083038186803b1580156116e357600080fd5b505afa1580156116f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061171b9190613360565b601203600a0a838161172957fe5b0490505b60405163ef693bed60e01b81526001600160a01b0385169063ef693bed9061175b90309085906004016137f3565b600060405180830381600087803b15801561177557600080fd5b505af1158015611789573d6000803e3d6000fd5b505050506117968461241b565b1561186a57836001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b1580156117d457600080fd5b505afa1580156117e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180c91906131d6565b6001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b8152600401611837919061383f565b600060405180830381600087803b15801561185157600080fd5b505af1158015611865573d6000803e3d6000fd5b505050505b95945050505050565b600080600080600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b031686600001516001600160a01b0316141561192e5785516118b8906124f8565b6001600160a01b031686526040808701518151630d0e30db60e41b8152915173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29263d0e30db09291600480830192600092919082900301818588803b15801561191457600080fd5b505af1158015611928573d6000803e3d6000fd5b50505050505b61194a86604001518760c0015188600001518960a0015161253f565b60408701805191909103905261012086015160600151156119875761197086600061271f565b925090508015611987578561012001516020015192505b806119a15761199786600061291d565b91508560e0015192505b60006119c073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2612021565b1115611aa6576040516370a0823160e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d9082906370a0823190611a059030906004016137df565b602060405180830381600087803b158015611a1f57600080fd5b505af1158015611a33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a579190613360565b6040518263ffffffff1660e01b8152600401611a73919061383f565b600060405180830381600087803b158015611a8d57600080fd5b505af1158015611aa1573d6000803e3d6000fd5b505050505b60208601516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415611b4957611ae186608001518760400151612b5f565b611afe73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee612021565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525090611b435760405162461bcd60e51b81526004016111cf919061385f565b50611baf565b611b5b86608001518760400151612b5f565b611b688760200151612021565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525090611bad5760405162461bcd60e51b81526004016111cf919061385f565b505b509092509050915091565b6000806000806000856060015160001415604051806040016040528060138152602001724465737420616d6f756e74206d697373696e6760681b81525090611c155760405162461bcd60e51b81526004016111cf919061385f565b50611c3286604001518760c0015188600001518960a0015161253f565b60408701805191909103905285516001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415611ce5578551611c6f906124f8565b6001600160a01b031686526040808701518151630d0e30db60e41b8152915173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29263d0e30db09291600480830192600092919082900301818588803b158015611ccb57600080fd5b505af1158015611cdf573d6000803e3d6000fd5b50505050505b6101208601516060015115611d1657611cff86600161271f565b925090508015611d16578561012001516020015192505b80611d5b57611d41611d3a611d3388606001518960800151612b87565b606961122a565b6064612ba7565b6040870152611d5186600161291d565b91508560e0015192505b6000611d7a73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2612021565b1115611e60576040516370a0823160e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d9082906370a0823190611dbf9030906004016137df565b602060405180830381600087803b158015611dd957600080fd5b505af1158015611ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e119190613360565b6040518263ffffffff1660e01b8152600401611e2d919061383f565b600060405180830381600087803b158015611e4757600080fd5b505af1158015611e5b573d6000803e3d6000fd5b505050505b60208601516001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415611ef6578560600151611eab73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee612021565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525090611ef05760405162461bcd60e51b81526004016111cf919061385f565b50611f4f565b8560600151611f088760200151612021565b10156040518060400160405280600c81526020016b14db1a5c1c1859d9481a1a5d60a21b81525090611f4d5760405162461bcd60e51b81526004016111cf919061385f565b505b82611f5d8760200151612021565b94509450505050915091565b600080826001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b158015611fa557600080fd5b505afa158015611fb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fdd91906131d6565b90506001600160a01b03811673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214156107435773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee91505061059f565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561204f57504761059f565b6040516370a0823160e01b81526001600160a01b038316906370a082319061207b9030906004016137df565b60206040518083038186803b15801561209357600080fd5b505afa1580156120a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107439190613360565b6000828201838110156120f05760405162461bcd60e51b81526004016111cf906138b4565b9392505050565b60008060009054906101000a90046001600160a01b03166001600160a01b031663ed6ff7606040518163ffffffff1660e01b815260040160206040518083038186803b15801561214657600080fd5b505afa15801561215a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217e91906131d6565b9050611080818484612bb2565b47156121c8576040516001600160a01b038216904780156108fc02916000818181858888f193505050501580156121c6573d6000803e3d6000fd5b505b60006121d384612021565b11156121f7576121f7816121e685612021565b6001600160a01b038616919061102a565b600061220283612021565b1115611080576110808161221584612021565b6001600160a01b038516919061102a565b60606109178484600085612c48565b600080846001600160a01b0316636c25b346856040518263ffffffff1660e01b815260040161226491906137df565b60206040518083038186803b15801561227c57600080fd5b505afa158015612290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b49190613360565b90506000856001600160a01b031663d9638d36856040518263ffffffff1660e01b81526004016122e4919061383f565b60a06040518083038186803b1580156122fc57600080fd5b505afa158015612310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123349190613644565b5050509150506000866001600160a01b0316632424be5c86886040518363ffffffff1660e01b815260040161236a929190613848565b604080518083038186803b15801561238157600080fd5b505afa158015612395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b99190613621565b9150506123ce8284816123c857fe5b046123f9565b9350808411156123e9576123e1816123f9565b6000036123ee565b836000035b979650505050505050565b80600081121561059f5760405162461bcd60e51b81526004016111cf9061396c565b6000739759a6ac90977b93b58547b4a71c78317f391a286001600160a01b038316141561244a5750600061059f565b816001600160a01b0316637bd2bea76040518163ffffffff1660e01b815260040160206040518083038186803b15801561248357600080fd5b505afa158015612497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124bb91906131d6565b6001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031614156124f05750600161059f565b506000919050565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146125245781610743565b5073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2919050565b600081158015906125d25750604051632cdc77ab60e21b8152731b14e8d511c9a4395425314f849bd737baf8208f9063b371deac906125829087906004016137df565b60206040518083038186803b15801561259a57600080fd5b505afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d291906132fc565b1561266157604051636eeb543160e01b8152731b14e8d511c9a4395425314f849bd737baf8208f90636eeb54319061260e9087906004016137df565b60206040518083038186803b15801561262657600080fd5b505afa15801561263a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265e9190613360565b91505b8161266e57506000610917565b81858161267757fe5b049050600a850481111561268b5750600a84045b6001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156126f75760405173322d58b9e75a6918f7e7849aee0ff09369977e089082156108fc029083906000818181858888f193505050501580156126f1573d6000803e3d6000fd5b50610917565b6109176001600160a01b03841673322d58b9e75a6918f7e7849aee0ff09369977e088361102a565b610120820151602001516040516302f5cc7960e11b81526000918291734ba1f38427b33b8ab7bb0490200dae1f1c36823f916305eb98f29161276491906004016137df565b60206040518083038186803b15801561277c57600080fd5b505afa158015612790573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b491906132fc565b6127c357506000905080612916565b6101208401515160405163e0aa279760e01b81527325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d9163e0aa27979161280091906004016137df565b60206040518083038186803b15801561281857600080fd5b505afa15801561282c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285091906132fc565b61285f57506000905080612916565b6101208401515160408501518551612882926001600160a01b039091169161102a565b610120840151805160809091015160405163097396a160e31b81526001600160a01b0390921691634b9cb50891906128c090889088906004016139a5565b60408051808303818588803b1580156128d857600080fd5b505af11580156128ec573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612911919061331c565b915091505b9250929050565b60e082015160405163e0aa279760e01b81526000917325dd3f51e0c3c3ff164ddc02a8e4d65bb9cbb12d9163e0aa27979161295a916004016137df565b60206040518083038186803b15801561297257600080fd5b505afa158015612986573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129aa91906132fc565b6040518060400160405280600f81526020016e15dc985c1c195c881a5b9d985b1a59608a1b815250906129f05760405162461bcd60e51b81526004016111cf919061385f565b5060e083015160408401518451612a12926001600160a01b039091169161102a565b6000826001811115612a2057fe5b1415612ac6578260e001516001600160a01b0316635b6f36fc8460000151856020015186604001518761010001516040518563ffffffff1660e01b8152600401612a6d949392919061380c565b602060405180830381600087803b158015612a8757600080fd5b505af1158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190613360565b9050610743565b8260e001516001600160a01b0316633924db668460000151856020015186606001518761010001516040518563ffffffff1660e01b8152600401612b0d949392919061380c565b602060405180830381600087803b158015612b2757600080fd5b505af1158015612b3b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f09190613360565b6000670de0b6b3a764000061101b612b77858561122a565b6002670de0b6b3a7640000611015565b60008161101b612b9f85670de0b6b3a764000061122a565b600285611015565b600081838161102257fe5b612bba612d0c565b6001600160a01b0316826001600160a01b03161415612c3457826001600160a01b031681604051612bea906137dc565b60006040518083038185875af1925050503d8060008114612c27576040519150601f19603f3d011682016040523d82523d6000602084013e612c2c565b606091505b505050611080565b6110806001600160a01b038316848361102a565b6060612c5385612d24565b612c6f5760405162461bcd60e51b81526004016111cf906138eb565b60006060866001600160a01b03168587604051612c8c91906137c0565b60006040518083038185875af1925050503d8060008114612cc9576040519150601f19603f3d011682016040523d82523d6000602084013e612cce565b606091505b50915091508115612ce25791506109179050565b805115612cf25780518082602001fd5b8360405162461bcd60e51b81526004016111cf919061385f565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610917575050151592915050565b60405180610140016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160608152602001612dd4612e8d565b905290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081018290529060e0820190612dd4565b6040518061014001604052806000815260200160008152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160001515815260200160006001600160a01b03168152602001600081525090565b6040518060c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001606081525090565b803561074381613a8f565b805161074381613a8f565b8051801515811461074357600080fd5b600082601f830112612f14578081fd5b8135612f27612f2282613a3b565b613a14565b9150808252836020828501011115612f3e57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112612f67578081fd5b8151612f75612f2282613a3b565b9150808252836020828501011115612f8c57600080fd5b612f9d816020840160208601613a5f565b5092915050565b805161074381613aa7565b6000610140808385031215612fc2578182fd5b612fcb81613a14565b915050612fd88383612ee9565b8152612fe78360208401612ee9565b602082015260408201516040820152606082015160608201526080820151608082015260a082015160a08201526130218360c08401612ee9565b60c08201526130338360e08401612ee9565b60e08201526101008083015167ffffffffffffffff8082111561305557600080fd5b61306186838701612f57565b8385015261012092508285015191508082111561307d57600080fd5b5061308a8582860161312e565b82840152505092915050565b600060c082840312156130a7578081fd5b6130b160c0613a14565b905081356130be81613a8f565b815260208201356130ce81613a8f565b602082015260408201356130e181613a8f565b80604083015250606082013560608201526080820135608082015260a082013567ffffffffffffffff81111561311657600080fd5b61312284828501612f04565b60a08301525092915050565b600060c0828403121561313f578081fd5b61314960c0613a14565b9050815161315681613a8f565b8152602082015161316681613a8f565b6020820152604082015161317981613a8f565b80604083015250606082015160608201526080820151608082015260a082015167ffffffffffffffff8111156131ae57600080fd5b61312284828501612f57565b6000602082840312156131cb578081fd5b81356120f081613a8f565b6000602082840312156131e7578081fd5b81516120f081613a8f565b60008060408385031215613204578081fd5b823561320f81613a8f565b9150602083013567ffffffffffffffff81111561322a578182fd5b61323685828601612f04565b9150509250929050565b60008060408385031215613252578182fd5b823561325d81613a8f565b946020939093013593505050565b600080600080600060808688031215613282578081fd5b853561328d81613a8f565b94506020860135935060408601359250606086013567ffffffffffffffff808211156132b7578283fd5b818801915088601f8301126132ca578283fd5b8135818111156132d8578384fd5b8960208285010111156132e9578384fd5b9699959850939650602001949392505050565b60006020828403121561330d578081fd5b815180151581146120f0578182fd5b6000806040838503121561332e578182fd5b6133388484612ef4565b9150602083015190509250929050565b600060208284031215613359578081fd5b5035919050565b600060208284031215613371578081fd5b5051919050565b600060208284031215613389578081fd5b813567ffffffffffffffff81111561339f578182fd5b61073f84828501612f04565b6000806000606084860312156133bf578081fd5b83356133ca81613a8f565b95602085013595506040909401359392505050565b600080604083850312156133f1578182fd5b82516133fc81613a8f565b6020939093015192949293505050565b60006020828403121561341d578081fd5b81356120f081613aa7565b60008082840361012081121561343c578283fd5b6101008082121561344b578384fd5b61345481613a14565b9150845182526134678660208701612ee9565b60208301526040850151604083015260608501516060830152608085015160808301526134978660a08701612ef4565b60a08301526134a98660c08701612ef4565b60c08301526134bb8660e08701612fa4565b60e083015284015190925067ffffffffffffffff8111156134da578182fd5b61323685828601612faf565b6000602082840312156134f7578081fd5b813567ffffffffffffffff8082111561350e578283fd5b8184019150610140808387031215613524578384fd5b61352d81613a14565b90506135398684612ede565b81526135488660208501612ede565b602082015260408301356040820152606083013560608201526080830135608082015260a083013560a08201526135828660c08501612ede565b60c08201526135948660e08501612ede565b60e082015261010080840135838111156135ac578586fd5b6135b888828701612f04565b82840152505061012080840135838111156135d1578586fd5b6135dd88828701613096565b918301919091525095945050505050565b6000602082840312156135ff578081fd5b815167ffffffffffffffff811115613615578182fd5b61073f84828501612faf565b60008060408385031215613633578182fd5b505080516020909101519092909150565b600080600080600060a0868803121561365b578283fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b6001600160a01b03169052565b600081518084526136a8816020860160208601613a5f565b601f01601f19169290920160200192915050565b60006101406136cc848451613683565b60208301516136de6020860182613683565b5060408301516040850152606083015160608501526080830151608085015260a083015160a085015260c083015161371960c0860182613683565b5060e083015161372c60e0860182613683565b5061010080840151828287015261374583870182613690565b925050506101208084015185830382870152613761838261376b565b9695505050505050565b600060018060a01b0380835116845280602084015116602085015280604084015116604085015250606082015160608401526080820151608084015260a082015160c060a085015261073f60c0850182613690565b600082516137d2818460208701613a5f565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061376190830184613690565b90815260200190565b9182526001600160a01b0316602082015260400190565b6000602082526120f06020830184613690565b60208082526022908201527f42656c6f77206d696e2e206e756d626572206f66206574682073706563696669604082015261195960f21b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600c908201526b696e742d6f766572666c6f7760a01b604082015260600190565b6000602082526120f060208301846136bc565b6000604082526139b860408301856136bc565b9050600283106139c457fe5b8260208301529392505050565b9283526001600160a01b03919091166020830152604082015260600190565b9283526020830191909152604082015260600190565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715613a3357600080fd5b604052919050565b600067ffffffffffffffff821115613a51578081fd5b50601f01601f191660200190565b60005b83811015613a7a578181015183820152602001613a62565b83811115613a89576000848401525b50505050565b6001600160a01b0381168114613aa457600080fd5b50565b60028110613aa457600080fdfea2646970667358221220ae5c0a93345d2902744b9dd637cd6ce74d9c233a15f9ca75cf839132f8befb0964736f6c634300060c0033
Deployed Bytecode Sourcemap
64683:5392:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28614:134;;;;;;;;;;-1:-1:-1;28614:134:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;24308:122;;;;;;;;;;-1:-1:-1;24308:122:0;;;;;:::i;:::-;;:::i;:::-;;33650:56;;;;;;;;;;;;;:::i;29072:86::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;65113:80::-;;;;;;;;;;;;;:::i;65538:58::-;;;;;;;;;;;;;:::i;15081:186::-;;;;;;;;;;-1:-1:-1;15081:186:0;;;;;:::i;:::-;;:::i;29449:92::-;;;;;;;;;;;;;:::i;69761:223::-;;;;;;;;;;-1:-1:-1;69761:223:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;65603:42::-;;;;;;;;;;;;;:::i;24603:285::-;;;;;;;;;;-1:-1:-1;24603:285:0;;;;;:::i;:::-;;:::i;14572:357::-;;;;;;;;;;-1:-1:-1;14572:357:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;24476:80::-;;;;;;;;;;;;;:::i;33859:72::-;;;;;;;;;;;;;:::i;15396:336::-;;;;;;;;;;-1:-1:-1;15396:336:0;;;;;:::i;:::-;;:::i;64942:38::-;;;;;;;;;;;;;:::i;29165:90::-;;;;;;;;;;;;;:::i;29550:87::-;;;;;;;;;;;;;:::i;23266:20::-;;;;;;;;;;;;;:::i;64791:142::-;;;;;;;;;;;;;:::i;28756:159::-;;;;;;;;;;-1:-1:-1;28756:159:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;29357:85::-;;;;;;;;;;;;;:::i;24087:122::-;;;;;;;;;;-1:-1:-1;24087:122:0;;;;;:::i;:::-;;:::i;28955:74::-;;;;;;;;;;;;;:::i;65472:59::-;;;;;;;;;;;;;:::i;33713:70::-;;;;;;;;;;;;;:::i;52646:54::-;;;;;;;;;;;;;:::i;33790:62::-;;;;;;;;;;;;;:::i;29264:86::-;;;;;;;;;;;;;:::i;23804:161::-;;;;;;;;;;-1:-1:-1;23804:161:0;;;;;:::i;:::-;;:::i;66011:1176::-;;;;;;;;;;-1:-1:-1;66011:1176:0;;;;;:::i;:::-;;:::i;23293:20::-;;;;;;;;;;;;;:::i;28614:134::-;28689:12;28732:7;28721:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;28714:26;;28614:134;;;;:::o;24308:122::-;24389:5;;-1:-1:-1;;;;;24389:5:0;24375:10;:19;24367:28;;;;;;24408:5;:14;;-1:-1:-1;;;;;;24408:14:0;-1:-1:-1;;;;;24408:14:0;;;;;;;;;;24308:122::o;33650:56::-;;;;;;;;;;;;;;-1:-1:-1;;;33650:56:0;;;;:::o;29072:86::-;29116:42;29072:86;:::o;65113:80::-;65151:42;65113:80;:::o;65538:58::-;65334:42;65538:58;:::o;15081:186::-;15151:7;15171:13;15203:8;-1:-1:-1;;;;;15203:13:0;;15217:6;15203:21;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15171:55;;15246:5;-1:-1:-1;;;;;15246:11:0;;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15239:20;;;15081:186;;;;;:::o;29449:92::-;29499:42;29449:92;:::o;69761:223::-;69852:18;;-1:-1:-1;;;69852:18:0;;69814:7;;;;65334:42;;69852:12;;:18;;69865:4;;69852:18;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69906:14;;-1:-1:-1;;;69906:14:0;;69834:36;;-1:-1:-1;69886:12:0;;-1:-1:-1;65421:42:0;;69906:8;;:14;;69915:4;;69906:14;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69881:39;;;;;;69940:36;69945:25;69950:4;65334:42;-1:-1:-1;;;;;69956:11:0;;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69945:4;:25::i;:::-;69972:3;69940:4;:36::i;:::-;69933:43;69761:223;-1:-1:-1;;;;69761:223:0:o;65603:42::-;65421;65603;:::o;24603:285::-;23362:5;;-1:-1:-1;;;;;23362:5:0;23371:10;23362:19;23354:28;;;;;;24703:42:::1;-1:-1:-1::0;;;;;24693:52:0;::::1;;24689:192;;;24770:5;::::0;24762:32:::1;::::0;-1:-1:-1;;;;;24770:5:0;;::::1;::::0;24762:32;::::1;;;::::0;24786:7;;24770:5:::1;24762:32:::0;24770:5;24762:32;24786:7;24770:5;24762:32;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;24689:192;;;24854:5;::::0;24827:42:::1;::::0;-1:-1:-1;;;;;24827:26:0;;::::1;::::0;24854:5:::1;24861:7:::0;24827:26:::1;:42::i;:::-;24603:285:::0;;:::o;14572:357::-;14658:4;14664;14681:11;14695:8;-1:-1:-1;;;;;14695:12:0;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14681:28;;14720:11;14734:8;-1:-1:-1;;;;;14734:13:0;;14748:6;14734:21;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14720:35;;14769:15;14786:9;14803:3;-1:-1:-1;;;;;14799:13:0;;14813:4;14819:3;14799:24;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14768:55;;;;14836:9;14856:3;-1:-1:-1;;;;;14852:13:0;;14866:4;14852:19;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14834:37;;;;;;14892:10;14904:16;14909:4;14915;14904;:16::i;:::-;14884:37;;;;;;;;;14572:357;;;;;;:::o;24476:80::-;23362:5;;-1:-1:-1;;;;;23362:5:0;23371:10;23362:19;23354:28;;;;;;24541:5:::1;::::0;-1:-1:-1;;;;;24541:5:0::1;24520:28;33859:72:::0;;;;;;;;;;;;;;-1:-1:-1;;;33859:72:0;;;;:::o;15396:336::-;15467:7;;15491:12;:31;;;;;;;;;15487:238;;;-1:-1:-1;15546:42:0;15539:49;;15487:238;15626:21;15610:12;:37;;;;;;;;;15606:119;;;-1:-1:-1;15671:42:0;15664:49;;64942:38;64977:3;64942:38;:::o;29165:90::-;29213:42;29165:90;:::o;29550:87::-;29595:42;29550:87;:::o;23266:20::-;;;-1:-1:-1;;;;;23266:20:0;;:::o;64791:142::-;;;-1:-1:-1;;;;;64791:142:0;;:::o;28756:159::-;28824:27;;:::i;:::-;28885:5;28874:33;;;;;;;;;;;;:::i;29357:85::-;29400:42;29357:85;:::o;24087:122::-;24168:5;;-1:-1:-1;;;;;24168:5:0;24154:10;:19;24146:28;;;;;;24187:5;:14;;-1:-1:-1;;;;;;24187:14:0;-1:-1:-1;;;;;24187:14:0;;;;;;;;;;24087:122::o;28955:74::-;;;;;;;;;;;;;;-1:-1:-1;;;28955:74:0;;;;:::o;65472:59::-;65243:42;65472:59;:::o;33713:70::-;;;;;;;;;;;;;;-1:-1:-1;;;33713:70:0;;;;:::o;52646:54::-;;;-1:-1:-1;;;;;52646:54:0;;:::o;33790:62::-;;;;;;;;;;;;;;-1:-1:-1;;;33790:62:0;;;;:::o;29264:86::-;29308:42;29264:86;:::o;23804:161::-;23885:5;;-1:-1:-1;;;;;23885:5:0;23871:10;:19;23863:28;;;;;;23910:5;;-1:-1:-1;;;;;23910:5:0;:19;23902:28;;;;;66011:1176;66184:13;66199:23;66226:36;;;;66237:7;66226:36;:::i;:::-;66183:79;;;;66276:44;;:::i;:::-;66322:32;;:::i;:::-;66369:10;66358:62;;;;;;;;;;;;:::i;:::-;66275:145;;;;66433:26;;:::i;:::-;66462:419;;;;;;;;66494:13;:19;;;66462:419;;;;66540:13;:24;;;66462:419;;;;66590:13;:23;;;66462:419;;;;66641:13;:25;;;66462:419;;;;66691:13;:22;;;-1:-1:-1;;;;;66462:419:0;;;;;66735:5;-1:-1:-1;;;;;66462:419:0;;;;;66762:4;66462:419;;;;66788:13;:19;;;66462:419;;;;;;66831:8;-1:-1:-1;;;;;66462:419:0;;;;;66862:7;66462:419;;;66433:448;;66894:12;66925:9;:15;;;-1:-1:-1;;;;;66909:39:0;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;64977:3;66963:26;;;:40;-1:-1:-1;;;;;67014:24:0;;:17;;;:24;67088:25;;;;66894:56;;-1:-1:-1;;;67073:41:0;;:14;:41::i;:::-;67051:63;;67127:52;67136:9;67147:12;67161:4;67167:11;67127:8;:52::i;:::-;66011:1176;;;;;;;;;;;;:::o;23293:20::-;;;-1:-1:-1;;;;;23293:20:0;;:::o;5375:122::-;5434:9;5230:6;5460:23;5464:9;5468:1;5471;5464:3;:9::i;:::-;5481:1;5230:6;5475:7;;5460:3;:23::i;:::-;:29;;;;;;;5375:122;-1:-1:-1;;;5375:122:0:o;21312:176::-;21394:86;21414:5;21444:23;;;21469:2;21473:5;21421:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;21421:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;21421:58:0;-1:-1:-1;;;;;;21421:58:0;;;;;;;;;;21394:19;:86::i;:::-;21312:176;;;:::o;67195:1237::-;67405:16;;67423:44;;-1:-1:-1;;;67423:44:0;;67379:111;;67391:12;;-1:-1:-1;;;;;67423:26:0;;;;;:44;;67405:16;;67423:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67469:10;:20;;;67379:11;:111::i;:::-;67523:16;67542:93;67560:12;67574:10;:16;;;67592:10;:19;;;67613:10;:21;;;67542:17;:93::i;:::-;67523:112;;67673:14;67708:10;:16;;;67704:288;;;67741:23;;;:37;;;67809:20;67741:13;67809:5;:20::i;:::-;67793:36;-1:-1:-1;67704:288:0;;-1:-1:-1;67704:288:0;;67913:16;;;;67890:20;;;;:39;67862:24;;;:68;67961:19;67862:13;67961:4;:19::i;:::-;67945:35;-1:-1:-1;;67704:288:0;68004:17;68024:37;68041:10;:19;;;68024:16;:37::i;:::-;68004:57;;68078:10;:16;;;68074:72;;;-1:-1:-1;65151:42:0;68074:72;68191:10;:22;;;68166:21;68177:9;68166:10;:21::i;:::-;:47;;68158:94;;;;-1:-1:-1;;;68158:94:0;;;;;;;:::i;:::-;;;;;;;;;68265:92;68297:10;:18;;;68317:39;68339:10;:16;;;68317:10;:17;;;:21;;:39;;;;:::i;:::-;68265:31;:92::i;:::-;68370:52;68383:9;65151:42;68415:5;68370:12;:52::i;:::-;67195:1237;;;;;;;:::o;4464:127::-;4522:9;4552:6;;;:30;;-1:-1:-1;;4567:5:0;;;4581:1;4576;4567:5;4576:1;4562:15;;;;;:20;4552:30;4544:39;;;;;4222:113;4315:5;;;4310:16;;;;4302:25;;;;;22781:419;22863:23;22889:69;22917:4;22889:69;;;;;;;;;;;;;;;;;22897:5;-1:-1:-1;;;;;22889:27:0;;;:69;;;;;:::i;:::-;22973:17;;22863:95;;-1:-1:-1;22973:21:0;22969:224;;23115:10;23104:30;;;;;;;;;;;;:::i;:::-;23096:85;;;;-1:-1:-1;;;23096:85:0;;;;;;;:::i;69102:365::-;69223:34;;-1:-1:-1;;;69223:34:0;;69209:11;;-1:-1:-1;;;;;69223:26:0;;;;;:34;;69250:6;;69223:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69209:48;;65243:42;-1:-1:-1;;;;;69270:11:0;;:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;69270:21:0;;65243:42;69310:10;69270:51;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69332:29:0;;-1:-1:-1;;;69332:29:0;;65243:42;;-1:-1:-1;69332:12:0;;-1:-1:-1;69332:29:0;;69345:3;;69350:10;;69332:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69382:12;-1:-1:-1;;;;;69374:26:0;;69401:6;69409:1;69412:46;65421:42;69448:3;69453:4;69412:22;:46::i;:::-;69374:85;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69102:365;;;;;:::o;68440:654::-;68553:4;68578:12;-1:-1:-1;;;;;68570:26:0;;68597:6;68606:22;68620:7;68606:13;:22::i;:::-;68605:23;;68630:1;68570:62;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;68643:58:0;;-1:-1:-1;;;68643:58:0;;-1:-1:-1;;;;;68643:26:0;;;-1:-1:-1;68643:26:0;;-1:-1:-1;68643:58:0;;68670:6;;68686:4;;68693:7;;68643:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68714:15;68732:7;68714:25;;68761:9;-1:-1:-1;;;;;68756:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68781:2;68756:27;68752:119;;68841:9;-1:-1:-1;;;;;68836:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68831:2;:26;68824:2;:34;68813:7;:46;;;;;;68800:59;;68752:119;68883:47;;-1:-1:-1;;;68883:47:0;;-1:-1:-1;;;;;68883:20:0;;;;;:47;;68912:4;;68919:10;;68883:47;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68947:24;68961:9;68947:13;:24::i;:::-;68943:114;;;68993:9;-1:-1:-1;;;;;68988:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;68988:30:0;;69019:10;68988:42;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68943:114;69076:10;68440:654;-1:-1:-1;;;;;68440:654:0:o;34202:1670::-;34263:7;34272:4;34291:15;34317:17;34345:12;29116:42;-1:-1:-1;;;;;34418:35:0;:6;:14;;;-1:-1:-1;;;;;34418:35:0;;34414:201;;;34501:14;;34487:29;;:13;:29::i;:::-;-1:-1:-1;;;;;34470:46:0;;;34584:16;;;;;34531:72;;-1:-1:-1;;;34531:72:0;;;;29213:42;;34531:45;;34584:16;34531:72;;;;;34470:14;;34531:72;;;;;;;34584:16;29213:42;34531:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34414:201;34647:75;34654:6;:16;;;34672:6;:11;;;34685:6;:14;;;34701:6;:20;;;34647:6;:75::i;:::-;34627:16;;;:95;;;;;;;;34802:19;;;;:25;;;:29;34798:228;;34874:34;34884:6;34892:15;34874:9;:34::i;:::-;34848:60;-1:-1:-1;34848:60:0;-1:-1:-1;34925:90:0;;;;34967:6;:19;;;:32;;;34957:42;;34925:90;35096:7;35091:129;;35135:34;35145:6;35153:15;35135:9;:34::i;:::-;35120:49;;35194:6;:14;;;35184:24;;35091:129;35336:1;35300:33;29213:42;35300:10;:33::i;:::-;:37;35296:212;;;35419:62;;-1:-1:-1;;;35419:62:0;;29213:42;;35354:46;;29213:42;;35419:47;;:62;;35475:4;;35419:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;35354:142;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35296:212;35524:15;;;;-1:-1:-1;;;;;35524:40:0;29213:42;35524:40;35520:302;;;35622:39;35627:6;:15;;;35644:6;:16;;;35622:4;:39::i;:::-;35589:29;29116:42;35589:10;:29::i;:::-;:72;;35663:16;;;;;;;;;;;;;-1:-1:-1;;;35663:16:0;;;35581:99;;;;;-1:-1:-1;;;35581:99:0;;;;;;;;:::i;:::-;;35520:302;;;35752:39;35757:6;:15;;;35774:6;:16;;;35752:4;:39::i;:::-;35721:27;35732:6;:15;;;35721:10;:27::i;:::-;:70;;35793:16;;;;;;;;;;;;;-1:-1:-1;;;35793:16:0;;;35713:97;;;;;-1:-1:-1;;;35713:97:0;;;;;;;;:::i;:::-;;35520:302;-1:-1:-1;35842:7:0;;-1:-1:-1;35851:12:0;-1:-1:-1;34202:1670:0;;;:::o;36140:1892::-;36200:7;36209:4;36228:15;36254:17;36282:12;36315:6;:17;;;36336:1;36315:22;;36339:23;;;;;;;;;;;;;-1:-1:-1;;;36339:23:0;;;36307:56;;;;;-1:-1:-1;;;36307:56:0;;;;;;;;:::i;:::-;;36396:75;36403:6;:16;;;36421:6;:11;;;36434:6;:14;;;36450:6;:20;;;36396:6;:75::i;:::-;36376:16;;;:95;;;;;;;;36532:14;;-1:-1:-1;;;;;36532:35:0;29116:42;36532:35;36528:201;;;36615:14;;36601:29;;:13;:29::i;:::-;-1:-1:-1;;;;;36584:46:0;;;36698:16;;;;;36645:72;;-1:-1:-1;;;36645:72:0;;;;29213:42;;36645:45;;36698:16;36645:72;;;;;36584:14;;36645:72;;;;;;;36698:16;29213:42;36645:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36528:201;36745:19;;;;:25;;;:29;36741:227;;36817:33;36827:6;36835:14;36817:9;:33::i;:::-;36791:59;-1:-1:-1;36791:59:0;-1:-1:-1;36867:90:0;;;;36909:6;:19;;;:32;;;36899:42;;36867:90;37038:7;37033:376;;37235:60;37239:50;37243:40;37248:6;:17;;;37267:6;:15;;;37243:4;:40::i;:::-;37285:3;37239;:50::i;:::-;37291:3;37235;:60::i;:::-;37216:16;;;:79;37325:33;37216:6;37343:14;37325:9;:33::i;:::-;37310:48;;37383:6;:14;;;37373:24;;37033:376;37525:1;37489:33;29213:42;37489:10;:33::i;:::-;:37;37485:212;;;37608:62;;-1:-1:-1;;;37608:62:0;;29213:42;;37543:46;;29213:42;;37608:47;;:62;;37664:4;;37608:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37543:142;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37485:212;37713:15;;;;-1:-1:-1;;;;;37713:40:0;29213:42;37713:40;37709:258;;;37811:6;:17;;;37778:29;29116:42;37778:10;:29::i;:::-;:50;;37830:16;;;;;;;;;;;;;-1:-1:-1;;;37830:16:0;;;37770:77;;;;;-1:-1:-1;;;37770:77:0;;;;;;;;:::i;:::-;;37709:258;;;37919:6;:17;;;37888:27;37899:6;:15;;;37888:10;:27::i;:::-;:48;;37938:16;;;;;;;;;;;;;-1:-1:-1;;;37938:16:0;;;37880:75;;;;;-1:-1:-1;;;37880:75:0;;;;;;;;:::i;:::-;;37709:258;37987:7;37996:27;38007:6;:15;;;37996:10;:27::i;:::-;37979:45;;;;;;;36140:1892;;;:::o;69475:278::-;69543:7;69563:17;69596:9;-1:-1:-1;;;;;69591:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;69563:50;-1:-1:-1;;;;;;69630:34:0;;29213:42;69630:34;69626:91;;;29116:42;69681:24;;;;;29830:275;29893:12;-1:-1:-1;;;;;29922:31:0;;29116:42;29922:31;29918:180;;;-1:-1:-1;29980:21:0;29918:180;;;30044:42;;-1:-1:-1;;;30044:42:0;;-1:-1:-1;;;;;30044:27:0;;;;;:42;;30080:4;;30044:42;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;19474:181::-;19532:7;19564:5;;;19588:6;;;;19580:46;;;;-1:-1:-1;;;19580:46:0;;;;;;;:::i;:::-;19646:1;19474:181;-1:-1:-1;;;19474:181:0:o;52871:220::-;52969:20;52992:17;;;;;;;;;-1:-1:-1;;;;;52992:17:0;-1:-1:-1;;;;;52992:36:0;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52969:61;;53043:40;53060:4;53065:8;53075:7;53043:16;:40::i;30113:502::-;30268:21;:25;30264:93;;30310:35;;-1:-1:-1;;;;;30310:12:0;;;30323:21;30310:35;;;;;;;;;30323:21;30310:12;:35;;;;;;;;;;;;;;;;;;;;;30264:93;30396:1;30373:20;30384:8;30373:10;:20::i;:::-;:24;30369:112;;;30414:55;30443:3;30448:20;30459:8;30448:10;:20::i;:::-;-1:-1:-1;;;;;30414:28:0;;;:55;:28;:55::i;:::-;30521:1;30497:21;30508:9;30497:10;:21::i;:::-;:25;30493:115;;;30539:57;30569:3;30574:21;30585:9;30574:10;:21::i;:::-;-1:-1:-1;;;;;30539:29:0;;;:57;:29;:57::i;17705:196::-;17808:12;17840:53;17863:6;17871:4;17877:1;17880:12;17840:22;:53::i;12545:382::-;12642:10;12665:8;12680:4;-1:-1:-1;;;;;12676:13:0;;12690:4;12676:19;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12665:30;;12711:9;12731:4;-1:-1:-1;;;;;12727:14:0;;12742:4;12727:20;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12708:39;;;;;;12761:8;12777:4;-1:-1:-1;;;;;12773:14:0;;12788:4;12794;12773:26;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12758:41;;;12821:25;12841:4;12835:3;:10;;;;;;12821:13;:25::i;:::-;12812:34;;12882:3;12871:6;12866:19;;:53;;12901:18;12915:3;12901:13;:18::i;:::-;12899:20;;12866:53;;;12890:6;12888:8;;12866:53;12857:62;12545:382;-1:-1:-1;;;;;;;12545:382:0:o;12220:134::-;12301:2;12275:5;12323:6;;;12315:31;;;;-1:-1:-1;;;12315:31:0;;;;;;;:::i;13963:436::-;14028:4;14127:42;-1:-1:-1;;;;;14114:55:0;;;14110:73;;;-1:-1:-1;14178:5:0;14171:12;;14110:73;14264:9;-1:-1:-1;;;;;14259:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;14251:76:0;14285:42;-1:-1:-1;;;;;14251:76:0;;14247:120;;;-1:-1:-1;14351:4:0;14344:11;;14247:120;-1:-1:-1;14386:5:0;13963:436;;;:::o;32548:151::-;32608:7;-1:-1:-1;;;;;32635:25:0;;29116:42;32635:25;:56;;32687:4;32635:56;;;-1:-1:-1;29213:42:0;;32548:151;-1:-1:-1;32548:151:0:o;30937:830::-;31043:17;31077:19;;;;;:71;;-1:-1:-1;31100:48:0;;-1:-1:-1;;;31100:48:0;;29400:42;;31100:41;;:48;;31142:5;;31100:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31073:174;;;31182:53;;-1:-1:-1;;;31182:53:0;;29400:42;;31182:46;;:53;;31229:5;;31182:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;31165:70;;31073:174;31263:19;31259:501;;-1:-1:-1;31311:1:0;31259:501;;;31367:14;31357:7;:24;;;;;;;-1:-1:-1;31483:2:0;31473:7;:12;31460:9;:26;31456:91;;;-1:-1:-1;31529:2:0;31519:12;;31456:91;-1:-1:-1;;;;;31567:27:0;;29116:42;31567:27;31563:186;;;31615:29;;29308:42;;31615:29;;;;;31634:9;;31615:29;;;;31634:9;29308:42;31615:29;;;;;;;;;;;;;;;;;;;;;31563:186;;;31685:48;-1:-1:-1;;;;;31685:26:0;;29308:42;31723:9;31685:26;:48::i;38163:692::-;38353:20;;;;:33;;;38310:77;;-1:-1:-1;;;38310:77:0;;38271:12;;;;29595:42;;38310;;:77;;38353:33;38310:77;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38305:128;;-1:-1:-1;38412:5:0;;-1:-1:-1;38412:5:0;38404:17;;38305:128;38507:20;;;;:28;38450:86;;-1:-1:-1;;;38450:86:0;;29499:42;;38450:56;;:86;;38507:28;38450:86;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38445:137;;-1:-1:-1;38561:5:0;;-1:-1:-1;38561:5:0;38553:17;;38445:137;38658:20;;;;:28;38688:17;;;;38628:15;;38622:84;;-1:-1:-1;;;;;38622:35:0;;;;;:84::i;:::-;38751:20;;;;:28;;38798:32;;;;;38726:121;;-1:-1:-1;;;38726:121:0;;-1:-1:-1;;;;;38726:64:0;;;;;;38798:32;38726:121;;38751:7;;38841:5;;38726:121;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38719:128;;;;38163:692;;;;;;:::o;39121:717::-;39300:15;;;;39243:73;;-1:-1:-1;;;39243:73:0;;39205:17;;29499:42;;39243:56;;:73;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39318:19;;;;;;;;;;;;;-1:-1:-1;;;39318:19:0;;;39235:103;;;;;-1:-1:-1;;;39235:103:0;;;;;;;;:::i;:::-;-1:-1:-1;39387:15:0;;;;39404:17;;;;39357:15;;39351:71;;-1:-1:-1;;;;;39351:35:0;;;;;:71::i;:::-;39448:15;39439:5;:24;;;;;;;;;39435:396;;;39515:7;:15;;;-1:-1:-1;;;;;39495:63:0;;39559:7;:15;;;39576:7;:16;;;39594:7;:17;;;39613:7;:19;;;39495:138;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39480:153;;39435:396;;;39701:7;:15;;;-1:-1:-1;;;;;39681:62:0;;39744:7;:15;;;39761:7;:16;;;39779:7;:18;;;39799:7;:19;;;39681:138;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;5245:122::-;5304:9;5194:6;5330:23;5334:9;5338:1;5341;5334:3;:9::i;:::-;5351:1;5194:6;5345:7;;5505:120;5564:9;5616:1;5590:23;5594:11;5598:1;5194:6;5594:3;:11::i;:::-;5611:1;5607;:5;;4599:100;4657:9;4690:1;4686;:5;;;;53099:355;53226:26;:24;:26::i;:::-;-1:-1:-1;;;;;53214:38:0;:8;-1:-1:-1;;;;;53214:38:0;;53211:168;;;53309:12;-1:-1:-1;;;;;53309:17:0;53334:7;53309:37;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53361:7;;53211:168;53391:51;-1:-1:-1;;;;;53391:28:0;;53420:12;53434:7;53391:28;:51::i;18467:979::-;18597:12;18630:18;18641:6;18630:10;:18::i;:::-;18622:60;;;;-1:-1:-1;;;18622:60:0;;;;;;;:::i;:::-;18756:12;18770:23;18797:6;-1:-1:-1;;;;;18797:11:0;18817:8;18828:4;18797:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18755:78;;;;18848:7;18844:595;;;18879:10;-1:-1:-1;18872:17:0;;-1:-1:-1;18872:17:0;18844:595;18993:17;;:21;18989:439;;19256:10;19250:17;19317:15;19304:10;19300:2;19296:19;19289:44;19204:148;19399:12;19392:20;;-1:-1:-1;;;19392:20:0;;;;;;;;:::i;52380:121::-;52451:42;52380:121;:::o;16492:619::-;16552:4;17020:20;;16863:66;17060:23;;;;;;:42;;-1:-1:-1;;17087:15:0;;;16492:619;-1:-1:-1;;16492:619:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130::-;72:20;;97:33;72:20;97:33;:::i;142:134::-;220:13;;238:33;220:13;238:33;:::i;593:128::-;668:13;;40881;;40874:21;44576:32;;44566:2;;44622:1;;44612:12;1365:440;;1466:3;1459:4;1451:6;1447:17;1443:27;1433:2;;-1:-1;;1474:12;1433:2;1521:6;1508:20;1543:64;1558:48;1599:6;1558:48;:::i;:::-;1543:64;:::i;:::-;1534:73;;1627:6;1620:5;1613:21;1731:3;1663:4;1722:6;1655;1713:16;;1710:25;1707:2;;;1748:1;;1738:12;1707:2;43689:6;1663:4;1655:6;1651:17;1663:4;1689:5;1685:16;43666:30;43745:1;43727:16;;;1663:4;43727:16;43720:27;1689:5;1426:379;-1:-1;;1426:379::o;1814:442::-;;1926:3;1919:4;1911:6;1907:17;1903:27;1893:2;;-1:-1;;1934:12;1893:2;1974:6;1968:13;1996:64;2011:48;2052:6;2011:48;:::i;1996:64::-;1987:73;;2080:6;2073:5;2066:21;2184:3;2116:4;2175:6;2108;2166:16;;2163:25;2160:2;;;2201:1;;2191:12;2160:2;2211:39;2243:6;2116:4;2142:5;2138:16;2116:4;2108:6;2104:17;2211:39;:::i;:::-;;1886:370;;;;:::o;2946:166::-;3040:13;;3058:49;3040:13;3058:49;:::i;6638:2005::-;;6768:6;;6756:9;6751:3;6747:19;6743:32;6740:2;;;-1:-1;;6778:12;6740:2;6806:22;6768:6;6806:22;:::i;:::-;6797:31;;;6913:60;6969:3;6945:22;6913:60;:::i;:::-;6895:16;6888:86;7072:60;7128:3;7039:2;7108:9;7104:22;7072:60;:::i;:::-;7039:2;7058:5;7054:16;7047:86;7199:2;7268:9;7264:22;11391:13;7199:2;7218:5;7214:16;7207:86;7360:2;7429:9;7425:22;11391:13;7360:2;7379:5;7375:16;7368:86;7519:3;7589:9;7585:22;11391:13;7519:3;7539:5;7535:16;7528:86;7684:3;7754:9;7750:22;11391:13;7684:3;7704:5;7700:16;7693:86;7874:60;7930:3;7840;7910:9;7906:22;7874:60;:::i;:::-;7840:3;7860:5;7856:16;7849:86;8033:60;8089:3;7999;8069:9;8065:22;8033:60;:::i;:::-;7999:3;8019:5;8015:16;8008:86;8183:3;;8172:9;8168:19;8162:26;8208:18;;8200:6;8197:30;8194:2;;;6881:1;;8230:12;8194:2;8277:69;8342:3;8333:6;8322:9;8318:22;8277:69;:::i;:::-;8183:3;8261:5;8257:18;8250:97;8437:3;;;;8426:9;8422:19;8416:26;8402:40;;8208:18;8454:6;8451:30;8448:2;;;6881:1;;8484:12;8448:2;;8531:90;8617:3;8608:6;8597:9;8593:22;8531:90;:::i;:::-;8437:3;8515:5;8511:18;8504:118;;;6734:1909;;;;:::o;8692:1179::-;;8811:4;8799:9;8794:3;8790:19;8786:30;8783:2;;;-1:-1;;8819:12;8783:2;8847:20;8811:4;8847:20;:::i;:::-;8838:29;;85:6;72:20;97:33;124:5;97:33;:::i;:::-;8927:75;;9071:2;9125:22;;72:20;97:33;72:20;97:33;:::i;:::-;9071:2;9086:16;;9079:75;9226:2;9280:22;;72:20;97:33;72:20;97:33;:::i;:::-;9259:49;9226:2;9245:5;9241:16;9234:75;;9371:2;9429:9;9425:22;11243:20;9371:2;9390:5;9386:16;9379:75;9522:3;9581:9;9577:22;11243:20;9522:3;9542:5;9538:16;9531:75;9699:3;9688:9;9684:19;9671:33;9724:18;9716:6;9713:30;9710:2;;;-1:-1;;9746:12;9710:2;9791:58;9845:3;9836:6;9825:9;9821:22;9791:58;:::i;:::-;9699:3;9777:5;9773:16;9766:84;;8777:1094;;;;:::o;9920:1249::-;;10050:4;10038:9;10033:3;10029:19;10025:30;10022:2;;;-1:-1;;10058:12;10022:2;10086:20;10050:4;10086:20;:::i;:::-;10077:29;;226:6;220:13;238:33;265:5;238:33;:::i;:::-;10166:86;;10321:2;10386:22;;220:13;238:33;220:13;238:33;:::i;:::-;10321:2;10336:16;;10329:86;10487:2;10552:22;;220:13;238:33;220:13;238:33;:::i;:::-;10520:60;10487:2;10506:5;10502:16;10495:86;;10643:2;10712:9;10708:22;11391:13;10643:2;10662:5;10658:16;10651:86;10805:3;10875:9;10871:22;11391:13;10805:3;10825:5;10821:16;10814:86;10986:3;10975:9;10971:19;10965:26;11011:18;11003:6;11000:30;10997:2;;;-1:-1;;11033:12;10997:2;11078:69;11143:3;11134:6;11123:9;11119:22;11078:69;:::i;11454:241::-;;11558:2;11546:9;11537:7;11533:23;11529:32;11526:2;;;-1:-1;;11564:12;11526:2;85:6;72:20;97:33;124:5;97:33;:::i;11702:263::-;;11817:2;11805:9;11796:7;11792:23;11788:32;11785:2;;;-1:-1;;11823:12;11785:2;226:6;220:13;238:33;265:5;238:33;:::i;12258:486::-;;;12396:2;12384:9;12375:7;12371:23;12367:32;12364:2;;;-1:-1;;12402:12;12364:2;371:6;358:20;383:41;418:5;383:41;:::i;:::-;12454:71;-1:-1;12590:2;12575:18;;12562:32;12614:18;12603:30;;12600:2;;;-1:-1;;12636:12;12600:2;12666:62;12720:7;12711:6;12700:9;12696:22;12666:62;:::i;:::-;12656:72;;;12358:386;;;;;:::o;12751:366::-;;;12872:2;12860:9;12851:7;12847:23;12843:32;12840:2;;;-1:-1;;12878:12;12840:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;12930:63;13030:2;13069:22;;;;11243:20;;-1:-1;;;12834:283::o;13124:741::-;;;;;;13298:3;13286:9;13277:7;13273:23;13269:33;13266:2;;;-1:-1;;13305:12;13266:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;13357:63;-1:-1;13457:2;13496:22;;11243:20;;-1:-1;13565:2;13604:22;;11243:20;;-1:-1;13701:2;13686:18;;13673:32;13725:18;13714:30;;;13711:2;;;-1:-1;;13747:12;13711:2;13832:6;13821:9;13817:22;;;1134:3;1127:4;1119:6;1115:17;1111:27;1101:2;;-1:-1;;1142:12;1101:2;1185:6;1172:20;13725:18;1204:6;1201:30;1198:2;;;-1:-1;;1234:12;1198:2;1329:3;13457:2;1309:17;1270:6;1295:32;;1292:41;1289:2;;;-1:-1;;1336:12;1289:2;13260:605;;;;-1:-1;13260:605;;-1:-1;13457:2;1266:17;;13767:82;13260:605;-1:-1;;;13260:605::o;13872:257::-;;13984:2;13972:9;13963:7;13959:23;13955:32;13952:2;;;-1:-1;;13990:12;13952:2;674:6;668:13;44601:5;40881:13;40874:21;44579:5;44576:32;44566:2;;-1:-1;;44612:12;14136:393;;;14265:2;14253:9;14244:7;14240:23;14236:32;14233:2;;;-1:-1;;14271:12;14233:2;14333:61;14386:7;14362:22;14333:61;:::i;:::-;14323:71;;14431:2;14485:9;14481:22;11391:13;14439:74;;14227:302;;;;;:::o;14536:241::-;;14640:2;14628:9;14619:7;14615:23;14611:32;14608:2;;;-1:-1;;14646:12;14608:2;-1:-1;795:20;;14602:175;-1:-1;14602:175::o;14784:263::-;;14899:2;14887:9;14878:7;14874:23;14870:32;14867:2;;;-1:-1;;14905:12;14867:2;-1:-1;943:13;;14861:186;-1:-1;14861:186::o;15054:345::-;;15167:2;15155:9;15146:7;15142:23;15138:32;15135:2;;;-1:-1;;15173:12;15135:2;15231:17;15218:31;15269:18;15261:6;15258:30;15255:2;;;-1:-1;;15291:12;15255:2;15321:62;15375:7;15366:6;15355:9;15351:22;15321:62;:::i;16103:523::-;;;;16257:2;16245:9;16236:7;16232:23;16228:32;16225:2;;;-1:-1;;16263:12;16225:2;2523:6;2510:20;2535:49;2578:5;2535:49;:::i;:::-;16315:79;16431:2;16470:22;;11243:20;;-1:-1;16539:2;16578:22;;;795:20;;16219:407;-1:-1;;;16219:407::o;16633:439::-;;;16785:2;16773:9;16764:7;16760:23;16756:32;16753:2;;;-1:-1;;16791:12;16753:2;2700:6;2694:13;2712:53;2759:5;2712:53;:::i;:::-;16974:2;17024:22;;;;11391:13;16843:94;;11391:13;;-1:-1;;;16747:325::o;17079:273::-;;17199:2;17187:9;17178:7;17174:23;17170:32;17167:2;;;-1:-1;;17205:12;17167:2;2873:6;2860:20;2885:49;2928:5;2885:49;:::i;17359:594::-;;;17536:9;17527:7;17523:23;17548:3;17523:23;17519:33;17516:2;;;-1:-1;;17555:12;17516:2;3283:6;;3262:19;3258:32;3255:2;;;-1:-1;;3293:12;3255:2;3321:22;3283:6;3321:22;:::i;:::-;3312:31;;3458:22;11391:13;3408:16;3401:86;3585:60;3641:3;3552:2;3621:9;3617:22;3585:60;:::i;:::-;3552:2;3571:5;3567:16;3560:86;3713:2;3782:9;3778:22;11391:13;3713:2;3732:5;3728:16;3721:86;3873:2;3942:9;3938:22;11391:13;3873:2;3892:5;3888:16;3881:86;4035:3;4105:9;4101:22;11391:13;4035:3;4055:5;4051:16;4044:86;4230:57;4283:3;4196;4263:9;4259:22;4230:57;:::i;:::-;4196:3;4216:5;4212:16;4205:83;4384:57;4437:3;4350;4417:9;4413:22;4384:57;:::i;:::-;4350:3;4370:5;4366:16;4359:83;4544:76;4616:3;4510;4596:9;4592:22;4544:76;:::i;:::-;4510:3;4526:16;;4519:102;17751:19;;17745:26;4530:5;;-1:-1;17791:18;17780:30;;17777:2;;;-1:-1;;17813:12;17777:2;17843:94;17929:7;17920:6;17909:9;17905:22;17843:94;:::i;17960:387::-;;18094:2;18082:9;18073:7;18069:23;18065:32;18062:2;;;-1:-1;;18100:12;18062:2;18158:17;18145:31;18196:18;;18188:6;18185:30;18182:2;;;-1:-1;;18218:12;18182:2;18314:6;18303:9;18299:22;;;4810:6;;4798:9;4793:3;4789:19;4785:32;4782:2;;;-1:-1;;4820:12;4782:2;4848:22;4810:6;4848:22;:::i;:::-;4839:31;;4955:49;5000:3;4976:22;4955:49;:::i;:::-;4937:16;4930:75;5103:49;5148:3;18094:2;5128:9;5124:22;5103:49;:::i;:::-;18094:2;5089:5;5085:16;5078:75;5219:2;5277:9;5273:22;11243:20;5219:2;5238:5;5234:16;5227:75;5369:2;5427:9;5423:22;11243:20;5369:2;5388:5;5384:16;5377:75;5517:3;5576:9;5572:22;11243:20;5517:3;5537:5;5533:16;5526:75;5671:3;5730:9;5726:22;11243:20;5671:3;5691:5;5687:16;5680:75;5850:49;5895:3;5816;5875:9;5871:22;5850:49;:::i;:::-;5816:3;5836:5;5832:16;5825:75;5998:49;6043:3;5964;6023:9;6019:22;5998:49;:::i;:::-;5964:3;5984:5;5980:16;5973:75;6144:3;;6133:9;6129:19;6116:33;18196:18;6161:6;6158:30;6155:2;;;-1:-1;;6191:12;6155:2;6238:58;6292:3;6283:6;6272:9;6268:22;6238:58;:::i;:::-;6144:3;6222:5;6218:18;6211:86;;;6394:3;;6383:9;6379:19;6366:33;18196:18;6411:6;6408:30;6405:2;;;-1:-1;;6441:12;6405:2;6488:79;6563:3;6554:6;6543:9;6539:22;6488:79;:::i;:::-;6468:18;;;6461:107;;;;-1:-1;6472:5;18056:291;-1:-1;;;;;18056:291::o;18354:402::-;;18499:2;18487:9;18478:7;18474:23;18470:32;18467:2;;;-1:-1;;18505:12;18467:2;18556:17;18550:24;18594:18;18586:6;18583:30;18580:2;;;-1:-1;;18616:12;18580:2;18646:94;18732:7;18723:6;18712:9;18708:22;18646:94;:::i;19033:399::-;;;19165:2;19153:9;19144:7;19140:23;19136:32;19133:2;;;-1:-1;;19171:12;19133:2;-1:-1;;11391:13;;19334:2;19384:22;;;11391:13;;;;;-1:-1;19127:305::o;19439:809::-;;;;;;19622:3;19610:9;19601:7;19597:23;19593:33;19590:2;;;-1:-1;;19629:12;19590:2;-1:-1;;11391:13;;19792:2;19842:22;;11391:13;19911:2;19961:22;;11391:13;20030:2;20080:22;;11391:13;20149:3;20200:22;;;11391:13;;;;;-1:-1;11391:13;;-1:-1;11391:13;;-1:-1;19584:664;-1:-1;19584:664::o;20404:137::-;-1:-1;;;;;41610:54;20491:45;;20485:56::o;20898:323::-;;21030:5;39784:12;40059:6;40054:3;40047:19;21113:52;21158:6;40096:4;40091:3;40087:14;40096:4;21139:5;21135:16;21113:52;:::i;:::-;44122:7;44106:14;-1:-1;;44102:28;21177:39;;;;40096:4;21177:39;;20978:243;-1:-1;;20978:243::o;25557:1986::-;;25718:6;25818:63;25866:14;25795:16;25789:23;25818:63;:::i;:::-;25964:4;25957:5;25953:16;25947:23;25976:63;25964:4;26028:3;26024:14;26010:12;25976:63;:::i;:::-;;26123:4;26116:5;26112:16;26106:23;26123:4;26187:3;26183:14;20849:37;26283:4;26276:5;26272:16;26266:23;26283:4;26347:3;26343:14;20849:37;26441:4;26434:5;26430:16;26424:23;26441:4;26505:3;26501:14;20849:37;26604:4;26597:5;26593:16;26587:23;26604:4;26668:3;26664:14;20849:37;26758:4;26751:5;26747:16;26741:23;26770:63;26758:4;26822:3;26818:14;26804:12;26770:63;:::i;:::-;;26915:4;26908:5;26904:16;26898:23;26927:63;26915:4;26979:3;26975:14;26961:12;26927:63;:::i;:::-;;27076:6;;27069:5;27065:18;27059:25;25718:6;27076;27108:3;27104:16;27097:40;27152:71;25718:6;25713:3;25709:16;27204:12;27152:71;:::i;:::-;27144:79;;;;27316:6;;27309:5;27305:18;27299:25;27372:3;27366:4;27362:14;27316:6;27348:3;27344:16;27337:40;27392:113;27500:4;27486:12;27392:113;:::i;:::-;27527:11;25691:1852;-1:-1;;;;;;25691:1852::o;27631:1219::-;;8208:18;;41621:42;;;;27857:16;27851:23;41610:54;20498:3;20491:45;41621:42;28030:4;28023:5;28019:16;28013:23;41610:54;28030:4;28094:3;28090:14;20491:45;41621:42;28195:4;28188:5;28184:16;28178:23;41610:54;28195:4;28259:3;28255:14;20491:45;;28350:4;28343:5;28339:16;28333:23;28350:4;28414:3;28410:14;20849:37;28511:4;28504:5;28500:16;28494:23;28511:4;28575:3;28571:14;20849:37;28669:4;28662:5;28658:16;28652:23;27782:4;28669;28699:3;28695:14;28688:38;28741:71;27782:4;27777:3;27773:14;28793:12;28741:71;:::i;29087:271::-;;21738:5;39784:12;21849:52;21894:6;21889:3;21882:4;21875:5;21871:16;21849:52;:::i;:::-;21913:16;;;;;29221:137;-1:-1;;29221:137::o;29365:379::-;29729:10;29553:191::o;29751:222::-;-1:-1;;;;;41610:54;;;;20491:45;;29878:2;29863:18;;29849:124::o;30486:349::-;-1:-1;;;;;41610:54;;;;20334:58;;30821:2;30806:18;;20849:37;30649:2;30634:18;;30620:215::o;30842:640::-;-1:-1;;;;;41610:54;;;20491:45;;41610:54;;31236:2;31221:18;;20491:45;31319:2;31304:18;;20849:37;;;31071:3;31356:2;31341:18;;31334:48;;;30842:640;;31396:76;;31056:19;;31458:6;31396:76;:::i;31829:222::-;20849:37;;;31956:2;31941:18;;31927:124::o;32058:333::-;20849:37;;;-1:-1;;;;;41610:54;32377:2;32362:18;;20491:45;32213:2;32198:18;;32184:207::o;32398:306::-;;32543:2;32564:17;32557:47;32618:76;32543:2;32532:9;32528:18;32680:6;32618:76;:::i;34102:416::-;34302:2;34316:47;;;23633:2;34287:18;;;40047:19;23669:34;40087:14;;;23649:55;-1:-1;;;23724:12;;;23717:26;23762:12;;;34273:245::o;34525:416::-;34725:2;34739:47;;;24013:2;34710:18;;;40047:19;24049:29;40087:14;;;24029:50;24098:12;;;34696:245::o;34948:416::-;35148:2;35162:47;;;24654:2;35133:18;;;40047:19;24690:31;40087:14;;;24670:52;24741:12;;;35119:245::o;35371:416::-;35571:2;35585:47;;;24992:2;35556:18;;;40047:19;25028:34;40087:14;;;25008:55;-1:-1;;;25083:12;;;25076:34;25129:12;;;35542:245::o;35794:416::-;35994:2;36008:47;;;25380:2;35979:18;;;40047:19;-1:-1;;;40087:14;;;25396:35;25450:12;;;35965:245::o;36217:390::-;;36404:2;36425:17;36418:47;36479:118;36404:2;36393:9;36389:18;36583:6;36479:118;:::i;36614:527::-;;36842:2;36863:17;36856:47;36917:118;36842:2;36831:9;36827:18;37021:6;36917:118;:::i;:::-;36909:126;;44227:1;44220:5;44217:12;44207:2;;44233:9;44207:2;43192:39;37127:2;37116:9;37112:18;22715:63;36813:328;;;;;:::o;37377:460::-;20849:37;;;-1:-1;;;;;41610:54;;;;37740:2;37725:18;;20334:58;37823:2;37808:18;;20849:37;37568:2;37553:18;;37539:298::o;37844:454::-;20849:37;;;38194:2;38179:18;;20849:37;;;;38284:2;38269:18;;22985:57;38032:2;38017:18;;38003:295::o;38766:333::-;20849:37;;;39085:2;39070:18;;20849:37;38921:2;38906:18;;38892:207::o;39106:256::-;39168:2;39162:9;39194:17;;;39269:18;39254:34;;39290:22;;;39251:62;39248:2;;;39326:1;;39316:12;39248:2;39168;39335:22;39146:216;;-1:-1;39146:216::o;39369:321::-;;39512:18;39504:6;39501:30;39498:2;;;-1:-1;;39534:12;39498:2;-1:-1;44122:7;39588:17;-1:-1;;39584:33;39675:4;39665:15;;39435:255::o;43762:268::-;43827:1;43834:101;43848:6;43845:1;43842:13;43834:101;;;43915:11;;;43909:18;43896:11;;;43889:39;43870:2;43863:10;43834:101;;;43950:6;43947:1;43944:13;43941:2;;;43827:1;44006:6;44001:3;43997:16;43990:27;43941:2;;43811:219;;;:::o;44256:117::-;-1:-1;;;;;41610:54;;44315:35;;44305:2;;44364:1;;44354:12;44305:2;44299:74;:::o;45228:110::-;45313:1;45306:5;45303:12;45293:2;;45329:1;;45319:12
Swarm Source
ipfs://ae5c0a93345d2902744b9dd637cd6ce74d9c233a15f9ca75cf839132f8befb09
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.