Contract Overview
Balance:
0 Ether
More Info
My Name Tag:
Not Available
Txn Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x9b6f0d86ee8de6edbf2fc80c5e91d98b6b8d354ec2058f2b2a2c6668e2fb5f05 | Enable Market | 6002394 | 820 days 5 hrs ago | 0x8d7f03fde1a626223364e592740a233b72395235 | IN | 0x02ee9aebb75470d517bff722d36762d2b231539c | 0 Ether | 0.000024377 | |
0x2527759daa2de69f1a61e881c02272aeb7c37190c6d6c7c688f62b8219d6d2d3 | Enable Market | 6002391 | 820 days 5 hrs ago | 0x8d7f03fde1a626223364e592740a233b72395235 | IN | 0x02ee9aebb75470d517bff722d36762d2b231539c | 0 Ether | 0.000022587 | |
0x1f93d18d63b98cba459559908b3413bb3e0334eb0f6bd1adf879b4a1b87a72e3 | Transfer Ownersh... | 5996139 | 821 days 7 hrs ago | 0x8d7f03fde1a626223364e592740a233b72395235 | IN | 0x02ee9aebb75470d517bff722d36762d2b231539c | 0 Ether | 0.000449216 | |
0x4207103063a86ecb68d6efb381a18cac0524d879e8b9df9a137740fa8db61ab4 | 0x60806040 | 5996122 | 821 days 7 hrs ago | 0x8d7f03fde1a626223364e592740a233b72395235 | IN | Create: DmmController | 0 Ether | 0.026811768 |
[ Download CSV Export ]
Latest 20 internal transactions
[ Download CSV Export ]
Contract Name:
DmmController
Compiler Version
v0.5.13+commit.5b0b510c
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-02-19 */ // File: @openzeppelin/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @openzeppelin/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ 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; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 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; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/utils/Address.sol pragma solidity ^0.5.5; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * This test is non-exhaustive, and there may be false-negatives: during the * execution of a contract's constructor, its address will be reported as * not containing a contract. * * IMPORTANT: It is unsafe to assume that an address for which this * function returns false is an externally-owned account (EOA) and not a * contract. */ function isContract(address account) internal view returns (bool) { // This method relies in extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. // 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 != 0x0 && codehash != accountHash); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.5.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 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)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "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"); } } } // File: @openzeppelin/contracts/GSN/Context.sol pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { _owner = _msgSender(); emit OwnershipTransferred(address(0), _owner); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: contracts/constants/CommonConstants.sol pragma solidity ^0.5.0; contract CommonConstants { uint public constant EXCHANGE_RATE_BASE_RATE = 1e18; } // File: contracts/utils/Blacklistable.sol pragma solidity ^0.5.0; /** * @dev Allows accounts to be blacklisted by the owner of the contract. * * Taken from USDC's contract for blacklisting certain addresses from owning and interacting with the token. */ contract Blacklistable is Ownable { string public constant BLACKLISTED = "BLACKLISTED"; mapping(address => bool) internal blacklisted; event Blacklisted(address indexed account); event UnBlacklisted(address indexed account); event BlacklisterChanged(address indexed newBlacklister); /** * @dev Throws if called by any account other than the creator of this contract */ modifier onlyBlacklister() { require(msg.sender == owner(), "MUST_BE_BLACKLISTER"); _; } /** * @dev Throws if `account` is blacklisted * * @param account The address to check */ modifier notBlacklisted(address account) { require(blacklisted[account] == false, BLACKLISTED); _; } /** * @dev Checks if `account` is blacklisted. Reverts with `BLACKLISTED` if blacklisted. */ function checkNotBlacklisted(address account) public view { require(!blacklisted[account], BLACKLISTED); } /** * @dev Checks if `account` is blacklisted * * @param account The address to check */ function isBlacklisted(address account) public view returns (bool) { return blacklisted[account]; } /** * @dev Adds `account` to blacklist * * @param account The address to blacklist */ function blacklist(address account) public onlyBlacklister { blacklisted[account] = true; emit Blacklisted(account); } /** * @dev Removes account from blacklist * * @param account The address to remove from the blacklist */ function unBlacklist(address account) public onlyBlacklister { blacklisted[account] = false; emit UnBlacklisted(account); } } // File: contracts/impl/DmmBlacklistable.sol pragma solidity ^0.5.0; contract DmmBlacklistable is Blacklistable { constructor() public { } } // File: contracts/interfaces/ICollateralValuator.sol pragma solidity ^0.5.0; interface ICollateralValuator { event CollateralValueUpdated(uint newCollateralValue); /** * @dev Gets the DMM ecosystem's collateral's value from Chainlink's on-chain data feed. * * @return The value of the ecosystem's collateral, as a number with 18 decimals */ function getCollateralValue() external view returns (uint); } // File: contracts/interfaces/InterestRateInterface.sol pragma solidity ^0.5.0; interface InterestRateInterface { /** * @dev Returns the current interest rate for the given DMMA and corresponding total supply & active supply * * @param dmmTokenId The DMMA whose interest should be retrieved * @param totalSupply The total supply fot he DMM token * @param activeSupply The supply that's currently being lent by users * @return The interest rate in APY, which is a number with 18 decimals */ function getInterestRate(uint dmmTokenId, uint totalSupply, uint activeSupply) external view returns (uint); } // File: @openzeppelin/contracts/access/Roles.sol pragma solidity ^0.5.0; /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping (address => bool) bearer; } /** * @dev Give an account access to this role. */ function add(Role storage role, address account) internal { require(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); role.bearer[account] = false; } /** * @dev Check if an account has this role. * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0), "Roles: account is the zero address"); return role.bearer[account]; } } // File: @openzeppelin/contracts/access/roles/PauserRole.sol pragma solidity ^0.5.0; contract PauserRole is Context { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; constructor () internal { _addPauser(_msgSender()); } modifier onlyPauser() { require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role"); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(_msgSender()); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } } // File: @openzeppelin/contracts/lifecycle/Pausable.sol pragma solidity ^0.5.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ contract Pausable is Context, PauserRole { /** * @dev Emitted when the pause is triggered by a pauser (`account`). */ event Paused(address account); /** * @dev Emitted when the pause is lifted by a pauser (`account`). */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. Assigns the Pauser role * to the deployer. */ constructor () internal { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function isPaused() public view returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "Pausable: not paused"); _; } /** * @dev Called by a pauser to pause, triggers stopped state. */ function pause() public onlyPauser whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Called by a pauser to unpause, returns to normal state. */ function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // File: contracts/interfaces/IDmmController.sol pragma solidity ^0.5.0; interface IDmmController { event TotalSupplyIncreased(uint oldTotalSupply, uint newTotalSupply); event TotalSupplyDecreased(uint oldTotalSupply, uint newTotalSupply); event AdminDeposit(address indexed admin, uint amount); event AdminWithdraw(address indexed admin, uint amount); function blacklistable() external view returns (Blacklistable); /** * @dev Disables the corresponding DMMA from minting new tokens. This allows the market to close over time, since * users are only able to redeem tokens. * * @param underlyingToken The token that should be wrapped to create a new DMMA * @param symbol The symbol of the new DMMA, IE DAI or USDC * @param decimals The number of decimals of the underlying token, and therefore the number for this DMMA. */ function addMarket( address underlyingToken, string calldata symbol, string calldata name, uint8 decimals, uint minMintAmount, uint minRedeemAmount, uint totalSupply ) external; /** * @dev Enables the corresponding DMMA to allow minting new tokens. * * @param dmmTokenId The DMMA that should be enabled. */ function enableMarket(uint dmmTokenId) external; /** * @dev Disables the corresponding DMMA from minting new tokens. This allows the market to close over time, since * users are only able to redeem tokens. * * @param dmmTokenId The DMMA that should be disabled. */ function disableMarket(uint dmmTokenId) external; /** * @dev Sets a new contract that implements the `InterestRateInterface` interface. * * @param newInterestRateInterface The new contract that implements the `InterestRateInterface` interface. */ function setInterestRateInterface(address newInterestRateInterface) external; /** * @dev Sets a new contract that implements the `ICollateralizationGetter` interface. * * @param newCollateralValuator The new contract that implements the `ICollateralValuator` interface. */ function setCollateralValuator(address newCollateralValuator) external; /** * @dev Sets a new contract that implements the `UnderlyingTokenValuator` interface * * @param newUnderlyingTokenValuator The new contract that implements the `UnderlyingTokenValuator` interface */ function setUnderlyingTokenValuator(address newUnderlyingTokenValuator) external; /** * @dev Allows the owners of the DMM Ecosystem to withdraw funds from a DMMA. These withdrawn funds are then * allocated to real-world assets that will be used to pay interest into the DMMA. * * @param newMinCollateralization The new min collateralization (with 18 decimals) at which the DMME must be in * order to add to the total supply of DMM. */ function setMinCollateralization(uint newMinCollateralization) external; /** * @dev Allows the owners of the DMM Ecosystem to withdraw funds from a DMMA. These withdrawn funds are then * allocated to real-world assets that will be used to pay interest into the DMMA. * * @param newMinReserveRatio The new ratio (with 18 decimals) that is used to enforce a certain percentage of assets * are kept in each DMMA. */ function setMinReserveRatio(uint newMinReserveRatio) external; /** * @dev Increases the max supply for the provided `dmmTokenId` by `amount`. This call reverts with * INSUFFICIENT_COLLATERAL if there isn't enough collateral in the Chainlink contract to cover the controller's * requirements for minimum collateral. */ function increaseTotalSupply(uint dmmTokenId, uint amount) external; /** * @dev Increases the max supply for the provided `dmmTokenId` by `amount`. */ function decreaseTotalSupply(uint dmmTokenId, uint amount) external; /** * @dev Allows the owners of the DMM Ecosystem to withdraw funds from a DMMA. These withdrawn funds are then * allocated to real-world assets that will be used to pay interest into the DMMA. * * @param dmmTokenId The ID of the DMM token whose underlying will be funded. * @param underlyingAmount The amount underlying the DMM token that will be deposited into the DMMA. */ function adminWithdrawFunds(uint dmmTokenId, uint underlyingAmount) external; /** * @dev Allows the owners of the DMM Ecosystem to deposit funds into a DMMA. These funds are used to disburse * interest payments and add more liquidity to the specific market. * * @param dmmTokenId The ID of the DMM token whose underlying will be funded. * @param underlyingAmount The amount underlying the DMM token that will be deposited into the DMMA. */ function adminDepositFunds(uint dmmTokenId, uint underlyingAmount) external; /** * @dev Gets the collateralization of the system by dividing the total value of all the assets by the value of the * total supplies of all the markets. * * @return The total collateralization of the system, as a number with 18 decimals. For example * `1010000000000000000` is 101% or 1.01. */ function getTotalCollateralization() external view returns (uint); /** * @dev Gets the collateralization of the system by dividing the total value of all the assets by the value of the * active supplies of the DMM tokens. In this case, active supply means the number of DMM tokens that are NOT * in the contract, and therefore there is an obligation to pay interest to those token holders. * * @return The active collateralization of the system, as a number with 18 decimals. For example * `1010000000000000000` is 101% or 1.01. */ function getActiveCollateralization() external view returns (uint); /** * @dev Gets the interest rate from the underlying token, IE DAI or USDC. * * @return The current interest rate, represented using 18 decimals. Meaning `65000000000000000` is 6.5% APY or * 0.065. */ function getInterestRateByUnderlyingTokenAddress(address underlyingToken) external view returns (uint); /** * @dev Gets the interest rate from the DMM token, IE DMM: DAI or DMM: USDC. * * @return The current interest rate, represented using 18 decimals. Meaning, `65000000000000000` is 6.5% APY or * 0.065. */ function getInterestRateByDmmTokenId(uint dmmTokenId) external view returns (uint); /** * @dev Gets the interest rate from the DMM token, IE DMM: DAI or DMM: USDC. * * @return The current interest rate, represented using 18 decimals. Meaning, `65000000000000000` is 6.5% APY or * 0.065. */ function getInterestRateByDmmTokenAddress(address dmmToken) external view returns (uint); /** * @dev Gets the exchange rate from the underlying to the DMM token, such that * `DMM: Token = underlying / exchangeRate` * * @return The current exchange rate, represented using 18 decimals. Meaning, `200000000000000000` is 0.2. */ function getExchangeRateByUnderlying(address underlyingToken) external view returns (uint); /** * @dev Gets the exchange rate from the underlying to the DMM token, such that * `DMM: Token = underlying / exchangeRate` * * @return The current exchange rate, represented using 18 decimals. Meaning, `200000000000000000` is 0.2. */ function getExchangeRate(address dmmToken) external view returns (uint); /** * @dev Gets the DMM token for the provided underlying token. For example, sending DAI returns DMM: DAI. */ function getDmmTokenForUnderlying(address underlyingToken) external view returns (address); /** * @dev Gets the underlying token for the provided DMM token. For example, sending DMM: DAI returns DAI. */ function getUnderlyingTokenForDmm(address dmmToken) external view returns (address); /** * @return True if the market is enabled for this DMMA or false if it is not enabled. */ function isMarketEnabledByDmmTokenId(uint dmmTokenId) external view returns (bool); /** * @return True if the market is enabled for this DMM token (IE DMM: DAI) or false if it is not enabled. */ function isMarketEnabledByDmmTokenAddress(address dmmToken) external view returns (bool); /** * @return True if the market is enabled for this underlying token (IE DAI) or false if it is not enabled. */ function getTokenIdFromDmmTokenAddress(address dmmTokenAddress) external view returns (uint); } // File: contracts/interfaces/IDmmToken.sol pragma solidity ^0.5.0; /** * Basically an interface except, contains the implementation of the type-hashes for offline signature generation. * * This contract contains the signatures and documentation for all publicly-implemented functions in the DMM token. */ interface IDmmToken { /***************** * Events */ event Mint(address indexed minter, address indexed recipient, uint amount); event Redeem(address indexed redeemer, address indexed recipient, uint amount); event FeeTransfer(address indexed owner, address indexed recipient, uint amount); event TotalSupplyIncreased(uint oldTotalSupply, uint newTotalSupply); event TotalSupplyDecreased(uint oldTotalSupply, uint newTotalSupply); event OffChainRequestValidated(address indexed owner, address indexed feeRecipient, uint nonce, uint expiry, uint feeAmount); /***************** * Functions */ /** * @dev The controller that deployed this parent */ function controller() external view returns (address); /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() external view returns (uint8); /** * @return The min amount that can be minted in a single transaction. This amount corresponds with the number of * decimals that this token has. */ function minMintAmount() external view returns (uint); /** * @return The min amount that can be redeemed from DMM to underlying in a single transaction. This amount * corresponds with the number of decimals that this token has. */ function minRedeemAmount() external view returns (uint); /** * @dev The amount of DMM that is in circulation (outside of this contract) */ function activeSupply() external view returns (uint); /** * @dev Attempts to add `amount` to the total supply by issuing the tokens to this contract. This call fires a * Transfer event from the 0x0 address to this contract. */ function increaseTotalSupply(uint amount) external; /** * @dev Attempts to remove `amount` from the total supply by destroying those tokens that are held in this * contract. This call reverts with TOO_MUCH_ACTIVE_SUPPLY if `amount` is not held in this contract. */ function decreaseTotalSupply(uint amount) external; /** * @dev An admin function that lets the ecosystem's organizers deposit the underlying token around which this DMMA * wraps to this contract. This is used to replenish liquidity and after interest payouts are made from the * real-world assets. */ function depositUnderlying(uint underlyingAmount) external returns (bool); /** * @dev An admin function that lets the ecosystem's organizers withdraw the underlying token around which this DMMA * wraps from this contract. This is used to withdraw deposited tokens, to be allocated to real-world assets * that produce income streams and can cover interest payments. */ function withdrawUnderlying(uint underlyingAmount) external returns (bool); /** * @dev The timestamp at which the exchange rate was last updated. */ function exchangeRateLastUpdatedTimestamp() external view returns (uint); /** * @dev The timestamp at which the exchange rate was last updated. */ function exchangeRateLastUpdatedBlockNumber() external view returns (uint); /** * @dev The exchange rate from underlying to DMM. Invert this number to go from DMM to underlying. This number * has 18 decimals. */ function getCurrentExchangeRate() external view returns (uint); /** * @dev The current nonce of the provided `owner`. This `owner` should be the signer for any gasless transactions. */ function nonceOf(address owner) external view returns (uint); /** * @dev Transfers the token around which this DMMA wraps from msg.sender to the DMMA contract. Then, sends the * corresponding amount of DMM to the msg.sender. Note, this call reverts with INSUFFICIENT_DMM_LIQUIDITY if * there is not enough DMM available to be minted. * * @param amount The amount of underlying to send to this DMMA for conversion to DMM. * @return The amount of DMM minted. */ function mint(uint amount) external returns (uint); /** * @dev Transfers the token around which this DMMA wraps from sender to the DMMA contract. Then, sends the * corresponding amount of DMM to recipient. Note, an allowance must be set for sender for the underlying * token that is at least of size `amount` / `exchangeRate`. This call reverts with INSUFFICIENT_DMM_LIQUIDITY if * there is not enough DMM available to be minted. * * @param owner The address that is sending the `underlyingAmount` underlying token. * @param recipient The address the will receive the newly minted DMM. * @param amount The amount of underlying to send to this DMMA for conversion to DMM. * @return The amount of DMM minted. */ function mintFrom(address owner, address recipient, uint amount) external returns (uint); /** * @dev Transfers the token around which this DMMA wraps from sender to the DMMA contract. Then, sends the * corresponding amount of DMM to recipient. Note, an allowance must be set for sender for the underlying * token that is at least of size `amount` / `exchangeRate`. This call reverts with INSUFFICIENT_DMM_LIQUIDITY * if there is not enough DMM available to be minted. See #MINT_TYPE_HASH. This function gives the `owner` the * illusion of committing a gasless transaction, allowing a relayer to broadcast the transaction and * potentially collect a fee for doing so. * * @param owner The user that signed the off-chain message. * @param recipient The address that will receive the newly-minted DMM tokens. * @param nonce An auto-incrementing integer that prevents replay attacks. See #nonceOf(address) to get the * owner's current nonce. * @param expiry The timestamp, in unix seconds, at which the signed off-chain message expires. A value of 0 * means there is no expiration. * @param amount The amount of underlying that should be minted by `owner` and sent to `recipient`. * @param feeAmount The amount of DMM to be sent to feeRecipient for sending this transaction on behalf of * owner. Can be 0, which means the user won't be charged a fee. Must be <= `amount`. * @param feeRecipient The address that should receive the fee. A value of 0x0 will send the fees to `msg.sender`. * Note, no fees are sent if the feeAmount is 0, regardless of what feeRecipient is. * @param v The ECDSA V parameter. * @param r The ECDSA R parameter. * @param s The ECDSA S parameter. * @return The amount of DMM minted. */ function mintFromGaslessRequest( address owner, address recipient, uint nonce, uint expiry, uint amount, uint feeAmount, address feeRecipient, uint8 v, bytes32 r, bytes32 s ) external returns (uint); /** * @dev Transfers DMM from msg.sender to this DMMA contract. Then, sends the corresponding amount of token around * which this DMMA wraps to the msg.sender. Note, this call reverts with INSUFFICIENT_UNDERLYING_LIQUIDITY if * there is not enough DMM available to be redeemed. * * @param amount The amount of DMM to be transferred from msg.sender to this DMMA. * @return The amount of underlying redeemed. */ function redeem(uint amount) external returns (uint); /** * @dev Transfers DMM from `sender` to this DMMA contract. Then, sends the corresponding amount of token around * which this DMMA wraps to `recipient`. Note, an allowance must be set for sender for DMM that is at least of * size `amount`. This call reverts with INSUFFICIENT_UNDERLYING_LIQUIDITY if there is not enough underlying * available to be redeemed. * * @param owner The address that is sending the `underlyingAmount` underlying token. * @param recipient The address the will receive the newly redeemed DMM. * @param amount The amount of DMM token to be redeemed for the recipient. * @return The amount of underlying redeemed. */ function redeemFrom(address owner, address recipient, uint amount) external returns (uint); /** * @dev Transfers DMM from `owner` to the DMMA contract. Then, sends the corresponding amount of token around which * this DMMA wraps to `recipient`. Note, an allowance must be set for sender for the underlying * token that is at least of size `amount`. This call reverts with INSUFFICIENT_UNDERLYING_LIQUIDITY * if there is not enough underlying available to be redeemed. See #REDEEM_TYPE_HASH. This function gives the * `owner` the illusion of committing a gasless transaction, allowing a relayer to broadcast the transaction * and potentially collect a fee for doing so. * * @param owner The user that signed the off-chain message. * @param recipient The address that will receive the newly-redeemed DMM tokens. * @param nonce An auto-incrementing integer that prevents replay attacks. See #nonceOf(address) to get the * owner's current nonce. * @param expiry The timestamp, in unix seconds, at which the signed off-chain message expires. A value of 0 * means there is no expiration. * @param amount The amount of DMM that should be redeemed for `owner` and sent to `recipient`. * @param feeAmount The amount of DMM to be sent to feeRecipient for sending this transaction on behalf of * owner. Can be 0, which means the user won't be charged a fee. Must be <= `amount` * @param feeRecipient The address that should receive the fee. A value of 0x0 will send the fees to `msg.sender`. * Note, no fees are sent if the feeAmount is 0, regardless of what feeRecipient is. * @param v The ECDSA V parameter. * @param r The ECDSA R parameter. * @param s The ECDSA S parameter. * @return The amount of underlying redeemed. */ function redeemFromGaslessRequest( address owner, address recipient, uint nonce, uint expiry, uint amount, uint feeAmount, address feeRecipient, uint8 v, bytes32 r, bytes32 s ) external returns (uint); /** * @dev Sets an allowance for owner with spender using an offline-generated signature. This function allows a * relayer to send the transaction, giving the owner the illusion of committing a gasless transaction. See * #PERMIT_TYPEHASH. * * @param owner The user that signed the off-chain message. * @param spender The contract/wallet that can spend DMM tokens on behalf of owner. * @param nonce An auto-incrementing integer that prevents replay attacks. See #nonceOf(address) to get the * owner's current nonce. * @param expiry The timestamp, in unix seconds, at which the signed off-chain message expires. A value of 0 * means there is no expiration. * @param allowed True if the spender can spend funds on behalf of owner or false to revoke this privilege. * @param feeAmount The amount of DMM to be sent to feeRecipient for sending this transaction on behalf of * owner. Can be 0, which means the user won't be charged a fee. * @param feeRecipient The address that should receive the fee. A value of 0x0 will send the fees to `msg.sender`. * Note, no fees are sent if the feeAmount is 0, regardless of what feeRecipient is. * @param v The ECDSA V parameter. * @param r The ECDSA R parameter. * @param s The ECDSA S parameter. */ function permit( address owner, address spender, uint nonce, uint expiry, bool allowed, uint feeAmount, address feeRecipient, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Transfers DMM from the `owner` to `recipient` using an offline-generated signature. This function allows a * relayer to send the transaction, giving the owner the illusion of committing a gasless transaction. See * #TRANSFER_TYPEHASH. This function gives the `owner` the illusion of committing a gasless transaction, * allowing a relayer to broadcast the transaction and potentially collect a fee for doing so. * * @param owner The user that signed the off-chain message and originator of the transfer. * @param recipient The address that will receive the transferred DMM tokens. * @param nonce An auto-incrementing integer that prevents replay attacks. See #nonceOf(address) to get the * owner's current nonce. * @param expiry The timestamp, in unix seconds, at which the signed off-chain message expires. A value of 0 * means there is no expiration. * @param amount The amount of DMM that should be transferred from `owner` and sent to `recipient`. * @param feeAmount The amount of DMM to be sent to feeRecipient for sending this transaction on behalf of * owner. Can be 0, which means the user won't be charged a fee. * @param feeRecipient The address that should receive the fee. A value of 0x0 will send the fees to `msg.sender`. * Note, no fees are sent if the feeAmount is 0, regardless of what feeRecipient is. * @param v The ECDSA V parameter. * @param r The ECDSA R parameter. * @param s The ECDSA S parameter. * @return True if the transfer was successful or false if it failed. */ function transferFromGaslessRequest( address owner, address recipient, uint nonce, uint expiry, uint amount, uint feeAmount, address feeRecipient, uint8 v, bytes32 r, bytes32 s ) external; } // File: contracts/interfaces/IUnderlyingTokenValuator.sol pragma solidity ^0.5.0; interface IUnderlyingTokenValuator { /** * @dev Gets the tokens value in terms of USD. * * @return The value of the `amount` of `token`, as a number with 18 decimals */ function getTokenValue(address token, uint amount) external view returns (uint); } // File: contracts/interfaces/IDmmTokenFactory.sol pragma solidity ^0.5.0; interface IDmmTokenFactory { function deployToken( string calldata symbol, string calldata name, uint8 decimals, uint minMintAmount, uint minRedeemAmount, uint totalSupply, address controller ) external returns (IDmmToken); } // File: contracts/impl/DmmController.sol pragma solidity ^0.5.0; contract DmmController is Pausable, CommonConstants, IDmmController, Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; /******************************** * Events */ event InterestRateInterfaceChanged(address previousInterestRateInterface, address newInterestRateInterface); event CollateralValuatorChanged(address previousCollateralValuator, address newCollateralValuator); event UnderlyingTokenValuatorChanged(address previousUnderlyingTokenValuator, address newUnderlyingTokenValuator); event MarketAdded(uint indexed dmmTokenId, address indexed dmmToken, address indexed underlyingToken); event DisableMarket(uint indexed dmmTokenId); event EnableMarket(uint indexed dmmTokenId); event MinCollateralizationChanged(uint previousMinCollateralization, uint newMinCollateralization); event MinReserveRatioChanged(uint previousMinReserveRatio, uint newMinReserveRatio); /******************************** * Controller Fields */ DmmBlacklistable public dmmBlacklistable; InterestRateInterface public interestRateInterface; ICollateralValuator public collateralValuator; IUnderlyingTokenValuator public underlyingTokenValuator; IDmmTokenFactory public dmmTokenFactory; IDmmTokenFactory public dmmEtherFactory; uint public minCollateralization; uint public minReserveRatio; address public wethToken; /******************************** * DMM Account Management */ mapping(uint => address) public dmmTokenIdToDmmTokenAddressMap; mapping(address => uint) public dmmTokenAddressToDmmTokenIdMap; mapping(address => uint) public underlyingTokenAddressToDmmTokenIdMap; mapping(uint => address) public dmmTokenIdToUnderlyingTokenAddressMap; mapping(uint => bool) public dmmTokenIdToIsDisabledMap; uint[] public dmmTokenIds; /******************************** * Constants */ uint public constant COLLATERALIZATION_BASE_RATE = 1e18; uint public constant MIN_RESERVE_RATIO_BASE_RATE = 1e18; constructor( address _interestRateInterface, address _collateralValuator, address _underlyingTokenValuator, address _dmmEtherFactory, address _dmmTokenFactory, address _dmmBlacklistable, uint256 _minCollateralization, uint256 _minReserveRatio, address _wethToken ) public { interestRateInterface = InterestRateInterface(_interestRateInterface); collateralValuator = ICollateralValuator(_collateralValuator); underlyingTokenValuator = IUnderlyingTokenValuator(_underlyingTokenValuator); dmmTokenFactory = IDmmTokenFactory(_dmmTokenFactory); dmmEtherFactory = IDmmTokenFactory(_dmmEtherFactory); dmmBlacklistable = DmmBlacklistable(_dmmBlacklistable); minCollateralization = _minCollateralization; minReserveRatio = _minReserveRatio; wethToken = _wethToken; } /***************** * Modifiers */ modifier whenNotPaused() { require(!isPaused(), "ECOSYSTEM_PAUSED"); _; } modifier whenPaused() { require(isPaused(), "ECOSYSTEM_NOT_PAUSED"); _; } modifier checkTokenExists(uint dmmTokenId) { require(dmmTokenIdToDmmTokenAddressMap[dmmTokenId] != address(0x0), "TOKEN_DOES_NOT_EXIST"); _; } /********************** * Public Functions */ function transferOwnership(address newOwner) public onlyOwner { super.transferOwnership(newOwner); addPauser(newOwner); } function blacklistable() public view returns (Blacklistable) { return dmmBlacklistable; } function addMarket( address underlyingToken, string memory symbol, string memory name, uint8 decimals, uint minMintAmount, uint minRedeemAmount, uint totalSupply ) public onlyOwner { require(underlyingTokenAddressToDmmTokenIdMap[underlyingToken] == 0, "TOKEN_ALREADY_EXISTS"); // Start the IDs at 1. Zero is reserved for the empty case when it doesn't exist. uint dmmTokenId = dmmTokenIds.length + 1; address controller = address(this); IDmmToken dmmToken; if (underlyingToken == wethToken) { dmmToken = dmmEtherFactory.deployToken( symbol, name, decimals, minMintAmount, minRedeemAmount, totalSupply, controller ); } else { dmmToken = dmmTokenFactory.deployToken( symbol, name, decimals, minMintAmount, minRedeemAmount, totalSupply, controller ); } address dmmTokenAddress = address(dmmToken); // Update the maps dmmTokenIdToDmmTokenAddressMap[dmmTokenId] = dmmTokenAddress; dmmTokenAddressToDmmTokenIdMap[dmmTokenAddress] = dmmTokenId; underlyingTokenAddressToDmmTokenIdMap[underlyingToken] = dmmTokenId; dmmTokenIdToUnderlyingTokenAddressMap[dmmTokenId] = underlyingToken; // Misc. Structures dmmTokenIdToIsDisabledMap[dmmTokenId] = false; dmmTokenIds.push(dmmTokenId); emit MarketAdded(dmmTokenId, dmmTokenAddress, underlyingToken); } function enableMarket(uint dmmTokenId) public checkTokenExists(dmmTokenId) whenNotPaused onlyOwner { require(dmmTokenIdToIsDisabledMap[dmmTokenId], "MARKET_ALREADY_ENABLED"); dmmTokenIdToIsDisabledMap[dmmTokenId] = false; emit EnableMarket(dmmTokenId); } function disableMarket(uint dmmTokenId) public checkTokenExists(dmmTokenId) whenNotPaused onlyOwner { require(!dmmTokenIdToIsDisabledMap[dmmTokenId], "MARKET_ALREADY_DISABLED"); dmmTokenIdToIsDisabledMap[dmmTokenId] = true; emit DisableMarket(dmmTokenId); } function setInterestRateInterface(address newInterestRateInterface) public whenNotPaused onlyOwner { address oldInterestRateInterface = address(interestRateInterface); interestRateInterface = InterestRateInterface(newInterestRateInterface); emit InterestRateInterfaceChanged(oldInterestRateInterface, address(interestRateInterface)); } function setCollateralValuator(address newCollateralValuator) public whenNotPaused onlyOwner { address oldCollateralValuator = address(collateralValuator); collateralValuator = ICollateralValuator(newCollateralValuator); emit CollateralValuatorChanged(oldCollateralValuator, address(collateralValuator)); } function setUnderlyingTokenValuator(address newUnderlyingTokenValuator) public whenNotPaused onlyOwner { address oldUnderlyingTokenValuator = address(underlyingTokenValuator); underlyingTokenValuator = IUnderlyingTokenValuator(newUnderlyingTokenValuator); emit UnderlyingTokenValuatorChanged(oldUnderlyingTokenValuator, address(underlyingTokenValuator)); } function setMinCollateralization(uint newMinCollateralization) public whenNotPaused onlyOwner { uint oldMinCollateralization = minCollateralization; minCollateralization = newMinCollateralization; emit MinCollateralizationChanged(oldMinCollateralization, minCollateralization); } function setMinReserveRatio(uint newMinReserveRatio) public whenNotPaused onlyOwner { uint oldMinReserveRatio = minReserveRatio; minReserveRatio = newMinReserveRatio; emit MinReserveRatioChanged(oldMinReserveRatio, minReserveRatio); } function increaseTotalSupply( uint dmmTokenId, uint amount ) public checkTokenExists(dmmTokenId) whenNotPaused onlyOwner { IDmmToken(dmmTokenIdToDmmTokenAddressMap[dmmTokenId]).increaseTotalSupply(amount); require(getTotalCollateralization() >= minCollateralization, "INSUFFICIENT_COLLATERAL"); } function decreaseTotalSupply( uint dmmTokenId, uint amount ) public checkTokenExists(dmmTokenId) whenNotPaused onlyOwner { IDmmToken(dmmTokenIdToDmmTokenAddressMap[dmmTokenId]).decreaseTotalSupply(amount); } function adminWithdrawFunds( uint dmmTokenId, uint256 underlyingAmount ) public checkTokenExists(dmmTokenId) whenNotPaused onlyOwner { // Attempt to pull from the DMM contract into this contract, then send from this contract to sender. IDmmToken token = IDmmToken(dmmTokenIdToDmmTokenAddressMap[dmmTokenId]); token.withdrawUnderlying(underlyingAmount); IERC20 underlyingToken = IERC20(dmmTokenIdToUnderlyingTokenAddressMap[dmmTokenId]); underlyingToken.safeTransfer(_msgSender(), underlyingAmount); // This is the amount owed by the system in terms of underlying uint totalOwedAmount = token.activeSupply().mul(token.getCurrentExchangeRate()).div(EXCHANGE_RATE_BASE_RATE); uint underlyingBalance = IERC20(dmmTokenIdToUnderlyingTokenAddressMap[dmmTokenId]).balanceOf(address(token)); // IE if we owe 100 and have an underlying balance of 10 --> reserve ratio is 0.1 uint actualReserveRatio = underlyingBalance.mul(MIN_RESERVE_RATIO_BASE_RATE).div(totalOwedAmount); require(actualReserveRatio >= minReserveRatio, "INSUFFICIENT_LEFTOVER_RESERVES"); emit AdminWithdraw(_msgSender(), underlyingAmount); } function adminDepositFunds( uint dmmTokenId, uint256 underlyingAmount ) public checkTokenExists(dmmTokenId) whenNotPaused onlyOwner { // Attempt to pull from the sender into this contract, then have the DMM token pull from here. IERC20 underlyingToken = IERC20(dmmTokenIdToUnderlyingTokenAddressMap[dmmTokenId]); underlyingToken.safeTransferFrom(_msgSender(), address(this), underlyingAmount); address dmmTokenAddress = dmmTokenIdToDmmTokenAddressMap[dmmTokenId]; underlyingToken.approve(dmmTokenAddress, underlyingAmount); IDmmToken(dmmTokenAddress).depositUnderlying(underlyingAmount); emit AdminDeposit(_msgSender(), underlyingAmount); } function getTotalCollateralization() public view returns (uint) { uint totalLiabilities = 0; for (uint i = 0; i < dmmTokenIds.length; i++) { // IDs start at 1 IDmmToken token = IDmmToken(dmmTokenIdToDmmTokenAddressMap[dmmTokenIds[i]]); uint underlyingValue = getSupplyValue(token, IERC20(address(token)).totalSupply()); totalLiabilities = totalLiabilities.add(underlyingValue); } uint collateralValue = collateralValuator.getCollateralValue(); return collateralValue.mul(COLLATERALIZATION_BASE_RATE).div(totalLiabilities); } function getActiveCollateralization() public view returns (uint) { uint totalLiabilities = 0; for (uint i = 0; i < dmmTokenIds.length; i++) { // IDs start at 1 IDmmToken token = IDmmToken(dmmTokenIdToDmmTokenAddressMap[dmmTokenIds[i + 1]]); uint underlyingValue = getSupplyValue(token, token.activeSupply()); totalLiabilities = totalLiabilities.add(underlyingValue); } uint collateralValue = collateralValuator.getCollateralValue(); return collateralValue.mul(COLLATERALIZATION_BASE_RATE).div(totalLiabilities); } function getInterestRateByUnderlyingTokenAddress(address underlyingToken) public view returns (uint) { uint dmmTokenId = underlyingTokenAddressToDmmTokenIdMap[underlyingToken]; return getInterestRateByDmmTokenId(dmmTokenId); } function getInterestRateByDmmTokenId(uint dmmTokenId) checkTokenExists(dmmTokenId) public view returns (uint) { address dmmToken = dmmTokenIdToDmmTokenAddressMap[dmmTokenId]; uint totalSupply = IERC20(dmmToken).totalSupply(); uint activeSupply = IDmmToken(dmmToken).activeSupply(); return interestRateInterface.getInterestRate(dmmTokenId, totalSupply, activeSupply); } function getInterestRateByDmmTokenAddress(address dmmToken) public view returns (uint) { uint dmmTokenId = dmmTokenAddressToDmmTokenIdMap[dmmToken]; require(dmmTokenId != 0, "TOKEN_DOES_NOT_EXIST"); uint totalSupply = IERC20(dmmToken).totalSupply(); uint activeSupply = IDmmToken(dmmToken).activeSupply(); return interestRateInterface.getInterestRate(dmmTokenId, totalSupply, activeSupply); } function getExchangeRateByUnderlying(address underlyingToken) public view returns (uint) { address dmmToken = getDmmTokenForUnderlying(underlyingToken); return IDmmToken(dmmToken).getCurrentExchangeRate(); } function getExchangeRate(address dmmToken) public view returns (uint) { uint dmmTokenId = dmmTokenAddressToDmmTokenIdMap[dmmToken]; require(dmmTokenId != 0, "TOKEN_DOES_NOT_EXIST"); return IDmmToken(dmmToken).getCurrentExchangeRate(); } function getDmmTokenForUnderlying(address underlyingToken) public view returns (address) { uint dmmTokenId = underlyingTokenAddressToDmmTokenIdMap[underlyingToken]; require(dmmTokenId != 0, "TOKEN_DOES_NOT_EXIST"); return dmmTokenIdToDmmTokenAddressMap[dmmTokenId]; } function getUnderlyingTokenForDmm(address dmmToken) public view returns (address) { uint dmmTokenId = dmmTokenAddressToDmmTokenIdMap[dmmToken]; require(dmmTokenId != 0, "TOKEN_DOES_NOT_EXIST"); return dmmTokenIdToUnderlyingTokenAddressMap[dmmTokenId]; } function isMarketEnabledByDmmTokenId(uint dmmTokenId) checkTokenExists(dmmTokenId) public view returns (bool) { return !dmmTokenIdToIsDisabledMap[dmmTokenId]; } function isMarketEnabledByDmmTokenAddress(address dmmToken) public view returns (bool) { uint dmmTokenId = dmmTokenAddressToDmmTokenIdMap[dmmToken]; require(dmmTokenId != 0, "TOKEN_DOES_NOT_EXIST"); return !dmmTokenIdToIsDisabledMap[dmmTokenId]; } function getTokenIdFromDmmTokenAddress(address dmmToken) public view returns (uint) { uint dmmTokenId = dmmTokenAddressToDmmTokenIdMap[dmmToken]; require(dmmTokenId != 0, "TOKEN_DOES_NOT_EXIST"); return dmmTokenId; } function getDmmTokenIds() public view returns (uint[] memory) { return dmmTokenIds; } /********************** * Private Functions */ function getSupplyValue(IDmmToken token, uint supply) private view returns (uint) { uint underlyingTokenAmount = supply.mul(token.getCurrentExchangeRate()).div(EXCHANGE_RATE_BASE_RATE); address underlyingToken = getUnderlyingTokenForDmm(address(token)); return underlyingTokenValuator.getTokenValue(underlyingToken, underlyingTokenAmount); } }
[{"inputs":[{"internalType":"address","name":"_interestRateInterface","type":"address"},{"internalType":"address","name":"_collateralValuator","type":"address"},{"internalType":"address","name":"_underlyingTokenValuator","type":"address"},{"internalType":"address","name":"_dmmEtherFactory","type":"address"},{"internalType":"address","name":"_dmmTokenFactory","type":"address"},{"internalType":"address","name":"_dmmBlacklistable","type":"address"},{"internalType":"uint256","name":"_minCollateralization","type":"uint256"},{"internalType":"uint256","name":"_minReserveRatio","type":"uint256"},{"internalType":"address","name":"_wethToken","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AdminDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AdminWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousCollateralValuator","type":"address"},{"indexed":false,"internalType":"address","name":"newCollateralValuator","type":"address"}],"name":"CollateralValuatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"dmmTokenId","type":"uint256"}],"name":"DisableMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"dmmTokenId","type":"uint256"}],"name":"EnableMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousInterestRateInterface","type":"address"},{"indexed":false,"internalType":"address","name":"newInterestRateInterface","type":"address"}],"name":"InterestRateInterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"dmmTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"dmmToken","type":"address"},{"indexed":true,"internalType":"address","name":"underlyingToken","type":"address"}],"name":"MarketAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousMinCollateralization","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinCollateralization","type":"uint256"}],"name":"MinCollateralizationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousMinReserveRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinReserveRatio","type":"uint256"}],"name":"MinReserveRatioChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldTotalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalSupply","type":"uint256"}],"name":"TotalSupplyDecreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldTotalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalSupply","type":"uint256"}],"name":"TotalSupplyIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousUnderlyingTokenValuator","type":"address"},{"indexed":false,"internalType":"address","name":"newUnderlyingTokenValuator","type":"address"}],"name":"UnderlyingTokenValuatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"constant":true,"inputs":[],"name":"COLLATERALIZATION_BASE_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"EXCHANGE_RATE_BASE_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MIN_RESERVE_RATIO_BASE_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"underlyingToken","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"minMintAmount","type":"uint256"},{"internalType":"uint256","name":"minRedeemAmount","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"}],"name":"addMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"dmmTokenId","type":"uint256"},{"internalType":"uint256","name":"underlyingAmount","type":"uint256"}],"name":"adminDepositFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"dmmTokenId","type":"uint256"},{"internalType":"uint256","name":"underlyingAmount","type":"uint256"}],"name":"adminWithdrawFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"blacklistable","outputs":[{"internalType":"contract Blacklistable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"collateralValuator","outputs":[{"internalType":"contract ICollateralValuator","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"dmmTokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreaseTotalSupply","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"dmmTokenId","type":"uint256"}],"name":"disableMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"dmmBlacklistable","outputs":[{"internalType":"contract DmmBlacklistable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dmmEtherFactory","outputs":[{"internalType":"contract IDmmTokenFactory","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"dmmTokenAddressToDmmTokenIdMap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dmmTokenFactory","outputs":[{"internalType":"contract IDmmTokenFactory","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dmmTokenIdToDmmTokenAddressMap","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dmmTokenIdToIsDisabledMap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dmmTokenIdToUnderlyingTokenAddressMap","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dmmTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"dmmTokenId","type":"uint256"}],"name":"enableMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getActiveCollateralization","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"underlyingToken","type":"address"}],"name":"getDmmTokenForUnderlying","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getDmmTokenIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"dmmToken","type":"address"}],"name":"getExchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"underlyingToken","type":"address"}],"name":"getExchangeRateByUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"dmmToken","type":"address"}],"name":"getInterestRateByDmmTokenAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"dmmTokenId","type":"uint256"}],"name":"getInterestRateByDmmTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"underlyingToken","type":"address"}],"name":"getInterestRateByUnderlyingTokenAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"dmmToken","type":"address"}],"name":"getTokenIdFromDmmTokenAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalCollateralization","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"dmmToken","type":"address"}],"name":"getUnderlyingTokenForDmm","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"dmmTokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseTotalSupply","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"interestRateInterface","outputs":[{"internalType":"contract InterestRateInterface","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"dmmToken","type":"address"}],"name":"isMarketEnabledByDmmTokenAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"dmmTokenId","type":"uint256"}],"name":"isMarketEnabledByDmmTokenId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minCollateralization","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minReserveRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renouncePauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newCollateralValuator","type":"address"}],"name":"setCollateralValuator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newInterestRateInterface","type":"address"}],"name":"setInterestRateInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newMinCollateralization","type":"uint256"}],"name":"setMinCollateralization","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newMinReserveRatio","type":"uint256"}],"name":"setMinReserveRatio","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newUnderlyingTokenValuator","type":"address"}],"name":"setUnderlyingTokenValuator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"underlyingTokenAddressToDmmTokenIdMap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"underlyingTokenValuator","outputs":[{"internalType":"contract IUnderlyingTokenValuator","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"wethToken","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162003a7938038062003a7983398181016040526101208110156200003857600080fd5b508051602082015160408301516060840151608085015160a086015160c087015160e0880151610100909801519697959694959394929391929091906200009a6200008b6001600160e01b036200019b16565b6001600160e01b036200019f16565b6001805460ff19169055620000b76001600160e01b036200019b16565b60018054610100600160a81b0319166101006001600160a01b03938416810291909117918290556040519104909116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600380546001600160a01b03199081166001600160a01b039b8c1617909155600480548216998b1699909917909855600580548916978a16979097179096556006805488169489169490941790935560078054871694881694909417909355600280548616918716919091179055600891909155600955600a805490921692169190911790556200031b565b3390565b620001ba816000620001f160201b6200346a1790919060201c565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b6200020682826001600160e01b036200029816565b156200027357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b60006001600160a01b038216620002fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018062003a576022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b61372c806200032b6000396000f3fe608060405234801561001057600080fd5b50600436106103425760003560e01c806382dc1ec4116101b8578063ba5d006711610104578063e09286de116100a2578063efb7601d1161007c578063efb7601d1461094a578063f2fde38b14610970578063f9322c7414610996578063ffd2bab6146109bc57610342565b8063e09286de1461091d578063e123bf271461093a578063eb65b7791461094257610342565b8063cd147c41116100de578063cd147c4114610891578063cd4aa182146108ae578063d9d3c53e146108d4578063e0471613146108f757610342565b8063ba5d006714610863578063c37c4d7c1461086b578063c3c6de911461069157610342565b806398c3729811610171578063af4b4cc51161014b578063af4b4cc5146107f2578063b187bd2614610818578063b2a24d9f14610820578063ba082cde1461083d57610342565b806398c372981461079e578063a0acbce0146107c4578063a694de28146107ea57610342565b806382dc1ec414610726578063836851351461074c5780638456cb59146107695780638da5cb5b146107715780638f32d59b1461077957806396a442251461078157610342565b8063533f3ba8116102925780636ef8d66d1161023057806379db8e231161020a57806379db8e23146106c65780637e7bb8a1146106e357806380d9fde61461069157806380de4cf91461070057610342565b80636ef8d66d14610699578063715018a6146106a15780637990e8fa146106a957610342565b8063565c17141161026c578063565c1714146106645780635a596d1c146106815780635b10a00e1461068957806369ce6b771461069157610342565b8063533f3ba8146104ee5780635550425a1461063f578063561778ea1461064757610342565b8063375cea96116102ff5780634b57b0be116102d95780634b57b0be146104775780634b826d811461047f5780634d38f747146104a25780634d79af57146104c857610342565b8063375cea961461042d5780633f4ba83a1461043557806346fbf68e1461043d57610342565b80630107f15b146103475780631b581b481461036b5780631deef941146103855780631fbfc5ff146103dd57806327c3a770146103e5578063339b37761461040a575b600080fd5b61034f6109e2565b604080516001600160a01b039092168252519081900360200190f35b6103736109f1565b60408051918252519081900360200190f35b61038d610b81565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103c95781810151838201526020016103b1565b505050509050019250505060405180910390f35b61034f610bd9565b610408600480360360408110156103fb57600080fd5b5080359060200135610be8565b005b6104086004803603604081101561042057600080fd5b5080359060200135610e67565b61034f611022565b610408611031565b6104636004803603602081101561045357600080fd5b50356001600160a01b031661111c565b604080519115158252519081900360200190f35b61034f611134565b6104086004803603604081101561049557600080fd5b5080359060200135611143565b610463600480360360208110156104b857600080fd5b50356001600160a01b03166112a0565b610408600480360360208110156104de57600080fd5b50356001600160a01b0316611312565b610408600480360360e081101561050457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561052f57600080fd5b82018360208201111561054157600080fd5b8035906020019184600183028401116401000000008311171561056357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156105b657600080fd5b8201836020820111156105c857600080fd5b803590602001918460018302840111640100000000831117156105ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505060ff8335169350505060208101359060408101359060600135611408565b61034f6118a5565b6104636004803603602081101561065d57600080fd5b50356118b4565b6104086004803603602081101561067a57600080fd5b50356118c9565b610373611a5e565b61034f611a64565b610373611a73565b610408611a7f565b610408611a91565b610463600480360360208110156106bf57600080fd5b5035611b28565b61034f600480360360208110156106dc57600080fd5b5035611b99565b610408600480360360208110156106f957600080fd5b5035611bb4565b6103736004803603602081101561071657600080fd5b50356001600160a01b0316611c8f565b6104086004803603602081101561073c57600080fd5b50356001600160a01b0316611ce8565b6104086004803603602081101561076257600080fd5b5035611d3a565b610408611e15565b61034f611edd565b610463611ef1565b6104086004803603602081101561079757600080fd5b5035611f1c565b61034f600480360360208110156107b457600080fd5b50356001600160a01b03166120a6565b610373600480360360208110156107da57600080fd5b50356001600160a01b031661211d565b61037361212f565b6103736004803603602081101561080857600080fd5b50356001600160a01b03166121dd565b6104636123a1565b6103736004803603602081101561083657600080fd5b50356123aa565b6104086004803603602081101561085357600080fd5b50356001600160a01b03166123c8565b6103736124be565b61034f6004803603602081101561088157600080fd5b50356001600160a01b03166124c4565b61034f600480360360208110156108a757600080fd5b503561253b565b610373600480360360208110156108c457600080fd5b50356001600160a01b0316612556565b610408600480360360408110156108ea57600080fd5b508035906020013561257f565b6104086004803603602081101561090d57600080fd5b50356001600160a01b031661296b565b6103736004803603602081101561093357600080fd5b5035612a61565b61034f612c3b565b61034f612c4a565b6103736004803603602081101561096057600080fd5b50356001600160a01b0316612c59565b6104086004803603602081101561098657600080fd5b50356001600160a01b0316612d1e565b610373600480360360208110156109ac57600080fd5b50356001600160a01b0316612d77565b610373600480360360208110156109d257600080fd5b50356001600160a01b0316612dbe565b6002546001600160a01b031690565b600080805b601054811015610ad3576000600b600060108460010181548110610a1657fe5b9060005260206000200154815260200190815260200160002060009054906101000a90046001600160a01b031690506000610ab582836001600160a01b031663babd70126040518163ffffffff1660e01b815260040160206040518083038186803b158015610a8457600080fd5b505afa158015610a98573d6000803e3d6000fd5b505050506040513d6020811015610aae57600080fd5b5051612dd0565b9050610ac7848263ffffffff612eb716565b935050506001016109f6565b506000600460009054906101000a90046001600160a01b03166001600160a01b031663c047e5636040518163ffffffff1660e01b815260040160206040518083038186803b158015610b2457600080fd5b505afa158015610b38573d6000803e3d6000fd5b505050506040513d6020811015610b4e57600080fd5b50519050610b7a82610b6e83670de0b6b3a764000063ffffffff612f1116565b9063ffffffff612f6a16565b9250505090565b60606010805480602002602001604051908101604052809291908181526020018280548015610bcf57602002820191906000526020600020905b815481526020019060010190808311610bbb575b5050505050905090565b6006546001600160a01b031681565b6000828152600b602052604090205482906001600160a01b0316610c41576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b610c496123a1565b15610c8e576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b610c96611ef1565b610cd5576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6000838152600e60205260409020546001600160a01b0316610d10610cf8612fac565b6001600160a01b03831690308663ffffffff612fb016565b6000848152600b6020908152604080832054815163095ea7b360e01b81526001600160a01b039182166004820181905260248201899052925192949186169363095ea7b39360448084019492939192918390030190829087803b158015610d7657600080fd5b505af1158015610d8a573d6000803e3d6000fd5b505050506040513d6020811015610da057600080fd5b50506040805163b9f5be4160e01b81526004810186905290516001600160a01b0383169163b9f5be419160248083019260209291908290030181600087803b158015610deb57600080fd5b505af1158015610dff573d6000803e3d6000fd5b505050506040513d6020811015610e1557600080fd5b50610e209050612fac565b6001600160a01b03167fce8f50bef0c9b984189b343b8bf9264667774780224a0b53de9005bb2d384a9f856040518082815260200191505060405180910390a25050505050565b6000828152600b602052604090205482906001600160a01b0316610ec0576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b610ec86123a1565b15610f0d576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b610f15611ef1565b610f54576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6000838152600b60205260408082205481516303a8799360e31b81526004810186905291516001600160a01b0390911692631d43cc98926024808201939182900301818387803b158015610fa757600080fd5b505af1158015610fbb573d6000803e3d6000fd5b50505050600854610fca61212f565b101561101d576040805162461bcd60e51b815260206004820152601760248201527f494e53554646494349454e545f434f4c4c41544552414c000000000000000000604482015290519081900360640190fd5b505050565b6007546001600160a01b031681565b61104161103c612fac565b61111c565b61107c5760405162461bcd60e51b81526004018080602001828103825260308152602001806135d46030913960400191505060405180910390fd5b6110846123a1565b6110cc576040805162461bcd60e51b81526020600482015260146024820152731150d3d4d654d5115357d393d517d4105554d15160621b604482015290519081900360640190fd5b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6110ff612fac565b604080516001600160a01b039092168252519081900360200190a1565b600061112e818363ffffffff61301016565b92915050565b600a546001600160a01b031681565b6000828152600b602052604090205482906001600160a01b031661119c576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b6111a46123a1565b156111e9576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b6111f1611ef1565b611230576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6000838152600b6020526040808220548151636e11451160e01b81526004810186905291516001600160a01b0390911692636e114511926024808201939182900301818387803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b50505050505050565b6001600160a01b0381166000908152600c6020526040812054806112f9576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b6000908152600f602052604090205460ff161592915050565b61131a6123a1565b1561135f576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b611367611ef1565b6113a6576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b600380546001600160a01b038381166001600160a01b0319831617928390556040805192821680845293909116602083015280517f8d7f6129d57ccb02dbf423991fc05188ee19ee305d4cc6eaa0e9eaf27bdbc8099281900390910190a15050565b611410611ef1565b61144f576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6001600160a01b0387166000908152600d6020526040902054156114b1576040805162461bcd60e51b8152602060048201526014602482015273544f4b454e5f414c52454144595f45584953545360601b604482015290519081900360640190fd5b601054600a5460019091019030906000906001600160a01b038b811691161415611653576007546040516208144560e11b815260ff89166044820152606481018890526084810187905260a481018690526001600160a01b0384811660c483015260e0600483019081528c5160e48401528c5191909316926210288a928d928d928d928d928d928d928c92829160248101916101049091019060208c019080838360005b8381101561156d578181015183820152602001611555565b50505050905090810190601f16801561159a5780820380516001836020036101000a031916815260200191505b5083810382528951815289516020918201918b019080838360005b838110156115cd5781810151838201526020016115b5565b50505050905090810190601f1680156115fa5780820380516001836020036101000a031916815260200191505b509950505050505050505050602060405180830381600087803b15801561162057600080fd5b505af1158015611634573d6000803e3d6000fd5b505050506040513d602081101561164a57600080fd5b505190506117cd565b6006546040516208144560e11b815260ff89166044820152606481018890526084810187905260a481018690526001600160a01b0384811660c483015260e0600483019081528c5160e48401528c5191909316926210288a928d928d928d928d928d928d928c92829160248101916101049091019060208c019080838360005b838110156116eb5781810151838201526020016116d3565b50505050905090810190601f1680156117185780820380516001836020036101000a031916815260200191505b5083810382528951815289516020918201918b019080838360005b8381101561174b578181015183820152602001611733565b50505050905090810190601f1680156117785780820380516001836020036101000a031916815260200191505b509950505050505050505050602060405180830381600087803b15801561179e57600080fd5b505af11580156117b2573d6000803e3d6000fd5b505050506040513d60208110156117c857600080fd5b505190505b6000838152600b6020908152604080832080546001600160a01b038087166001600160a01b03199283168117909355828652600c85528386208990558f16808652600d8552838620899055888652600e855283862080549092168117909155600f909352818420805460ff19169055601080546001810182559085527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae672018790559051849387917f54736d25075919df72a1cdd3bab83287f25b1bf8bf9deac0f043b6cf6eea334a9190a45050505050505050505050565b6002546001600160a01b031681565b600f6020526000908152604090205460ff1681565b6000818152600b602052604090205481906001600160a01b0316611922576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b61192a6123a1565b1561196f576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b611977611ef1565b6119b6576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6000828152600f602052604090205460ff1615611a1a576040805162461bcd60e51b815260206004820152601760248201527f4d41524b45545f414c52454144595f44495341424c4544000000000000000000604482015290519081900360640190fd5b6000828152600f6020526040808220805460ff191660011790555183917f88062db56f0bada5b549bac4f4637f70288a1bfbd50c0578cf1b217a5d94e9b491a25050565b60095481565b6004546001600160a01b031681565b670de0b6b3a764000081565b611a8f611a8a612fac565b613077565b565b611a99611ef1565b611ad8576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b60015460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a360018054610100600160a81b0319169055565b6000818152600b602052604081205482906001600160a01b0316611b81576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b50506000908152600f602052604090205460ff161590565b600b602052600090815260409020546001600160a01b031681565b611bbc6123a1565b15611c01576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b611c09611ef1565b611c48576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6008805490829055604080518281526020810184905281517f41c21d7a9652c6a2e6c22641602770b2d9d04f367adb18eabbf076d74521b721929181900390910190a15050565b6001600160a01b0381166000908152600c60205260408120548061112e576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b611cf361103c612fac565b611d2e5760405162461bcd60e51b81526004018080602001828103825260308152602001806135d46030913960400191505060405180910390fd5b611d37816130bf565b50565b611d426123a1565b15611d87576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b611d8f611ef1565b611dce576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6009805490829055604080518281526020810184905281517fb8a37dfe71ffcc47f17a11cabec0d2d41cd370c7f7f2c4a7fca4cef6282ad568929181900390910190a15050565b611e2061103c612fac565b611e5b5760405162461bcd60e51b81526004018080602001828103825260308152602001806135d46030913960400191505060405180910390fd5b611e636123a1565b15611ea8576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586110ff612fac565b60015461010090046001600160a01b031690565b60015460009061010090046001600160a01b0316611f0d612fac565b6001600160a01b031614905090565b6000818152600b602052604090205481906001600160a01b0316611f75576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b611f7d6123a1565b15611fc2576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b611fca611ef1565b612009576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6000828152600f602052604090205460ff16612065576040805162461bcd60e51b815260206004820152601660248201527513505492d15517d053149150511657d153905093115160521b604482015290519081900360640190fd5b6000828152600f6020526040808220805460ff191690555183917f8227fbc28a4e896face737e0ecdd927a187a4ef9013b8dbcce2f5fb88cc7a81791a25050565b6001600160a01b0381166000908152600d6020526040812054806120ff576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b6000908152600b60205260409020546001600160a01b031692915050565b600d6020526000908152604090205481565b600080805b601054811015610ad3576000600b60006010848154811061215157fe5b9060005260206000200154815260200190815260200160002060009054906101000a90046001600160a01b0316905060006121bf82836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a8457600080fd5b90506121d1848263ffffffff612eb716565b93505050600101612134565b6001600160a01b0381166000908152600c602052604081205480612236576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b6000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561227157600080fd5b505afa158015612285573d6000803e3d6000fd5b505050506040513d602081101561229b57600080fd5b505160408051635d5eb80960e11b815290519192506000916001600160a01b0387169163babd7012916004808301926020929190829003018186803b1580156122e357600080fd5b505afa1580156122f7573d6000803e3d6000fd5b505050506040513d602081101561230d57600080fd5b5051600354604080516364bfe61f60e11b815260048101879052602481018690526044810184905290519293506001600160a01b039091169163c97fcc3e91606480820192602092909190829003018186803b15801561236c57600080fd5b505afa158015612380573d6000803e3d6000fd5b505050506040513d602081101561239657600080fd5b505195945050505050565b60015460ff1690565b601081815481106123b757fe5b600091825260209091200154905081565b6123d06123a1565b15612415576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b61241d611ef1565b61245c576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b600580546001600160a01b038381166001600160a01b0319831617928390556040805192821680845293909116602083015280517f059ad1c0c51ecc25729ab67ccc037eb0729e4b7773c472de55817dc441b188179281900390910190a15050565b60085481565b6001600160a01b0381166000908152600c60205260408120548061251d576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b6000908152600e60205260409020546001600160a01b031692915050565b600e602052600090815260409020546001600160a01b031681565b6001600160a01b0381166000908152600d602052604081205461257881612a61565b9392505050565b6000828152600b602052604090205482906001600160a01b03166125d8576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b6125e06123a1565b15612625576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b61262d611ef1565b61266c576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b6000838152600b602090815260408083205481516301071a2960e41b81526004810187905291516001600160a01b03909116938493631071a290936024808201949293918390030190829087803b1580156126c657600080fd5b505af11580156126da573d6000803e3d6000fd5b505050506040513d60208110156126f057600080fd5b50506000848152600e60205260409020546001600160a01b031661272c612715612fac565b6001600160a01b038316908663ffffffff61310716565b600061281a670de0b6b3a7640000610b6e856001600160a01b0316633ca967f36040518163ffffffff1660e01b815260040160206040518083038186803b15801561277657600080fd5b505afa15801561278a573d6000803e3d6000fd5b505050506040513d60208110156127a057600080fd5b505160408051635d5eb80960e11b815290516001600160a01b0389169163babd7012916004808301926020929190829003018186803b1580156127e257600080fd5b505afa1580156127f6573d6000803e3d6000fd5b505050506040513d602081101561280c57600080fd5b50519063ffffffff612f1116565b6000878152600e602090815260408083205481516370a0823160e01b81526001600160a01b038981166004830152925195965093949116926370a08231926024808301939192829003018186803b15801561287457600080fd5b505afa158015612888573d6000803e3d6000fd5b505050506040513d602081101561289e57600080fd5b5051905060006128c083610b6e84670de0b6b3a764000063ffffffff612f1116565b9050600954811015612919576040805162461bcd60e51b815260206004820152601e60248201527f494e53554646494349454e545f4c4546544f5645525f52455345525645530000604482015290519081900360640190fd5b612921612fac565b6001600160a01b03167fba443e8671971c36cdeb74f87321041daff421230cbc5e36cb835269ed1d8b7e886040518082815260200191505060405180910390a25050505050505050565b6129736123a1565b156129b8576040805162461bcd60e51b815260206004820152601060248201526f1150d3d4d654d5115357d4105554d15160821b604482015290519081900360640190fd5b6129c0611ef1565b6129ff576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b600480546001600160a01b038381166001600160a01b0319831617928390556040805192821680845293909116602083015280517f314ae709118555c5bd2ada9391c31a42ad9ce83324312476b6cbb384bbc1f2729281900390910190a15050565b6000818152600b602052604081205482906001600160a01b0316612aba576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b6000838152600b602090815260408083205481516318160ddd60e01b815291516001600160a01b03909116939284926318160ddd9260048083019392829003018186803b158015612b0a57600080fd5b505afa158015612b1e573d6000803e3d6000fd5b505050506040513d6020811015612b3457600080fd5b505160408051635d5eb80960e11b815290519192506000916001600160a01b0385169163babd7012916004808301926020929190829003018186803b158015612b7c57600080fd5b505afa158015612b90573d6000803e3d6000fd5b505050506040513d6020811015612ba657600080fd5b5051600354604080516364bfe61f60e11b8152600481018a9052602481018690526044810184905290519293506001600160a01b039091169163c97fcc3e91606480820192602092909190829003018186803b158015612c0557600080fd5b505afa158015612c19573d6000803e3d6000fd5b505050506040513d6020811015612c2f57600080fd5b50519695505050505050565b6005546001600160a01b031681565b6003546001600160a01b031681565b6001600160a01b0381166000908152600c602052604081205480612cb2576040805162461bcd60e51b815260206004820152601460248201526000805160206136ae833981519152604482015290519081900360640190fd5b826001600160a01b0316633ca967f36040518163ffffffff1660e01b815260040160206040518083038186803b158015612ceb57600080fd5b505afa158015612cff573d6000803e3d6000fd5b505050506040513d6020811015612d1557600080fd5b50519392505050565b612d26611ef1565b612d65576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b612d6e81613159565b611d3781611ce8565b600080612d83836120a6565b9050806001600160a01b0316633ca967f36040518163ffffffff1660e01b815260040160206040518083038186803b158015612ceb57600080fd5b600c6020526000908152604090205481565b600080612e54670de0b6b3a7640000610b6e866001600160a01b0316633ca967f36040518163ffffffff1660e01b815260040160206040518083038186803b158015612e1b57600080fd5b505afa158015612e2f573d6000803e3d6000fd5b505050506040513d6020811015612e4557600080fd5b5051869063ffffffff612f1116565b90506000612e61856124c4565b60055460408051636d34cd1760e01b81526001600160a01b038085166004830152602482018790529151939450911691636d34cd1791604480820192602092909190829003018186803b15801561236c57600080fd5b600082820183811015612578576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082612f205750600061112e565b82820282848281612f2d57fe5b04146125785760405162461bcd60e51b815260040180806020018281038252602181526020018061364b6021913960400191505060405180910390fd5b600061257883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506131a9565b3390565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261300a90859061324b565b50505050565b60006001600160a01b0382166130575760405162461bcd60e51b815260040180806020018281038252602281526020018061368c6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b61308860008263ffffffff61340316565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b6130d060008263ffffffff61346a16565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261101d90849061324b565b613161611ef1565b6131a0576040805162461bcd60e51b8152602060048201819052602482015260008051602061366c833981519152604482015290519081900360640190fd5b611d37816134eb565b600081836132355760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156131fa5781810151838201526020016131e2565b50505050905090810190601f1680156132275780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161324157fe5b0495945050505050565b61325d826001600160a01b0316613597565b6132ae576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106132ec5780518252601f1990920191602091820191016132cd565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461334e576040519150601f19603f3d011682016040523d82523d6000602084013e613353565b606091505b5091509150816133aa576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b80511561300a578080602001905160208110156133c657600080fd5b505161300a5760405162461bcd60e51b815260040180806020018281038252602a8152602001806136ce602a913960400191505060405180910390fd5b61340d8282613010565b6134485760405162461bcd60e51b815260040180806020018281038252602181526020018061362a6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6134748282613010565b156134c6576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6001600160a01b0381166135305760405162461bcd60e51b81526004018080602001828103825260268152602001806136046026913960400191505060405180910390fd5b6001546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906135cb5750808214155b94935050505056fe506175736572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652050617573657220726f6c654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373544f4b454e5f444f45535f4e4f545f45584953540000000000000000000000005361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a7231582040b308e2af01060f2b41df0eed8e708021e549089b20ccd53ce7ef3c0cacd13b64736f6c634300050d0032526f6c65733a206163636f756e7420697320746865207a65726f20616464726573730000000000000000000000007a01313ed513f13acc35536cb66feb5362e6c3c300000000000000000000000028a655d5221c866fb3790dbe75fd657219cd3324000000000000000000000000cca971a0d728f138c96a0e14b20040832ea55053000000000000000000000000dd34269490a4095f445da6c683dd2f010bbc9282000000000000000000000000bc5b9040fee0cca807a0d6e35f535a1b8e609c14000000000000000000000000bb2706d18b5def6f66b1f97ee47b42ea6a45f73a0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000005ae1948b45d61917452af4208e3b2fef1bc70e12
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007a01313ed513f13acc35536cb66feb5362e6c3c300000000000000000000000028a655d5221c866fb3790dbe75fd657219cd3324000000000000000000000000cca971a0d728f138c96a0e14b20040832ea55053000000000000000000000000dd34269490a4095f445da6c683dd2f010bbc9282000000000000000000000000bc5b9040fee0cca807a0d6e35f535a1b8e609c14000000000000000000000000bb2706d18b5def6f66b1f97ee47b42ea6a45f73a0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000005ae1948b45d61917452af4208e3b2fef1bc70e12
-----Decoded View---------------
Arg [0] : _interestRateInterface (address): 0x7a01313ed513f13acc35536cb66feb5362e6c3c3
Arg [1] : _collateralValuator (address): 0x28a655d5221c866fb3790dbe75fd657219cd3324
Arg [2] : _underlyingTokenValuator (address): 0xcca971a0d728f138c96a0e14b20040832ea55053
Arg [3] : _dmmEtherFactory (address): 0xdd34269490a4095f445da6c683dd2f010bbc9282
Arg [4] : _dmmTokenFactory (address): 0xbc5b9040fee0cca807a0d6e35f535a1b8e609c14
Arg [5] : _dmmBlacklistable (address): 0xbb2706d18b5def6f66b1f97ee47b42ea6a45f73a
Arg [6] : _minCollateralization (uint256): 1000000000000000000
Arg [7] : _minReserveRatio (uint256): 500000000000000000
Arg [8] : _wethToken (address): 0x5ae1948b45d61917452af4208e3b2fef1bc70e12
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a01313ed513f13acc35536cb66feb5362e6c3c3
Arg [1] : 00000000000000000000000028a655d5221c866fb3790dbe75fd657219cd3324
Arg [2] : 000000000000000000000000cca971a0d728f138c96a0e14b20040832ea55053
Arg [3] : 000000000000000000000000dd34269490a4095f445da6c683dd2f010bbc9282
Arg [4] : 000000000000000000000000bc5b9040fee0cca807a0d6e35f535a1b8e609c14
Arg [5] : 000000000000000000000000bb2706d18b5def6f66b1f97ee47b42ea6a45f73a
Arg [6] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [7] : 00000000000000000000000000000000000000000000000006f05b59d3b20000
Arg [8] : 0000000000000000000000005ae1948b45d61917452af4208e3b2fef1bc70e12
Deployed ByteCode Sourcemap
52826:15286:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52826:15286:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56540:103;;;:::i;:::-;;;;-1:-1:-1;;;;;56540:103:0;;;;;;;;;;;;;;63963:615;;;:::i;:::-;;;;;;;;;;;;;;;;67561:99;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;67561:99:0;;;;;;;;;;;;;;;;;54090:39;;;:::i;62588:733::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62588:733:0;;;;;;;:::i;:::-;;60735:342;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60735:342:0;;;;;;;:::i;54136:39::-;;;:::i;26690:120::-;;;:::i;24167:109::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24167:109:0;-1:-1:-1;;;;;24167:109:0;;:::i;:::-;;;;;;;;;;;;;;;;;;54255:24;;;:::i;61085:244::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61085:244:0;;;;;;;:::i;67014:281::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;67014:281:0;-1:-1:-1;;;;;67014:281:0;;:::i;59025:367::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59025:367:0;-1:-1:-1;;;;;59025:367:0;;:::i;56651:1775::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;56651:1775:0;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;56651:1775:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;56651:1775:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;56651:1775:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;56651:1775:0;;;;;;;;-1:-1:-1;56651:1775:0;;-1:-1:-1;;21:11;5:28;;2:2;;;46:1;43;36:12;2:2;56651:1775:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;56651:1775:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;56651:1775:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;56651:1775:0;;-1:-1:-1;;56651:1775:0;;;;;-1:-1:-1;;;56651:1775:0;;;;;;;;;;;;;;:::i;53872:40::-;;;:::i;54663:54::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54663:54:0;;:::i;58728:289::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58728:289:0;;:::i;54221:27::-;;;:::i;53976:45::-;;;:::i;54888:55::-;;;:::i;24384:79::-;;;:::i;18260:140::-;;;:::i;66832:174::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66832:174:0;;:::i;54369:62::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54369:62:0;;:::i;60142:311::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60142:311:0;;:::i;67303:250::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;67303:250:0;-1:-1:-1;;;;;67303:250:0;;:::i;24284:92::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24284:92:0;-1:-1:-1;;;;;24284:92:0;;:::i;60461:266::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60461:266:0;;:::i;26477:118::-;;;:::i;17449:79::-;;;:::i;17815:94::-;;;:::i;58434:286::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58434:286:0;;:::i;66228:301::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66228:301:0;-1:-1:-1;;;;;66228:301:0;;:::i;54509:69::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54509:69:0;-1:-1:-1;;;;;54509:69:0;;:::i;63329:626::-;;;:::i;65260:444::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65260:444:0;-1:-1:-1;;;;;65260:444:0;;:::i;25895:80::-;;;:::i;54724:25::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54724:25:0;;:::i;59746:388::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59746:388:0;-1:-1:-1;;;;;59746:388:0;;:::i;54182:32::-;;;:::i;66537:287::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66537:287:0;-1:-1:-1;;;;;66537:287:0;;:::i;54585:69::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54585:69:0;;:::i;64586:249::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;64586:249:0;-1:-1:-1;;;;;64586:249:0;;:::i;61337:1243::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61337:1243:0;;;;;;;:::i;59400:338::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59400:338:0;-1:-1:-1;;;;;59400:338:0;;:::i;64843:409::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;64843:409:0;;:::i;54028:55::-;;;:::i;53919:50::-;;;:::i;65950:270::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65950:270:0;-1:-1:-1;;;;;65950:270:0;;:::i;56388:144::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56388:144:0;-1:-1:-1;;;;;56388:144:0;;:::i;65712:230::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65712:230:0;-1:-1:-1;;;;;65712:230:0;;:::i;54438:62::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54438:62:0;-1:-1:-1;;;;;54438:62:0;;:::i;56540:103::-;56619:16;;-1:-1:-1;;;;;56619:16:0;56540:103;:::o;63963:615::-;64022:4;;;64075:335;64096:11;:18;64092:22;;64075:335;;;64167:15;64195:30;:50;64226:11;64238:1;64242;64238:5;64226:18;;;;;;;;;;;;;;;;64195:50;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;64195:50:0;64167:79;;64261:20;64284:43;64299:5;64306;-1:-1:-1;;;;;64306:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;64306:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;64306:20:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;64306:20:0;64284:14;:43::i;:::-;64261:66;-1:-1:-1;64361:37:0;:16;64261:66;64361:37;:20;:37;:::i;:::-;64342:56;-1:-1:-1;;;64116:3:0;;64075:335;;;;64420:20;64443:18;;;;;;;;;-1:-1:-1;;;;;64443:18:0;-1:-1:-1;;;;;64443:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;64443:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;64443:39:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;64443:39:0;;-1:-1:-1;64500:70:0;64553:16;64500:48;64443:39;54877:4;64500:48;:19;:48;:::i;:::-;:52;:70;:52;:70;:::i;:::-;64493:77;;;;63963:615;:::o;67561:99::-;67608:13;67641:11;67634:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67561:99;:::o;54090:39::-;;;-1:-1:-1;;;;;54090:39:0;;:::o;62588:733::-;56266:3;56212:42;;;:30;:42;;;;;;62707:10;;-1:-1:-1;;;;;56212:42:0;56204:91;;;;;-1:-1:-1;;;56204:91:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56204:91:0;;;;;;;;;;;;;;;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;62858:22;62890:49;;;:37;:49;;;;;;-1:-1:-1;;;;;62890:49:0;62951:79;62984:12;:10;:12::i;:::-;-1:-1:-1;;;;;62951:32:0;;;63006:4;63013:16;62951:79;:32;:79;:::i;:::-;63043:23;63069:42;;;:30;:42;;;;;;;;;63122:58;;-1:-1:-1;;;63122:58:0;;-1:-1:-1;;;;;63069:42:0;;;63122:58;;;;;;;;;;;;;;63069:42;;63122:23;;;;;;:58;;;;;63069:42;;63122:58;;;;;;;;;;:23;:58;;;5:2:-1;;;;30:1;27;20:12;5:2;63122:58:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;63122:58:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;63191:62:0;;;-1:-1:-1;;;63191:62:0;;;;;;;;;;-1:-1:-1;;;;;63191:44:0;;;;;:62;;;;;63122:58;;63191:62;;;;;;;-1:-1:-1;63191:44:0;:62;;;5:2:-1;;;;30:1;27;20:12;5:2;63191:62:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;63191:62:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63282:12:0;;-1:-1:-1;63282:10:0;:12::i;:::-;-1:-1:-1;;;;;63269:44:0;;63296:16;63269:44;;;;;;;;;;;;;;;;;;17718:1;;62588:733;;;:::o;60735:342::-;56266:3;56212:42;;;:30;:42;;;;;;60843:10;;-1:-1:-1;;;;;56212:42:0;56204:91;;;;;-1:-1:-1;;;56204:91:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56204:91:0;;;;;;;;;;;;;;;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;60900:42;;;;:30;:42;;;;;;;60890:81;;-1:-1:-1;;;60890:81:0;;;;;;;;;;-1:-1:-1;;;;;60900:42:0;;;;60890:73;;:81;;;;;;;;;;;60900:42;;60890:81;;;5:2:-1;;;;30:1;27;20:12;5:2;60890:81:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60890:81:0;;;;61021:20;;60990:27;:25;:27::i;:::-;:51;;60982:87;;;;;-1:-1:-1;;;60982:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;60735:342;;;:::o;54136:39::-;;;-1:-1:-1;;;;;54136:39:0;;:::o;26690:120::-;24064:22;24073:12;:10;:12::i;:::-;24064:8;:22::i;:::-;24056:83;;;;-1:-1:-1;;;24056:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56087:10;:8;:10::i;:::-;56079:43;;;;;-1:-1:-1;;;56079:43:0;;;;;;;;;;;;-1:-1:-1;;;56079:43:0;;;;;;;;;;;;;;;26749:7;:15;;-1:-1:-1;;26749:15:0;;;26780:22;26789:12;:10;:12::i;:::-;26780:22;;;-1:-1:-1;;;;;26780:22:0;;;;;;;;;;;;;;26690:120::o;24167:109::-;24223:4;24247:21;24223:4;24260:7;24247:21;:12;:21;:::i;:::-;24240:28;24167:109;-1:-1:-1;;24167:109:0:o;54255:24::-;;;-1:-1:-1;;;;;54255:24:0;;:::o;61085:244::-;56266:3;56212:42;;;:30;:42;;;;;;61193:10;;-1:-1:-1;;;;;56212:42:0;56204:91;;;;;-1:-1:-1;;;56204:91:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56204:91:0;;;;;;;;;;;;;;;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;61250:42;;;;:30;:42;;;;;;;61240:81;;-1:-1:-1;;;61240:81:0;;;;;;;;;;-1:-1:-1;;;;;61250:42:0;;;;61240:73;;:81;;;;;;;;;;;61250:42;;61240:81;;;5:2:-1;;;;30:1;27;20:12;5:2;61240:81:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61240:81:0;;;;61085:244;;;:::o;67014:281::-;-1:-1:-1;;;;;67130:40:0;;67095:4;67130:40;;;:30;:40;;;;;;67189:15;67181:48;;;;;-1:-1:-1;;;67181:48:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;67181:48:0;;;;;;;;;;;;;;;67250:37;;;;:25;:37;;;;;;;;67249:38;;67014:281;-1:-1:-1;;67014:281:0:o;59025:367::-;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;59178:21;;;-1:-1:-1;;;;;59211:71:0;;;-1:-1:-1;;;;;;59211:71:0;;;;;;;59298:86;;;59178:21;;;59298:86;;;59361:21;;;;59298:86;;;;;;;;;;;;;;;;17718:1;59025:367;:::o;56651:1775::-;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;56919:54:0;;;;;;:37;:54;;;;;;:59;56911:92;;;;;-1:-1:-1;;;56911:92:0;;;;;;;;;;;;-1:-1:-1;;;56911:92:0;;;;;;;;;;;;;;;57125:11;:18;57257:9;;57146:1;57125:22;;;;57187:4;;57107:15;;-1:-1:-1;;;;;57238:28:0;;;57257:9;;57238:28;57234:600;;;57294:15;;:242;;-1:-1:-1;;;57294:242:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57294:242:0;;;;;;;;;;;;;;;;;;;;;;:15;;;;;:27;;57340:6;;57365:4;;57388:8;;57415:13;;57447:15;;57481:11;;57511:10;;57294:242;;;;;;;;;;;;;;;;;;:15;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57294:242:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;57294:242:0;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57294:242:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57294:242:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;57294:242:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;57294:242:0;;-1:-1:-1;57234:600:0;;;57580:15;;:242;;-1:-1:-1;;;57580:242:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57580:242:0;;;;;;;;;;;;;;;;;;;;;;:15;;;;;:27;;57626:6;;57651:4;;57674:8;;57701:13;;57733:15;;57767:11;;57797:10;;57580:242;;;;;;;;;;;;;;;;;;:15;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57580:242:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;57580:242:0;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57580:242:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57580:242:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;57580:242:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;57580:242:0;;-1:-1:-1;57234:600:0;57846:23;57930:42;;;:30;:42;;;;;;;;:60;;-1:-1:-1;;;;;57930:60:0;;;-1:-1:-1;;;;;;57930:60:0;;;;;;;;58001:47;;;:30;:47;;;;;:60;;;58072:54;;;;;:37;:54;;;;;:67;;;58150:49;;;:37;:49;;;;;:67;;;;;;;;;;58259:25;:37;;;;;;:45;;-1:-1:-1;;58259:45:0;;;58315:11;27:10:-1;;57930:60:0;23:18:-1;;45:23;;58315:28:0;;;;;;;;58361:57;;57880:8;;57961:10;;58361:57;;57846:23;58361:57;17718:1;;;;56651:1775;;;;;;;:::o;53872:40::-;;;-1:-1:-1;;;;;53872:40:0;;:::o;54663:54::-;;;;;;;;;;;;;;;:::o;58728:289::-;56266:3;56212:42;;;:30;:42;;;;;;58792:10;;-1:-1:-1;;;;;56212:42:0;56204:91;;;;;-1:-1:-1;;;56204:91:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56204:91:0;;;;;;;;;;;;;;;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;58848:37;;;;:25;:37;;;;;;;;58847:38;58839:74;;;;;-1:-1:-1;;;58839:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;58924:37;;;;:25;:37;;;;;;:44;;-1:-1:-1;;58924:44:0;58964:4;58924:44;;;58984:25;58950:10;;58984:25;;;58728:289;;:::o;54221:27::-;;;;:::o;53976:45::-;;;-1:-1:-1;;;;;53976:45:0;;:::o;54888:55::-;54939:4;54888:55;:::o;24384:79::-;24428:27;24442:12;:10;:12::i;:::-;24428:13;:27::i;:::-;24384:79::o;18260:140::-;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;18343:6;;18322:40;;18359:1;;18343:6;;;-1:-1:-1;;;;;18343:6:0;;18322:40;;18359:1;;18322:40;18373:6;:19;;-1:-1:-1;;;;;;18373:19:0;;;18260:140::o;66832:174::-;66936:4;56212:42;;;:30;:42;;;;;;66903:10;;-1:-1:-1;;;;;56212:42:0;56204:91;;;;;-1:-1:-1;;;56204:91:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56204:91:0;;;;;;;;;;;;;;;-1:-1:-1;;66961:37:0;;;;:25;:37;;;;;;;;66960:38;;66832:174::o;54369:62::-;;;;;;;;;;;;-1:-1:-1;;;;;54369:62:0;;:::o;60142:311::-;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;60278:20;;;60309:46;;;;60371:74;;;;;;;;;;;;;;;;;;;;;;;;;17718:1;60142:311;:::o;67303:250::-;-1:-1:-1;;;;;67416:40:0;;67381:4;67416:40;;;:30;:40;;;;;;67475:15;67467:48;;;;;-1:-1:-1;;;67467:48:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;67467:48:0;;;;;;;;;;;;;;24284:92;24064:22;24073:12;:10;:12::i;24064:22::-;24056:83;;;;-1:-1:-1;;;24056:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24349:19;24360:7;24349:10;:19::i;:::-;24284:92;:::o;60461:266::-;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;60582:15;;;60608:36;;;;60660:59;;;;;;;;;;;;;;;;;;;;;;;;;17718:1;60461:266;:::o;26477:118::-;24064:22;24073:12;:10;:12::i;24064:22::-;24056:83;;;;-1:-1:-1;;;24056:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;26547:4;26537:14;;-1:-1:-1;;26537:14:0;;;;;26567:20;26574:12;:10;:12::i;17449:79::-;17514:6;;;;;-1:-1:-1;;;;;17514:6:0;;17449:79::o;17815:94::-;17895:6;;17855:4;;17895:6;;;-1:-1:-1;;;;;17895:6:0;17879:12;:10;:12::i;:::-;-1:-1:-1;;;;;17879:22:0;;17872:29;;17815:94;:::o;58434:286::-;56266:3;56212:42;;;:30;:42;;;;;;58497:10;;-1:-1:-1;;;;;56212:42:0;56204:91;;;;;-1:-1:-1;;;56204:91:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56204:91:0;;;;;;;;;;;;;;;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;58552:37;;;;:25;:37;;;;;;;;58544:72;;;;;-1:-1:-1;;;58544:72:0;;;;;;;;;;;;-1:-1:-1;;;58544:72:0;;;;;;;;;;;;;;;58667:5;58627:37;;;:25;:37;;;;;;:45;;-1:-1:-1;;58627:45:0;;;58688:24;58653:10;;58688:24;;;58434:286;;:::o;66228:301::-;-1:-1:-1;;;;;66346:54:0;;66308:7;66346:54;;;:37;:54;;;;;;66419:15;66411:48;;;;;-1:-1:-1;;;66411:48:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;66411:48:0;;;;;;;;;;;;;;;66479:42;;;;:30;:42;;;;;;-1:-1:-1;;;;;66479:42:0;;66228:301;-1:-1:-1;;66228:301:0:o;54509:69::-;;;;;;;;;;;;;:::o;63329:626::-;63387:4;;;63440:347;63461:11;:18;63457:22;;63440:347;;;63532:15;63560:30;:46;63591:11;63603:1;63591:14;;;;;;;;;;;;;;;;63560:46;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;63560:46:0;63532:75;;63622:20;63645:59;63660:5;63682;-1:-1:-1;;;;;63667:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;63645:59:0;63622:82;-1:-1:-1;63738:37:0;:16;63622:82;63738:37;:20;:37;:::i;:::-;63719:56;-1:-1:-1;;;63481:3:0;;63440:347;;65260:444;-1:-1:-1;;;;;65376:40:0;;65341:4;65376:40;;;:30;:40;;;;;;65435:15;65427:48;;;;;-1:-1:-1;;;65427:48:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;65427:48:0;;;;;;;;;;;;;;;65488:16;65514:8;-1:-1:-1;;;;;65507:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65507:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65507:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65507:30:0;65568:34;;;-1:-1:-1;;;65568:34:0;;;;65507:30;;-1:-1:-1;65548:17:0;;-1:-1:-1;;;;;65568:32:0;;;;;:34;;;;;65507:30;;65568:34;;;;;;;:32;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;65568:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65568:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65568:34:0;65620:21;;:76;;;-1:-1:-1;;;65620:76:0;;;;;;;;;;;;;;;;;;;;;;65568:34;;-1:-1:-1;;;;;;65620:21:0;;;;:37;;:76;;;;;65568:34;;65620:76;;;;;;;;:21;:76;;;5:2:-1;;;;30:1;27;20:12;5:2;65620:76:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65620:76:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65620:76:0;;65260:444;-1:-1:-1;;;;;65260:444:0:o;25895:80::-;25960:7;;;;25895:80;:::o;54724:25::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54724:25:0;:::o;59746:388::-;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;59905:23;;;-1:-1:-1;;;;;59940:78:0;;;-1:-1:-1;;;;;;59940:78:0;;;;;;;60034:92;;;59905:23;;;60034:92;;;60101:23;;;;60034:92;;;;;;;;;;;;;;;;17718:1;59746:388;:::o;54182:32::-;;;;:::o;66537:287::-;-1:-1:-1;;;;;66648:40:0;;66610:7;66648:40;;;:30;:40;;;;;;66707:15;66699:48;;;;;-1:-1:-1;;;66699:48:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;66699:48:0;;;;;;;;;;;;;;;66767:49;;;;:37;:49;;;;;;-1:-1:-1;;;;;66767:49:0;;66537:287;-1:-1:-1;;66537:287:0:o;54585:69::-;;;;;;;;;;;;-1:-1:-1;;;;;54585:69:0;;:::o;64586:249::-;-1:-1:-1;;;;;64716:54:0;;64681:4;64716:54;;;:37;:54;;;;;;64788:39;64716:54;64788:27;:39::i;:::-;64781:46;64586:249;-1:-1:-1;;;64586:249:0:o;61337:1243::-;56266:3;56212:42;;;:30;:42;;;;;;61457:10;;-1:-1:-1;;;;;56212:42:0;56204:91;;;;;-1:-1:-1;;;56204:91:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56204:91:0;;;;;;;;;;;;;;;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;61614:15;61642:42;;;:30;:42;;;;;;;;;61696;;-1:-1:-1;;;61696:42:0;;;;;;;;;;-1:-1:-1;;;;;61642:42:0;;;;;;61696:24;;:42;;;;;61642;;61696;;;;;;;;61642;61696;;;5:2:-1;;;;30:1;27;20:12;5:2;61696:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61696:42:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;61749:22:0;61781:49;;;:37;61696:42;61781:49;;;;;-1:-1:-1;;;;;61781:49:0;61842:60;61871:12;:10;:12::i;:::-;-1:-1:-1;;;;;61842:28:0;;;61885:16;61842:60;:28;:60;:::i;:::-;61988:20;62011:85;19166:4;62011:56;62036:5;-1:-1:-1;;;;;62036:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62036:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62036:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62036:30:0;62011:20;;;-1:-1:-1;;;62011:20:0;;;;-1:-1:-1;;;;;62011:18:0;;;;;:20;;;;;62036:30;;62011:20;;;;;;;:18;:20;;;5:2:-1;;;;30:1;27;20:12;5:2;62011:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62011:20:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62011:20:0;;:56;:24;:56;:::i;:85::-;62107:22;62139:49;;;:37;:49;;;;;;;;;62132:83;;-1:-1:-1;;;62132:83:0;;-1:-1:-1;;;;;62132:83:0;;;;;;;;;61988:108;;-1:-1:-1;62107:22:0;;62139:49;;;62132:67;;:83;;;;;62139:49;;62132:83;;;;;62139:49;62132:83;;;5:2:-1;;;;30:1;27;20:12;5:2;62132:83:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62132:83:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62132:83:0;;-1:-1:-1;62319:23:0;62345:71;62400:15;62345:50;62132:83;54939:4;62345:50;:21;:50;:::i;:71::-;62319:97;;62459:15;;62437:18;:37;;62429:80;;;;;-1:-1:-1;;;62429:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;62541:12;:10;:12::i;:::-;-1:-1:-1;;;;;62527:45:0;;62555:16;62527:45;;;;;;;;;;;;;;;;;;17718:1;;;;;61337:1243;;;:::o;59400:338::-;55987:10;:8;:10::i;:::-;55986:11;55978:40;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;-1:-1:-1;;;55978:40:0;;;;;;;;;;;;;;;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;59544:18;;;-1:-1:-1;;;;;59574:63:0;;;-1:-1:-1;;;;;;59574:63:0;;;;;;;59653:77;;;59544:18;;;59653:77;;;59710:18;;;;59653:77;;;;;;;;;;;;;;;;17718:1;59400:338;:::o;64843:409::-;64947:4;56212:42;;;:30;:42;;;;;;64914:10;;-1:-1:-1;;;;;56212:42:0;56204:91;;;;;-1:-1:-1;;;56204:91:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56204:91:0;;;;;;;;;;;;;;;64964:16;64983:42;;;:30;:42;;;;;;;;;65055:30;;-1:-1:-1;;;65055:30:0;;;;-1:-1:-1;;;;;64983:42:0;;;;64964:16;64983:42;;65055:28;;:30;;;;;64983:42;65055:30;;;;;64983:42;65055:30;;;5:2:-1;;;;30:1;27;20:12;5:2;65055:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65055:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65055:30:0;65116:34;;;-1:-1:-1;;;65116:34:0;;;;65055:30;;-1:-1:-1;65096:17:0;;-1:-1:-1;;;;;65116:32:0;;;;;:34;;;;;65055:30;;65116:34;;;;;;;:32;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;65116:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65116:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65116:34:0;65168:21;;:76;;;-1:-1:-1;;;65168:76:0;;;;;;;;;;;;;;;;;;;;;;65116:34;;-1:-1:-1;;;;;;65168:21:0;;;;:37;;:76;;;;;65116:34;;65168:76;;;;;;;;:21;:76;;;5:2:-1;;;;30:1;27;20:12;5:2;65168:76:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;65168:76:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;65168:76:0;;64843:409;-1:-1:-1;;;;;;64843:409:0:o;54028:55::-;;;-1:-1:-1;;;;;54028:55:0;;:::o;53919:50::-;;;-1:-1:-1;;;;;53919:50:0;;:::o;65950:270::-;-1:-1:-1;;;;;66049:40:0;;66014:4;66049:40;;;:30;:40;;;;;;66108:15;66100:48;;;;;-1:-1:-1;;;66100:48:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;66100:48:0;;;;;;;;;;;;;;;66178:8;-1:-1:-1;;;;;66168:42:0;;:44;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66168:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;66168:44:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66168:44:0;;65950:270;-1:-1:-1;;;65950:270:0:o;56388:144::-;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;56461:33;56485:8;56461:23;:33::i;:::-;56505:19;56515:8;56505:9;:19::i;65712:230::-;65795:4;65812:16;65831:41;65856:15;65831:24;:41::i;:::-;65812:60;;65900:8;-1:-1:-1;;;;;65890:42:0;;:44;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;54438:62:0;;;;;;;;;;;;;:::o;67734:373::-;67810:4;67827:26;67856:71;19166:4;67856:42;67867:5;-1:-1:-1;;;;;67867:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;67867:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;67867:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;67867:30:0;67856:6;;:42;:10;:42;:::i;:71::-;67827:100;;67938:23;67964:40;67997:5;67964:24;:40::i;:::-;68022:23;;:77;;;-1:-1:-1;;;68022:77:0;;-1:-1:-1;;;;;68022:77:0;;;;;;;;;;;;;;;67938:66;;-1:-1:-1;68022:23:0;;;:37;;:77;;;;;;;;;;;;;;;:23;:77;;;5:2:-1;;;;30:1;27;20:12;3793:181:0;3851:7;3883:5;;;3907:6;;;;3899:46;;;;;-1:-1:-1;;;3899:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;5165:471;5223:7;5468:6;5464:47;;-1:-1:-1;5498:1:0;5491:8;;5464:47;5535:5;;;5539:1;5535;:5;:1;5559:5;;;;;:10;5551:56;;;;-1:-1:-1;;;5551:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6104:132;6162:7;6189:39;6193:1;6196;6189:39;;;;;;;;;;;;;;;;;:3;:39::i;16198:98::-;16278:10;16198:98;:::o;12364:204::-;12491:68;;;-1:-1:-1;;;;;12491:68:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;12491:68:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;12465:95:0;;12484:5;;12465:18;:95::i;:::-;12364:204;;;;:::o;23432:203::-;23504:4;-1:-1:-1;;;;;23529:21:0;;23521:68;;;;-1:-1:-1;;;23521:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;23607:20:0;:11;:20;;;;;;;;;;;;;;;23432:203::o;24601:130::-;24661:24;:8;24677:7;24661:24;:15;:24;:::i;:::-;24701:22;;-1:-1:-1;;;;;24701:22:0;;;;;;;;24601:130;:::o;24471:122::-;24528:21;:8;24541:7;24528:21;:12;:21;:::i;:::-;24565:20;;-1:-1:-1;;;;;24565:20:0;;;;;;;;24471:122;:::o;12180:176::-;12289:58;;;-1:-1:-1;;;;;12289:58:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;12289:58:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;12263:85:0;;12282:5;;12263:18;:85::i;18555:109::-;17661:9;:7;:9::i;:::-;17653:54;;;;;-1:-1:-1;;;17653:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;17653:54:0;;;;;;;;;;;;;;;18628:28;18647:8;18628:18;:28::i;6766:345::-;6852:7;6954:12;6947:5;6939:28;;;;-1:-1:-1;;;6939:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;6939:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6978:9;6994:1;6990;:5;;;;;;;6766:345;-1:-1:-1;;;;;6766:345:0:o;14219:1114::-;14823:27;14831:5;-1:-1:-1;;;;;14823:25:0;;:27::i;:::-;14815:71;;;;;-1:-1:-1;;;14815:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;14960:12;14974:23;15009:5;-1:-1:-1;;;;;15001:19:0;15021:4;15001:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;15001:25:0;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;14959:67:0;;;;15045:7;15037:52;;;;;-1:-1:-1;;;15037:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15106:17;;:21;15102:224;;15248:10;15237:30;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15237:30:0;15229:85;;;;-1:-1:-1;;;15229:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23154:183;23234:18;23238:4;23244:7;23234:3;:18::i;:::-;23226:64;;;;-1:-1:-1;;;23226:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23301:20:0;23324:5;23301:20;;;;;;;;;;;:28;;-1:-1:-1;;23301:28:0;;;23154:183::o;22896:178::-;22974:18;22978:4;22984:7;22974:3;:18::i;:::-;22973:19;22965:63;;;;;-1:-1:-1;;;22965:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23039:20:0;:11;:20;;;;;;;;;;;:27;;-1:-1:-1;;23039:27:0;23062:4;23039:27;;;22896:178::o;18770:229::-;-1:-1:-1;;;;;18844:22:0;;18836:73;;;;-1:-1:-1;;;18836:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18946:6;;18925:38;;-1:-1:-1;;;;;18925:38:0;;;;18946:6;;;;;18925:38;;;;;18974:6;:17;;-1:-1:-1;;;;;18974:17:0;;;;;-1:-1:-1;;;;;;18974:17:0;;;;;;;;;18770:229::o;9018:810::-;9078:4;9737:20;;9580:66;9777:15;;;;;:42;;;9808:11;9796:8;:23;;9777:42;9769:51;9018:810;-1:-1:-1;;;;9018:810:0:o
Swarm Source
bzzr://40b308e2af01060f2b41df0eed8e708021e549089b20ccd53ce7ef3c0cacd13b
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.