Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 25 from a total of 85 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Remove_liquidity | 12649175 | 1736 days ago | IN | 0 ETH | 0.00329891 | ||||
| Remove_liquidity | 12457849 | 1765 days ago | IN | 0 ETH | 0.00171833 | ||||
| Remove_liquidity | 12452352 | 1766 days ago | IN | 0 ETH | 0.01742172 | ||||
| Remove_liquidity | 12236050 | 1799 days ago | IN | 0 ETH | 0.04091703 | ||||
| Remove_liquidity | 12190013 | 1807 days ago | IN | 0 ETH | 0.04064223 | ||||
| Remove_liquidity | 12144007 | 1814 days ago | IN | 0 ETH | 0.03256365 | ||||
| Remove_liquidity | 12013411 | 1834 days ago | IN | 0 ETH | 0.04149786 | ||||
| Remove_liquidity | 11941977 | 1845 days ago | IN | 0 ETH | 0.03003337 | ||||
| Remove_liquidity | 11903499 | 1851 days ago | IN | 0 ETH | 0.09626332 | ||||
| Remove_liquidity | 11903333 | 1851 days ago | IN | 0 ETH | 0.04552682 | ||||
| Remove_liquidity | 11869906 | 1856 days ago | IN | 0 ETH | 0.03182772 | ||||
| Remove_liquidity | 11856025 | 1858 days ago | IN | 0 ETH | 0.05017626 | ||||
| Remove_liquidity | 11852025 | 1859 days ago | IN | 0 ETH | 0.03928473 | ||||
| Remove_liquidity | 11841501 | 1860 days ago | IN | 0 ETH | 0.04773816 | ||||
| Remove_liquidity | 11820393 | 1863 days ago | IN | 0 ETH | 0.04697088 | ||||
| Remove_liquidity | 11816789 | 1864 days ago | IN | 0 ETH | 0.1537272 | ||||
| Remove_liquidity | 11815776 | 1864 days ago | IN | 0 ETH | 0.06895137 | ||||
| Remove_liquidity | 11813971 | 1864 days ago | IN | 0 ETH | 0.06417555 | ||||
| Remove_liquidity | 11813965 | 1864 days ago | IN | 0 ETH | 0.0273306 | ||||
| Remove_liquidity | 11813113 | 1865 days ago | IN | 0 ETH | 0.02476298 | ||||
| Remove_liquidity | 11813101 | 1865 days ago | IN | 0 ETH | 0.04064451 | ||||
| Remove_liquidity | 11812078 | 1865 days ago | IN | 0 ETH | 0.04920263 | ||||
| Remove_liquidity | 11812072 | 1865 days ago | IN | 0 ETH | 0.04115859 | ||||
| Remove_liquidity | 11811002 | 1865 days ago | IN | 0 ETH | 0.055254 | ||||
| Remove_liquidity | 11810176 | 1865 days ago | IN | 0 ETH | 0.07273025 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SaffronPool
Compiler Version
v0.7.4+commit.3f05b770
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-01-27
*/
// File: contracts/interfaces/ISaffronBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.1;
interface ISaffronBase {
enum Tranche {S, AA, A}
enum LPTokenType {dsec, principal}
// Store values (balances, dsec, vdsec) with TrancheUint256
struct TrancheUint256 {
uint256 S;
uint256 AA;
uint256 A;
}
struct epoch_params {
uint256 start_date; // Time when the platform launched
uint256 duration; // Duration of epoch
}
}
// File: contracts/interfaces/ISaffronStrategy.sol
pragma solidity ^0.7.1;
interface ISaffronStrategy is ISaffronBase{
function deploy_all_capital() external;
function select_adapter_for_liquidity_removal() external returns(address);
function add_adapter(address adapter_address) external;
function add_pool(address pool_address) external;
function delete_adapters() external;
function set_governance(address to) external;
function get_adapter_address(uint256 adapter_index) external view returns(address);
function set_pool_SFI_reward(uint256 poolIndex, uint256 reward) external;
}
// File: contracts/interfaces/ISaffronPool.sol
pragma solidity ^0.7.1;
interface ISaffronPool is ISaffronBase {
function add_liquidity(uint256 amount, Tranche tranche) external;
function remove_liquidity(address v1_dsec_token_address, uint256 dsec_amount, address v1_principal_token_address, uint256 principal_amount) external;
function get_base_asset_address() external view returns(address);
function hourly_strategy(address adapter_address) external;
function wind_down_epoch(uint256 epoch, uint256 amount_sfi) external;
function set_governance(address to) external;
function get_epoch_cycle_params() external view returns (uint256, uint256);
function shutdown() external;
}
// File: contracts/interfaces/ISaffronAdapter.sol
pragma solidity ^0.7.1;
interface ISaffronAdapter is ISaffronBase {
function deploy_capital(uint256 amount) external;
function return_capital(uint256 base_asset_amount, address to) external;
function approve_transfer(address addr,uint256 amount) external;
function get_base_asset_address() external view returns(address);
function set_base_asset(address addr) external;
function get_holdings() external returns(uint256);
function get_interest(uint256 principal) external returns(uint256);
function set_governance(address to) external;
}
// File: contracts/lib/SafeMath.sol
pragma solidity ^0.7.1;
/**
* @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.
*/
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.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @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.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File: contracts/lib/IERC20.sol
pragma solidity ^0.7.1;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `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: contracts/lib/Context.sol
pragma solidity ^0.7.1;
/*
* @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.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File: contracts/lib/Address.sol
pragma solidity ^0.7.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.3._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.3._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File: contracts/lib/ERC20.sol
pragma solidity ^0.7.1;
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
using Address for address;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with
* a default value of 18.
*
* To select a different value for {decimals}, use {_setupDecimals}.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @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. This is the value {ERC20} uses, unless {_setupDecimals} is
* called.
*
* 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() public view returns (uint8) {
return _decimals;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20};
*
* Requirements:
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements
*
* - `to` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
*
* This is internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Sets {decimals} to a value other than the default one of 18.
*
* WARNING: This function should only be called from the constructor. Most
* applications that interact with token contracts will not expect
* {decimals} to ever change, and may work incorrectly if it does.
*/
function _setupDecimals(uint8 decimals_) internal {
_decimals = decimals_;
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be to transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
// File: contracts/lib/SafeERC20.sol
pragma solidity ^0.7.1;
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using 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));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// 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. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// File: contracts/SFI.sol
pragma solidity ^0.7.1;
contract SFI is ERC20 {
using SafeERC20 for IERC20;
address public governance;
address public SFI_minter;
uint256 public MAX_TOKENS = 100000 ether;
constructor (string memory name, string memory symbol) ERC20(name, symbol) {
// Initial governance is Saffron Deployer
governance = msg.sender;
}
function mint_SFI(address to, uint256 amount) public {
require(msg.sender == SFI_minter, "must be SFI_minter");
require(this.totalSupply() + amount < MAX_TOKENS, "cannot mint more than MAX_TOKENS");
_mint(to, amount);
}
function set_minter(address to) external {
require(msg.sender == governance, "must be governance");
SFI_minter = to;
}
function set_governance(address to) external {
require(msg.sender == governance, "must be governance");
governance = to;
}
event ErcSwept(address who, address to, address token, uint256 amount);
function erc_sweep(address _token, address _to) public {
require(msg.sender == governance, "must be governance");
IERC20 tkn = IERC20(_token);
uint256 tBal = tkn.balanceOf(address(this));
tkn.safeTransfer(_to, tBal);
emit ErcSwept(msg.sender, _to, _token, tBal);
}
}
// File: contracts/SaffronLPBalanceToken.sol
pragma solidity ^0.7.1;
contract SaffronLPBalanceToken is ERC20 {
address public pool_address;
constructor (string memory name, string memory symbol) ERC20(name, symbol) {
// Set pool_address to saffron pool that created token
pool_address = msg.sender;
}
// Allow creating new tranche tokens
function mint(address to, uint256 amount) public {
require(msg.sender == pool_address, "must be pool");
_mint(to, amount);
}
function burn(address account, uint256 amount) public {
require(msg.sender == pool_address, "must be pool");
_burn(account, amount);
}
function set_governance(address to) external {
require(msg.sender == pool_address, "must be pool");
pool_address = to;
}
}
// File: contracts/SaffronPool.sol
pragma solidity ^0.7.1;
contract SaffronPool is ISaffronPool {
using SafeMath for uint256;
using SafeERC20 for IERC20;
address public governance; // Governance (v3: add off-chain/on-chain governance)
address public base_asset_address; // Base asset managed by the pool (DAI, USDT, YFI...)
address public SFI_address; // SFI token
uint256 public pool_principal; // Current principal balance (added minus removed)
uint256 public pool_interest; // Current interest balance (redeemable by dsec tokens)
uint256 public tranche_A_multiplier; // Current yield multiplier for tranche A
uint256 public SFI_ratio; // Ratio of base asset to SFI necessary to join tranche A
bool public _shutdown = false; // v0, v1: shutdown the pool after the final capital deploy to prevent burning funds
/**** ADAPTERS ****/
address public best_adapter_address; // Current best adapter selected by strategy
uint256 public adapter_total_principal; // v0, v1: only one adapter
ISaffronAdapter[] private adapters; // v2: list of adapters
mapping(address=>uint256) private adapter_index; // v1: adapter contract address lookup for array indexes
/**** STRATEGY ****/
address public strategy;
/**** EPOCHS ****/
epoch_params public epoch_cycle = epoch_params({
start_date: 1604239200, // 11/01/2020 @ 2:00pm (UTC)
duration: 14 days // 1210000 seconds
});
/**** EPOCH INDEXED STORAGE ****/
uint256[] public epoch_principal; // Total principal owned by the pool (all tranches)
mapping(uint256=>bool) public epoch_wound_down; // True if epoch has been wound down already (governance)
/**** EPOCH-TRANCHE INDEXED STORAGE ****/
// Array of arrays, example: tranche_SFI_earned[epoch][Tranche.S]
address[3][] public dsec_token_addresses; // Address for each dsec token
address[3][] public principal_token_addresses; // Address for each principal token
uint256[3][] public tranche_total_dsec; // Total dsec (tokens + vdsec)
uint256[3][] public tranche_total_principal; // Total outstanding principal tokens
uint256[3][] public tranche_total_utilized; // Total utilized balance in each tranche
uint256[3][] public tranche_total_unutilized; // Total unutilized balance in each tranche
uint256[3][] public tranche_S_virtual_utilized; // Total utilized virtual balance taken from tranche S (first index unused)
uint256[3][] public tranche_S_virtual_unutilized; // Total unutilized virtual balance taken from tranche S (first index unused)
uint256[3][] public tranche_interest_earned; // Interest earned (calculated at wind_down_epoch)
uint256[3][] public tranche_SFI_earned; // Total SFI earned (minted at wind_down_epoch)
/**** SFI GENERATION ****/
// v0: pool generates SFI based on subsidy schedule
// v1: pool is distributed SFI generated by the strategy contract
// v1: pools each get an amount of SFI generated depending on the total liquidity added within each interval
TrancheUint256 public TRANCHE_SFI_MULTIPLIER = TrancheUint256({
S: 90000,
AA: 0,
A: 10000
});
/**** TRANCHE BALANCES ****/
// (v0 & v1: epochs are hard-forks)
// (v2: epoch rollover implemented)
// TrancheUint256 private eternal_unutilized_balances; // Unutilized balance (in base assets) for each tranche (assets held in this pool + assets held in platforms)
// TrancheUint256 private eternal_utilized_balances; // Balance for each tranche that is not held within this pool but instead held on a platform via an adapter
/**** SAFFRON LP TOKENS ****/
// If we just have a token address then we can look up epoch and tranche balance tokens using a mapping(address=>SaffronLPdsecInfo)
// LP tokens are dsec (redeemable for interest+SFI) and principal (redeemable for base asset) tokens
struct SaffronLPTokenInfo {
bool exists;
uint256 epoch;
Tranche tranche;
LPTokenType token_type;
}
mapping(address=>SaffronLPTokenInfo) private saffron_LP_token_info;
constructor(address _strategy, address _base_asset, address _SFI_address, uint256 _SFI_ratio, bool epoch_cycle_reset) {
governance = msg.sender;
base_asset_address = _base_asset;
strategy = _strategy;
SFI_address = _SFI_address;
tranche_A_multiplier = 10; // v1: start enhanced yield at 10X
SFI_ratio = _SFI_ratio; // v1: constant ratio
epoch_cycle.duration = (epoch_cycle_reset ? 20 minutes : 14 days); // Make testing previous epochs easier
epoch_cycle.start_date = (epoch_cycle_reset ? (block.timestamp) - (4 * epoch_cycle.duration) : 1604239200); // Make testing previous epochs easier
}
function new_epoch(uint256 epoch, address[] memory saffron_LP_dsec_token_addresses, address[] memory saffron_LP_principal_token_addresses) public {
require(tranche_total_principal.length == epoch, "improper new epoch");
require(governance == msg.sender, "must be governance");
epoch_principal.push(0);
tranche_total_dsec.push([0,0,0]);
tranche_total_principal.push([0,0,0]);
tranche_total_utilized.push([0,0,0]);
tranche_total_unutilized.push([0,0,0]);
tranche_S_virtual_utilized.push([0,0,0]);
tranche_S_virtual_unutilized.push([0,0,0]);
tranche_interest_earned.push([0,0,0]);
tranche_SFI_earned.push([0,0,0]);
dsec_token_addresses.push([ // Address for each dsec token
saffron_LP_dsec_token_addresses[uint256(Tranche.S)],
saffron_LP_dsec_token_addresses[uint256(Tranche.AA)],
saffron_LP_dsec_token_addresses[uint256(Tranche.A)]
]);
principal_token_addresses.push([ // Address for each principal token
saffron_LP_principal_token_addresses[uint256(Tranche.S)],
saffron_LP_principal_token_addresses[uint256(Tranche.AA)],
saffron_LP_principal_token_addresses[uint256(Tranche.A)]
]);
// Token info for looking up epoch and tranche of dsec tokens by token contract address
saffron_LP_token_info[saffron_LP_dsec_token_addresses[uint256(Tranche.S)]] = SaffronLPTokenInfo({
exists: true,
epoch: epoch,
tranche: Tranche.S,
token_type: LPTokenType.dsec
});
saffron_LP_token_info[saffron_LP_dsec_token_addresses[uint256(Tranche.AA)]] = SaffronLPTokenInfo({
exists: true,
epoch: epoch,
tranche: Tranche.AA,
token_type: LPTokenType.dsec
});
saffron_LP_token_info[saffron_LP_dsec_token_addresses[uint256(Tranche.A)]] = SaffronLPTokenInfo({
exists: true,
epoch: epoch,
tranche: Tranche.A,
token_type: LPTokenType.dsec
});
// for looking up epoch and tranche of PRINCIPAL tokens by token contract address
saffron_LP_token_info[saffron_LP_principal_token_addresses[uint256(Tranche.S)]] = SaffronLPTokenInfo({
exists: true,
epoch: epoch,
tranche: Tranche.S,
token_type: LPTokenType.principal
});
saffron_LP_token_info[saffron_LP_principal_token_addresses[uint256(Tranche.AA)]] = SaffronLPTokenInfo({
exists: true,
epoch: epoch,
tranche: Tranche.AA,
token_type: LPTokenType.principal
});
saffron_LP_token_info[saffron_LP_principal_token_addresses[uint256(Tranche.A)]] = SaffronLPTokenInfo({
exists: true,
epoch: epoch,
tranche: Tranche.A,
token_type: LPTokenType.principal
});
}
struct BalanceVars {
// Tranche balance
uint256 deposit; // User deposit
uint256 capacity; // Capacity for user's intended tranche
uint256 change; // Change from deposit - capacity
// S tranche specific vars
uint256 consumed; // Total consumed
uint256 utilized_consumed;
uint256 unutilized_consumed;
uint256 available_utilized;
uint256 available_unutilized;
}
event TrancheBalance(uint256 tranche, uint256 amount, uint256 deposit, uint256 capacity, uint256 change, uint256 consumed, uint256 utilized_consumed, uint256 unutilized_consumed, uint256 available_utilized, uint256 available_unutilized);
event DsecGeneration(uint256 time_remaining, uint256 amount, uint256 dsec, address dsec_address, uint256 epoch, uint256 tranche, address user_address, address principal_token_addr);
event AddLiquidity(uint256 new_pool_principal, uint256 new_epoch_principal, uint256 new_eternal_balance, uint256 new_tranche_principal, uint256 new_tranche_dsec);
// LP user adds liquidity to the pool
// Pre-requisite (front-end): have user approve transfer on front-end to base asset using our contract address
function add_liquidity(uint256 amount, Tranche tranche) external override {
require(!_shutdown, "pool shutdown");
require(tranche == Tranche.S || tranche == Tranche.A, "v1: can't add_liquidity into AA tranche");
uint256 epoch = get_current_epoch();
require(amount != 0, "can't add 0");
require(epoch == 6, "v1.6: must be epoch 6 only");
BalanceVars memory bv = BalanceVars({
deposit: 0,
capacity: 0,
change: 0,
consumed: 0,
utilized_consumed: 0,
unutilized_consumed: 0,
available_utilized: 0,
available_unutilized: 0
});
(bv.available_utilized, bv.available_unutilized) = get_available_S_balances();
if (tranche == Tranche.S) {
tranche_total_unutilized[epoch][uint256(Tranche.S)] = tranche_total_unutilized[epoch][uint256(Tranche.S)].add(amount);
bv.deposit = amount;
}
// if (tranche == Tranche.AA) {} // v1: AA tranche disabled (S tranche is effectively AA)
if (tranche == Tranche.A) {
// Find capacity for S tranche to facilitate a deposit into A. Deposit is min(principal, capacity): restricted by the user's capital or S tranche capacity
bv.capacity = (bv.available_utilized.add(bv.available_unutilized)).div(tranche_A_multiplier);
bv.deposit = (amount < bv.capacity) ? amount : bv.capacity;
bv.consumed = bv.deposit.mul(tranche_A_multiplier);
if (bv.consumed <= bv.available_utilized) {
// Take capacity from tranche S utilized first and give virtual utilized balance to AA
bv.utilized_consumed = bv.consumed;
} else {
// Take capacity from tranche S utilized and tranche S unutilized and give virtual utilized/unutilized balances to AA
bv.utilized_consumed = bv.available_utilized;
bv.unutilized_consumed = bv.consumed.sub(bv.utilized_consumed);
tranche_S_virtual_unutilized[epoch][uint256(Tranche.AA)] = tranche_S_virtual_unutilized[epoch][uint256(Tranche.AA)].add(bv.unutilized_consumed);
}
tranche_S_virtual_utilized[epoch][uint256(Tranche.AA)] = tranche_S_virtual_utilized[epoch][uint256(Tranche.AA)].add(bv.utilized_consumed);
if (bv.deposit < amount) bv.change = amount.sub(bv.deposit);
}
// Calculate the dsec for deposited DAI
uint256 dsec = bv.deposit.mul(get_seconds_until_epoch_end(epoch));
// Update pool principal eternal and epoch state
pool_principal = pool_principal.add(bv.deposit); // Add DAI to principal totals
epoch_principal[epoch] = epoch_principal[epoch].add(bv.deposit); // Add DAI total balance for epoch
// Update dsec and principal balance state
tranche_total_dsec[epoch][uint256(tranche)] = tranche_total_dsec[epoch][uint256(tranche)].add(dsec);
tranche_total_principal[epoch][uint256(tranche)] = tranche_total_principal[epoch][uint256(tranche)].add(bv.deposit);
// Transfer DAI from LP to pool
IERC20(base_asset_address).safeTransferFrom(msg.sender, address(this), bv.deposit);
if (tranche == Tranche.A) IERC20(SFI_address).safeTransferFrom(msg.sender, address(this), bv.deposit * 1 ether / SFI_ratio);
// Mint Saffron LP epoch 1 tranche dsec tokens and transfer them to sender
SaffronLPBalanceToken(dsec_token_addresses[epoch][uint256(tranche)]).mint(msg.sender, dsec);
// Mint Saffron LP epoch 1 tranche principal tokens and transfer them to sender
SaffronLPBalanceToken(principal_token_addresses[epoch][uint256(tranche)]).mint(msg.sender, bv.deposit);
emit TrancheBalance(uint256(tranche), bv.deposit, bv.deposit, bv.capacity, bv.change, bv.consumed, bv.utilized_consumed, bv.unutilized_consumed, bv.available_utilized, bv.available_unutilized);
emit DsecGeneration(get_seconds_until_epoch_end(epoch), bv.deposit, dsec, dsec_token_addresses[epoch][uint256(tranche)], epoch, uint256(tranche), msg.sender, principal_token_addresses[epoch][uint256(tranche)]);
emit AddLiquidity(pool_principal, epoch_principal[epoch], 0, tranche_total_principal[epoch][uint256(tranche)], tranche_total_dsec[epoch][uint256(tranche)]);
}
event WindDownEpochSFI(uint256 previous_epoch, uint256 S_SFI, uint256 AA_SFI, uint256 A_SFI);
event WindDownEpochState(uint256 epoch, uint256 tranche_S_interest, uint256 tranche_AA_interest, uint256 tranche_A_interest, uint256 tranche_SFI_earnings_S, uint256 tranche_SFI_earnings_AA, uint256 tranche_SFI_earnings_A);
struct WindDownVars {
uint256 previous_epoch;
uint256 epoch_interest;
uint256 epoch_dsec;
uint256 tranche_A_interest_ratio;
uint256 tranche_A_interest;
uint256 tranche_S_interest;
}
function wind_down_epoch(uint256 epoch, uint256 amount_sfi) public override {
require(msg.sender == strategy, "must be strategy");
require(!epoch_wound_down[epoch], "epoch already wound down");
uint256 current_epoch = get_current_epoch();
require(epoch < current_epoch, "cannot wind down future epoch");
WindDownVars memory wind_down = WindDownVars({
previous_epoch: 0,
epoch_interest: 0,
epoch_dsec: 0,
tranche_A_interest_ratio: 0,
tranche_A_interest: 0,
tranche_S_interest: 0
});
wind_down.previous_epoch = current_epoch - 1;
require(block.timestamp >= get_epoch_end(wind_down.previous_epoch), "can't call before epoch ended");
// Calculate SFI earnings per tranche
tranche_SFI_earned[epoch][uint256(Tranche.S)] = TRANCHE_SFI_MULTIPLIER.S.mul(amount_sfi).div(100000);
tranche_SFI_earned[epoch][uint256(Tranche.AA)] = TRANCHE_SFI_MULTIPLIER.AA.mul(amount_sfi).div(100000);
tranche_SFI_earned[epoch][uint256(Tranche.A)] = TRANCHE_SFI_MULTIPLIER.A.mul(amount_sfi).div(100000);
emit WindDownEpochSFI(wind_down.previous_epoch, tranche_SFI_earned[epoch][uint256(Tranche.S)], tranche_SFI_earned[epoch][uint256(Tranche.AA)], tranche_SFI_earned[epoch][uint256(Tranche.A)]);
// Calculate interest earnings per tranche
// Wind down will calculate interest and SFI earned by each tranche for the epoch which has ended
// Liquidity cannot be removed until wind_down_epoch is called and epoch_wound_down[epoch] is set to true
// Calculate pool_interest
// v0, v1: we only have one adapter
ISaffronAdapter adapter = ISaffronAdapter(best_adapter_address);
wind_down.epoch_interest = adapter.get_interest(adapter_total_principal);
pool_interest = pool_interest.add(wind_down.epoch_interest);
// Total dsec
// TODO: assert (dsec.totalSupply == epoch_dsec)
wind_down.epoch_dsec = tranche_total_dsec[epoch][uint256(Tranche.S)].add(tranche_total_dsec[epoch][uint256(Tranche.A)]);
wind_down.tranche_A_interest_ratio = tranche_total_dsec[epoch][uint256(Tranche.A)].mul(1 ether).div(wind_down.epoch_dsec);
// Calculate tranche share of interest
wind_down.tranche_A_interest = (wind_down.epoch_interest.mul(wind_down.tranche_A_interest_ratio).div(1 ether)).mul(tranche_A_multiplier);
wind_down.tranche_S_interest = wind_down.epoch_interest.sub(wind_down.tranche_A_interest);
// Update state for remove_liquidity
tranche_interest_earned[epoch][uint256(Tranche.S)] = wind_down.tranche_S_interest;
tranche_interest_earned[epoch][uint256(Tranche.AA)] = 0;
tranche_interest_earned[epoch][uint256(Tranche.A)] = wind_down.tranche_A_interest;
// Distribute SFI earnings to S tranche based on S tranche % share of dsec via vdsec
emit WindDownEpochState(epoch, wind_down.tranche_S_interest, 0, wind_down.tranche_A_interest, uint256(tranche_SFI_earned[epoch][uint256(Tranche.S)]), uint256(tranche_SFI_earned[epoch][uint256(Tranche.AA)]), uint256(tranche_SFI_earned[epoch][uint256(Tranche.A)]));
epoch_wound_down[epoch] = true;
delete wind_down;
}
event RemoveLiquidityDsec(uint256 dsec_percent, uint256 interest_owned, uint256 SFI_owned);
event RemoveLiquidityPrincipal(uint256 principal);
function remove_liquidity(address dsec_token_address, uint256 dsec_amount, address principal_token_address, uint256 principal_amount) external override {
require(dsec_amount > 0 || principal_amount > 0, "can't remove 0");
ISaffronAdapter best_adapter = ISaffronAdapter(best_adapter_address);
uint256 interest_owned;
uint256 SFI_earn;
uint256 SFI_return;
uint256 dsec_percent;
// Update state for removal via dsec token
if (dsec_token_address != address(0x0) && dsec_amount > 0) {
// Get info about the v1 dsec token from its address and check that it exists
SaffronLPTokenInfo memory token_info = saffron_LP_token_info[dsec_token_address];
require(token_info.exists, "balance token lookup failed");
SaffronLPBalanceToken sbt = SaffronLPBalanceToken(dsec_token_address);
require(sbt.balanceOf(msg.sender) >= dsec_amount, "insufficient dsec balance");
// Token epoch must be a past epoch
uint256 token_epoch = token_info.epoch;
require(token_info.token_type == LPTokenType.dsec, "bad dsec address");
require(token_epoch == 6, "v1.6: bal token epoch must be 6");
require(epoch_wound_down[token_epoch], "can't remove from wound up epoch");
uint256 tranche_dsec = tranche_total_dsec[token_epoch][uint256(token_info.tranche)];
// Dsec gives user claim over a tranche's earned SFI and interest
dsec_percent = (tranche_dsec == 0) ? 0 : dsec_amount.mul(1 ether).div(tranche_dsec);
interest_owned = tranche_interest_earned[token_epoch][uint256(token_info.tranche)].mul(dsec_percent) / 1 ether;
SFI_earn = tranche_SFI_earned[token_epoch][uint256(token_info.tranche)].mul(dsec_percent) / 1 ether;
tranche_interest_earned[token_epoch][uint256(token_info.tranche)] = tranche_interest_earned[token_epoch][uint256(token_info.tranche)].sub(interest_owned);
tranche_SFI_earned[token_epoch][uint256(token_info.tranche)] = tranche_SFI_earned[token_epoch][uint256(token_info.tranche)].sub(SFI_earn);
tranche_total_dsec[token_epoch][uint256(token_info.tranche)] = tranche_total_dsec[token_epoch][uint256(token_info.tranche)].sub(dsec_amount);
pool_interest = pool_interest.sub(interest_owned);
}
// Update state for removal via principal token
if (principal_token_address != address(0x0) && principal_amount > 0) {
// Get info about the v1 dsec token from its address and check that it exists
SaffronLPTokenInfo memory token_info = saffron_LP_token_info[principal_token_address];
require(token_info.exists, "balance token info lookup failed");
SaffronLPBalanceToken sbt = SaffronLPBalanceToken(principal_token_address);
require(sbt.balanceOf(msg.sender) >= principal_amount, "insufficient principal balance");
// Token epoch must be a past epoch
uint256 token_epoch = token_info.epoch;
require(token_info.token_type == LPTokenType.principal, "bad balance token address");
require(token_epoch == 6, "v1.6: bal token epoch must be 6");
require(epoch_wound_down[token_epoch], "can't remove from wound up epoch");
tranche_total_principal[token_epoch][uint256(token_info.tranche)] = tranche_total_principal[token_epoch][uint256(token_info.tranche)].sub(principal_amount);
epoch_principal[token_epoch] = epoch_principal[token_epoch].sub(principal_amount);
pool_principal = pool_principal.sub(principal_amount);
adapter_total_principal = adapter_total_principal.sub(principal_amount);
if (token_info.tranche == Tranche.A) SFI_return = principal_amount * 1 ether / SFI_ratio;
}
// Transfer
if (dsec_token_address != address(0x0) && dsec_amount > 0) {
SaffronLPBalanceToken sbt = SaffronLPBalanceToken(dsec_token_address);
require(sbt.balanceOf(msg.sender) >= dsec_amount, "insufficient dsec balance");
sbt.burn(msg.sender, dsec_amount);
if (interest_owned > 0) {
best_adapter.return_capital(interest_owned, msg.sender);
}
IERC20(SFI_address).safeTransfer(msg.sender, SFI_earn);
emit RemoveLiquidityDsec(dsec_percent, interest_owned, SFI_earn);
}
if (principal_token_address != address(0x0) && principal_amount > 0) {
SaffronLPBalanceToken sbt = SaffronLPBalanceToken(principal_token_address);
require(sbt.balanceOf(msg.sender) >= principal_amount, "insufficient principal balance");
sbt.burn(msg.sender, principal_amount);
best_adapter.return_capital(principal_amount, msg.sender);
IERC20(SFI_address).safeTransfer(msg.sender, SFI_return);
emit RemoveLiquidityPrincipal(principal_amount);
}
require((dsec_token_address != address(0x0) && dsec_amount > 0) || (principal_token_address != address(0x0) && principal_amount > 0), "no action performed");
}
// Strategy contract calls this to deploy capital to platforms
event StrategicDeploy(address adapter_address, uint256 amount, uint256 epoch);
function hourly_strategy(address adapter_address) external override {
require(msg.sender == strategy, "must be strategy");
require(!_shutdown, "pool shutdown");
uint256 epoch = get_current_epoch();
best_adapter_address = adapter_address;
ISaffronAdapter best_adapter = ISaffronAdapter(adapter_address);
uint256 amount = IERC20(base_asset_address).balanceOf(address(this));
// Update utilized/unutilized epoch-tranche state
tranche_total_utilized[epoch][uint256(Tranche.S)] = tranche_total_utilized[epoch][uint256(Tranche.S)].add(tranche_total_unutilized[epoch][uint256(Tranche.S)]);
tranche_total_utilized[epoch][uint256(Tranche.A)] = tranche_total_utilized[epoch][uint256(Tranche.A)].add(tranche_total_unutilized[epoch][uint256(Tranche.A)]);
tranche_S_virtual_utilized[epoch][uint256(Tranche.AA)] = tranche_S_virtual_utilized[epoch][uint256(Tranche.AA)].add(tranche_S_virtual_unutilized[epoch][uint256(Tranche.AA)]);
tranche_total_unutilized[epoch][uint256(Tranche.S)] = 0;
tranche_total_unutilized[epoch][uint256(Tranche.A)] = 0;
tranche_S_virtual_unutilized[epoch][uint256(Tranche.AA)] = 0;
// Add principal to adapter total
adapter_total_principal = adapter_total_principal.add(amount);
emit StrategicDeploy(adapter_address, amount, epoch);
// Move base assets to adapter and deploy
IERC20(base_asset_address).safeTransfer(adapter_address, amount);
best_adapter.deploy_capital(amount);
}
function shutdown() external override {
require(msg.sender == strategy || msg.sender == governance, "must be strategy");
require(block.timestamp > get_epoch_end(1) - 1 days, "trying to shutdown too early");
_shutdown = true;
}
/*** GOVERNANCE ***/
function set_governance(address to) external override {
require(msg.sender == governance, "must be governance");
governance = to;
}
function set_best_adapter(address to) external {
require(msg.sender == governance, "must be governance");
best_adapter_address = to;
}
/*** TIME UTILITY FUNCTIONS ***/
function get_epoch_end(uint256 epoch) public view returns (uint256) {
return epoch_cycle.start_date.add(epoch.add(1).mul(epoch_cycle.duration));
}
function get_current_epoch() public view returns (uint256) {
require(block.timestamp > epoch_cycle.start_date, "before epoch 0");
return (block.timestamp - epoch_cycle.start_date) / epoch_cycle.duration;
}
function get_seconds_until_epoch_end(uint256 epoch) public view returns (uint256) {
return epoch_cycle.start_date.add(epoch.add(1).mul(epoch_cycle.duration)).sub(block.timestamp);
}
/*** GETTERS ***/
function get_available_S_balances() public view returns(uint256, uint256) {
uint256 epoch = get_current_epoch();
uint256 AA_A_utilized = tranche_S_virtual_utilized[epoch][uint256(Tranche.A)].add(tranche_S_virtual_utilized[epoch][uint256(Tranche.AA)]);
uint256 AA_A_unutilized = tranche_S_virtual_unutilized[epoch][uint256(Tranche.A)].add(tranche_S_virtual_unutilized[epoch][uint256(Tranche.AA)]);
uint256 S_utilized = tranche_total_utilized[epoch][uint256(Tranche.S)];
uint256 S_unutilized = tranche_total_unutilized[epoch][uint256(Tranche.S)];
return ((S_utilized > AA_A_utilized ? S_utilized - AA_A_utilized : 0), (S_unutilized > AA_A_unutilized ? S_unutilized - AA_A_unutilized : 0));
}
function get_epoch_cycle_params() external view override returns (uint256, uint256) {
return (epoch_cycle.start_date, epoch_cycle.duration);
}
function get_base_asset_address() external view override returns(address) {
return base_asset_address;
}
//***** ADAPTER FUNCTIONS *****//
// Delete adapters (v0: for v0 wind-down)
function delete_adapters() external {
require(msg.sender == governance, "must be governance");
require(block.timestamp > epoch_cycle.start_date + 10 weeks, "too soon");
delete adapters;
}
event ErcSwept(address who, address to, address token, uint256 amount);
function erc_sweep(address _token, address _to) public {
require(msg.sender == governance, "must be governance");
require(_token != base_asset_address && _token != SFI_address, "cannot sweep pool assets");
IERC20 tkn = IERC20(_token);
uint256 tBal = tkn.balanceOf(address(this));
tkn.safeTransfer(_to, tBal);
emit ErcSwept(msg.sender, _to, _token, tBal);
}
event Swept(address who, address to, uint256 sfiBal, uint256 baseBal);
function sweep(address _to) public {
require(msg.sender == governance, "must be governance");
IERC20 tkn = IERC20(address(SFI_address));
uint256 sfiBal = tkn.balanceOf(address(this));
tkn.safeTransfer(_to, sfiBal);
IERC20 base = IERC20(address(base_asset_address));
uint256 baseBal = base.balanceOf(address(this));
base.safeTransfer(_to, baseBal);
emit Swept(msg.sender, _to, sfiBal, baseBal);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address","name":"_base_asset","type":"address"},{"internalType":"address","name":"_SFI_address","type":"address"},{"internalType":"uint256","name":"_SFI_ratio","type":"uint256"},{"internalType":"bool","name":"epoch_cycle_reset","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"new_pool_principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_epoch_principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_eternal_balance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_tranche_principal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_tranche_dsec","type":"uint256"}],"name":"AddLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time_remaining","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dsec","type":"uint256"},{"indexed":false,"internalType":"address","name":"dsec_address","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tranche","type":"uint256"},{"indexed":false,"internalType":"address","name":"user_address","type":"address"},{"indexed":false,"internalType":"address","name":"principal_token_addr","type":"address"}],"name":"DsecGeneration","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ErcSwept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dsec_percent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interest_owned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"SFI_owned","type":"uint256"}],"name":"RemoveLiquidityDsec","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"principal","type":"uint256"}],"name":"RemoveLiquidityPrincipal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"adapter_address","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"StrategicDeploy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"sfiBal","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseBal","type":"uint256"}],"name":"Swept","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tranche","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deposit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"change","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"consumed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"utilized_consumed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unutilized_consumed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"available_utilized","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"available_unutilized","type":"uint256"}],"name":"TrancheBalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previous_epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"S_SFI","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"AA_SFI","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"A_SFI","type":"uint256"}],"name":"WindDownEpochSFI","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tranche_S_interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tranche_AA_interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tranche_A_interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tranche_SFI_earnings_S","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tranche_SFI_earnings_AA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tranche_SFI_earnings_A","type":"uint256"}],"name":"WindDownEpochState","type":"event"},{"inputs":[],"name":"SFI_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SFI_ratio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANCHE_SFI_MULTIPLIER","outputs":[{"internalType":"uint256","name":"S","type":"uint256"},{"internalType":"uint256","name":"AA","type":"uint256"},{"internalType":"uint256","name":"A","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_shutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adapter_total_principal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"enum ISaffronBase.Tranche","name":"tranche","type":"uint8"}],"name":"add_liquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"base_asset_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"best_adapter_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delete_adapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"dsec_token_addresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epoch_cycle","outputs":[{"internalType":"uint256","name":"start_date","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"epoch_principal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"epoch_wound_down","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"erc_sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"get_available_S_balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_base_asset_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_current_epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_epoch_cycle_params","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"get_epoch_end","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"get_seconds_until_epoch_end","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adapter_address","type":"address"}],"name":"hourly_strategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"address[]","name":"saffron_LP_dsec_token_addresses","type":"address[]"},{"internalType":"address[]","name":"saffron_LP_principal_token_addresses","type":"address[]"}],"name":"new_epoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pool_interest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool_principal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"principal_token_addresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dsec_token_address","type":"address"},{"internalType":"uint256","name":"dsec_amount","type":"uint256"},{"internalType":"address","name":"principal_token_address","type":"address"},{"internalType":"uint256","name":"principal_amount","type":"uint256"}],"name":"remove_liquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"set_best_adapter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"set_governance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tranche_A_multiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranche_SFI_earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranche_S_virtual_unutilized","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranche_S_virtual_utilized","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranche_interest_earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranche_total_dsec","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranche_total_principal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranche_total_unutilized","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranche_total_utilized","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"amount_sfi","type":"uint256"}],"name":"wind_down_epoch","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6007805460ff19169055635f9ebf6060808190526212750060a0819052600c91909155600d5561012060405262015f9060c0819052600060e0819052612710610100819052601a92909255601b55601c553480156200005d57600080fd5b506040516200517838038062005178833981810160405260a08110156200008357600080fd5b50805160208201516040830151606084015160809094015160008054336001600160a01b0319918216179091556001805482166001600160a01b0380871691909117909155600b8054831682881617905560028054909216908416179055600a6005556006859055929391929091908062000102576212750062000106565b6104b05b62ffffff16600d55806200011f57635f9ebf6062000128565b600d5460040242035b600c55505050505061503880620001406000396000f3fe608060405234801561001057600080fd5b50600436106102de5760003560e01c80637425ffec11610186578063ac3dbb12116100e3578063df4cbfd811610097578063ebd485fc11610071578063ebd485fc1461086d578063f034c18d1461088a578063fc0e74d114610892576102de565b8063df4cbfd814610840578063dfe537961461085d578063e653be7414610865576102de565b8063bc87f62c116100c8578063bc87f62c146107f2578063c6b483ab14610815578063d2e7a1bb1461081d576102de565b8063ac3dbb12146107e2578063bc4ce844146107ea576102de565b80639b53e3661161013a578063a684b5991161011f578063a684b599146107b5578063a72b6c30146107d2578063a8c62e76146107da576102de565b80639b53e3661461076c578063a20f527214610792576102de565b8063837a9bc71161016b578063837a9bc71461071e57806384518744146107265780639392f6f214610749576102de565b80637425ffec146106d857806380e0f15f146106fb576102de565b806348373cc61161023f5780635b1caa2f116101f35780636bd6f696116101cd5780636bd6f6961461068a57806370cdf476146106ad57806370d4ac4e146106d0576102de565b80635b1caa2f1461050d5780636120f0dc146105545780636acc25be14610682576102de565b806354d0c8a01161022457806354d0c8a0146104da578063580f346f146104e25780635aa6e67514610505576102de565b806348373cc61461048b5780634c1a4259146104a7576102de565b80630f78dac31161029657806322cef9d31161027b57806322cef9d3146104405780632a0ccc88146104485780632b666fcf14610450576102de565b80630f78dac3146103f95780631816f3141461041f576102de565b8063070313fa116102c7578063070313fa1461034b5780630bbb0c581461037e5780630efb8dbd146103ca576102de565b806301681a62146102e357806302b6215914610318575b600080fd5b610316600480360360208110156102f957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661089a565b005b6103166004803603602081101561032e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b0d565b6103166004803603602081101561036157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610bdf565b6103a16004803603604081101561039457600080fd5b5080359060200135610cac565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6103e7600480360360208110156103e057600080fd5b5035610cf7565b60408051918252519081900360200190f35b6103166004803603604081101561040f57600080fd5b508035906020013560ff16610d25565b6104276116ba565b6040805192835260208301919091528051918290030190f35b6103a16116c3565b6103a16116e4565b6103166004803603604081101561046657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611700565b61049361195a565b604080519115158252519081900360200190f35b610316600480360360208110156104bd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611963565b6103a1611dba565b6103e7600480360360408110156104f857600080fd5b5080359060200135611dd6565b6103a1611e0b565b6103166004803603608081101561052357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135169060600135611e27565b6103166004803603606081101561056a57600080fd5b8135919081019060408101602082013564010000000081111561058c57600080fd5b82018360208201111561059e57600080fd5b803590602001918460208302840111640100000000831117156105c057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929594936020810193503591505064010000000081111561061057600080fd5b82018360208201111561062257600080fd5b8035906020019184602083028401116401000000008311171561064457600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612f4b945050505050565b6103e7613b2b565b6103e7600480360360408110156106a057600080fd5b5080359060200135613b31565b6103a1600480360360408110156106c357600080fd5b5080359060200135613b41565b6103e7613b51565b6103e7600480360360408110156106ee57600080fd5b5080359060200135613b57565b6103166004803603604081101561071157600080fd5b5080359060200135613b67565b6103e76141ff565b6103e76004803603604081101561073c57600080fd5b5080359060200135614287565b6103e76004803603604081101561075f57600080fd5b5080359060200135614297565b6107746142a7565b60408051938452602084019290925282820152519081900360600190f35b6103e7600480360360408110156107a857600080fd5b50803590602001356142b3565b610493600480360360208110156107cb57600080fd5b50356142c3565b6103a16142d8565b6103a16142f4565b6103e7614310565b6103e7614316565b6103e76004803603604081101561080857600080fd5b508035906020013561431c565b6103e761432c565b6103e76004803603604081101561083357600080fd5b5080359060200135614332565b6103e76004803603602081101561085657600080fd5b5035614342565b61042761436e565b61031661445e565b6103e76004803603602081101561088357600080fd5b5035614567565b610427614588565b610316614592565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff9092169160009183916370a0823191602480820192602092909190829003018186803b15801561099657600080fd5b505afa1580156109aa573d6000803e3d6000fd5b505050506040513d60208110156109c057600080fd5b505190506109e573ffffffffffffffffffffffffffffffffffffffff831684836146e3565b600154604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff9092169160009183916370a0823191602480820192602092909190829003018186803b158015610a5b57600080fd5b505afa158015610a6f573d6000803e3d6000fd5b505050506040513d6020811015610a8557600080fd5b50519050610aaa73ffffffffffffffffffffffffffffffffffffffff831686836146e3565b6040805133815273ffffffffffffffffffffffffffffffffffffffff871660208201528082018590526060810183905290517f8496dda4d04919fec296be83f4d7d178dafb7c0d3abe1553c092f1466e8f29289181900360800190a15050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b9357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b6007805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c6557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60108281548110610cbc57600080fd5b90600052602060002090600302018160038110610cd857600080fd5b015473ffffffffffffffffffffffffffffffffffffffff169150829050565b600d54600090610d1f90610d1690610d10856001614775565b906147f0565b600c5490614775565b92915050565b60075460ff1615610d9757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f706f6f6c2073687574646f776e00000000000000000000000000000000000000604482015290519081900360640190fd5b6000816002811115610da557fe5b1480610dbc57506002816002811115610dba57fe5b145b610e11576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180614fb26027913960400191505060405180910390fd5b6000610e1b6141ff565b905082610e8957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f63616e2774206164642030000000000000000000000000000000000000000000604482015290519081900360640190fd5b80600614610ef857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f76312e363a206d7573742062652065706f63682036206f6e6c79000000000000604482015290519081900360640190fd5b610f00614de2565b6040518061010001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152509050610f4c61436e565b60e083015260c08201526000836002811115610f6457fe5b1415610fc157610f9e8460158481548110610f7b57fe5b600091825260208220600390910201905b60038110610f9657fe5b015490614775565b60158381548110610fab57fe5b6000918252602082206003919091020101558381525b6002836002811115610fcf57fe5b141561110557610ffc600554610ff68360e001518460c0015161477590919063ffffffff16565b90614863565b602082018190528410611013578060200151611015565b835b80825260055461102591906147f0565b6060820181905260c08201511061104557606081015160808201526110b3565b60c081015160808201819052606082015161105f916148a5565b60a08201819052601780546110919291908590811061107a57fe5b600091825260209091206003909102016001610f8c565b6017838154811061109e57fe5b60009182526020909120600390910201600101555b6110c881608001516016848154811061107a57fe5b601683815481106110d557fe5b600091825260209091206003909102016001015580518411156111055780516110ff9085906148a5565b60408201525b600061111b61111384614342565b8351906147f0565b825160035491925061112d9190614775565b6003558151600e805461115f9291908690811061114657fe5b906000526020600020015461477590919063ffffffff16565b600e848154811061116c57fe5b90600052602060002001819055506111a5816012858154811061118b57fe5b9060005260206000209060030201866002811115610f8c57fe5b601284815481106111b257fe5b90600052602060002090600302018560028111156111cc57fe5b600381106111d657fe5b01558151601380546111ee9291908690811061118b57fe5b601384815481106111fb57fe5b906000526020600020906003020185600281111561121557fe5b6003811061121f57fe5b0155815160015461124c9173ffffffffffffffffffffffffffffffffffffffff90911690339030906148e7565b600284600281111561125a57fe5b14156112a1576112a133306006548560000151670de0b6b3a7640000028161127e57fe5b60025473ffffffffffffffffffffffffffffffffffffffff1693929190046148e7565b601083815481106112ae57fe5b90600052602060002090600302018460028111156112c857fe5b600381106112d257fe5b0154604080517f40c10f1900000000000000000000000000000000000000000000000000000000815233600482015260248101849052905173ffffffffffffffffffffffffffffffffffffffff909216916340c10f199160448082019260009290919082900301818387803b15801561134a57600080fd5b505af115801561135e573d6000803e3d6000fd5b505050506011838154811061136f57fe5b906000526020600020906003020184600281111561138957fe5b6003811061139357fe5b01548251604080517f40c10f1900000000000000000000000000000000000000000000000000000000815233600482015260248101929092525173ffffffffffffffffffffffffffffffffffffffff909216916340c10f199160448082019260009290919082900301818387803b15801561140d57600080fd5b505af1158015611421573d6000803e3d6000fd5b505050507f058587cdc5efcef45583dc39e6884e853b5c5aef182afe72ca96db6fa1c85c2184600281111561145257fe5b8360000151846000015185602001518660400151876060015188608001518960a001518a60c001518b60e00151604051808b81526020018a81526020018981526020018881526020018781526020018681526020018581526020018481526020018381526020018281526020019a505050505050505050505060405180910390a17fc7d2d1a5a726dc6005e76316c12eb5ee642296cc38c1b996651599995a480f3c6114fd84614342565b8360000151836010878154811061151057fe5b906000526020600020906003020188600281111561152a57fe5b6003811061153457fe5b015473ffffffffffffffffffffffffffffffffffffffff168789600281111561155957fe5b3360118b8154811061156757fe5b90600052602060002090600302018c600281111561158157fe5b6003811061158b57fe5b01546040805198895260208901979097528787019590955273ffffffffffffffffffffffffffffffffffffffff9384166060880152608087019290925260a0860152811660c08501521660e083015251908190036101000190a17f1d69fb63e4692a6ae9a9b249224c389569da92d8e2e96243d71fd6b3bc3055d9600354600e858154811061161657fe5b906000526020600020015460006013878154811061163057fe5b906000526020600020906003020188600281111561164a57fe5b6003811061165457fe5b01546012888154811061166357fe5b906000526020600020906003020189600281111561167d57fe5b6003811061168757fe5b01546040805195865260208601949094528484019290925260608401526080830152519081900360a00190a15050505050565b600c54600d5482565b600754610100900473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16331461178657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b60015473ffffffffffffffffffffffffffffffffffffffff8381169116148015906117cc575060025473ffffffffffffffffffffffffffffffffffffffff838116911614155b61183757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616e6e6f7420737765657020706f6f6c206173736574730000000000000000604482015290519081900360640190fd5b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051839160009173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b1580156118a857600080fd5b505afa1580156118bc573d6000803e3d6000fd5b505050506040513d60208110156118d257600080fd5b505190506118f773ffffffffffffffffffffffffffffffffffffffff831684836146e3565b6040805133815273ffffffffffffffffffffffffffffffffffffffff80861660208301528616818301526060810183905290517f2c4e64c7c0957a81c0076a0a3f3c7d9f0a5d6158292071c794436f829d12cfb79181900360800190a150505050565b60075460ff1681565b600b5473ffffffffffffffffffffffffffffffffffffffff1633146119e957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6d75737420626520737472617465677900000000000000000000000000000000604482015290519081900360640190fd5b60075460ff1615611a5b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f706f6f6c2073687574646f776e00000000000000000000000000000000000000604482015290519081900360640190fd5b6000611a656141ff565b6007805473ffffffffffffffffffffffffffffffffffffffff808616610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff90921691909117909155600154604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051939450859360009392909216916370a0823191602480820192602092909190829003018186803b158015611b1557600080fd5b505afa158015611b29573d6000803e3d6000fd5b505050506040513d6020811015611b3f57600080fd5b505160158054919250611b759185908110611b5657fe5b60009182526020822060039190910201015460148581548110610f7b57fe5b60148481548110611b8257fe5b600091825260208220600391909102010181905550611bdf60158481548110611ba757fe5b600091825260209091206003909102016002015460148581548110611bc857fe5b600091825260209091206003909102016002610f8c565b60148481548110611bec57fe5b6000918252602090912060039091020160020181905550611c3460178481548110611c1357fe5b60009182526020909120600390910201600101546016858154811061107a57fe5b60168481548110611c4157fe5b600091825260208220600160039092020101919091556015805485908110611c6557fe5b60009182526020822060039190910201919091556015805485908110611c8757fe5b600091825260208220600260039092020101919091556017805485908110611cab57fe5b6000918252602090912060039091020160010155600854611ccc9082614775565b6008556040805173ffffffffffffffffffffffffffffffffffffffff861681526020810183905280820185905290517ffc2f950130d4b652317d4d65735fe2c28b9b137f09199cc20367042dedafb6d59181900360600190a1600154611d499073ffffffffffffffffffffffffffffffffffffffff1685836146e3565b8173ffffffffffffffffffffffffffffffffffffffff16631d2e62d9826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611d9c57600080fd5b505af1158015611db0573d6000803e3d6000fd5b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60128281548110611de657600080fd5b90600052602060002090600302018160038110611e0257600080fd5b01549150829050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6000831180611e365750600081115b611ea157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f63616e27742072656d6f76652030000000000000000000000000000000000000604482015290519081900360640190fd5b60075473ffffffffffffffffffffffffffffffffffffffff610100909104811690600090819081908190891615801590611edb5750600088115b1561246b57611ee8614e27565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601d60209081526040918290208251608081018452815460ff9081161515825260018301549382019390935260028083015491949293928501929190911690811115611f4c57fe5b6002811115611f5757fe5b81526020016002820160019054906101000a900460ff166001811115611f7957fe5b6001811115611f8457fe5b9052508051909150611ff757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f62616c616e636520746f6b656e206c6f6f6b7570206661696c65640000000000604482015290519081900360640190fd5b604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518b918b9173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b15801561206757600080fd5b505afa15801561207b573d6000803e3d6000fd5b505050506040513d602081101561209157600080fd5b5051101561210057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e73756666696369656e7420647365632062616c616e636500000000000000604482015290519081900360640190fd5b602082015160008360600151600181111561211757fe5b1461218357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6261642064736563206164647265737300000000000000000000000000000000604482015290519081900360640190fd5b806006146121f257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f76312e363a2062616c20746f6b656e2065706f6368206d757374206265203600604482015290519081900360640190fd5b6000818152600f602052604090205460ff1661226f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f63616e27742072656d6f76652066726f6d20776f756e642075702065706f6368604482015290519081900360640190fd5b60006012828154811061227e57fe5b90600052602060002090600302018460400151600281111561229c57fe5b600381106122a657fe5b0154905080156122cb576122c681610ff68e670de0b6b3a76400006147f0565b6122ce565b60005b9450670de0b6b3a764000061231a86601885815481106122ea57fe5b90600052602060002090600302018760400151600281111561230857fe5b6003811061231257fe5b0154906147f0565b8161232157fe5b049750670de0b6b3a764000061233e86601985815481106122ea57fe5b8161234557fe5b049650612389886018848154811061235957fe5b90600052602060002090600302018660400151600281111561237757fe5b6003811061238157fe5b0154906148a5565b6018838154811061239657fe5b9060005260206000209060030201856040015160028111156123b457fe5b600381106123be57fe5b01819055506123d4876019848154811061235957fe5b601983815481106123e157fe5b9060005260206000209060030201856040015160028111156123ff57fe5b6003811061240957fe5b018190555061241f8c6012848154811061235957fe5b6012838154811061242c57fe5b90600052602060002090600302018560400151600281111561244a57fe5b6003811061245457fe5b015560045461246390896148a5565b600455505050505b73ffffffffffffffffffffffffffffffffffffffff8716158015906124905750600086115b156129255761249d614e27565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601d60209081526040918290208251608081018452815460ff908116151582526001830154938201939093526002808301549194929392850192919091169081111561250157fe5b600281111561250c57fe5b81526020016002820160019054906101000a900460ff16600181111561252e57fe5b600181111561253957fe5b90525080519091506125ac57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f62616c616e636520746f6b656e20696e666f206c6f6f6b7570206661696c6564604482015290519081900360640190fd5b604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518991899173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b15801561261c57600080fd5b505afa158015612630573d6000803e3d6000fd5b505050506040513d602081101561264657600080fd5b505110156126b557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e73756666696369656e74207072696e636970616c2062616c616e63650000604482015290519081900360640190fd5b60208201516001836060015160018111156126cc57fe5b1461273857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f6261642062616c616e636520746f6b656e206164647265737300000000000000604482015290519081900360640190fd5b806006146127a757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f76312e363a2062616c20746f6b656e2065706f6368206d757374206265203600604482015290519081900360640190fd5b6000818152600f602052604090205460ff1661282457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f63616e27742072656d6f76652066726f6d20776f756e642075702065706f6368604482015290519081900360640190fd5b612853896013838154811061283557fe5b90600052602060002090600302018560400151600281111561237757fe5b6013828154811061286057fe5b90600052602060002090600302018460400151600281111561287e57fe5b6003811061288857fe5b01819055506128b789600e838154811061289e57fe5b90600052602060002001546148a590919063ffffffff16565b600e82815481106128c457fe5b6000918252602090912001556003546128dd908a6148a5565b6003556008546128ed908a6148a5565b60085560028360400151600281111561290257fe5b14156129215760065489670de0b6b3a7640000028161291d57fe5b0494505b5050505b73ffffffffffffffffffffffffffffffffffffffff89161580159061294a5750600088115b15612be057604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518a918a9173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b1580156129bf57600080fd5b505afa1580156129d3573d6000803e3d6000fd5b505050506040513d60208110156129e957600080fd5b50511015612a5857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e73756666696369656e7420647365632062616c616e636500000000000000604482015290519081900360640190fd5b604080517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b9052905173ffffffffffffffffffffffffffffffffffffffff831691639dc29fac91604480830192600092919082900301818387803b158015612acc57600080fd5b505af1158015612ae0573d6000803e3d6000fd5b505050506000851115612b7a57604080517f96728a7200000000000000000000000000000000000000000000000000000000815260048101879052336024820152905173ffffffffffffffffffffffffffffffffffffffff8816916396728a7291604480830192600092919082900301818387803b158015612b6157600080fd5b505af1158015612b75573d6000803e3d6000fd5b505050505b600254612b9e9073ffffffffffffffffffffffffffffffffffffffff1633866146e3565b604080518381526020810187905280820186905290517f45d0d3545b4cb7d20e6d592c7158c445e3acda72c55074ab88b0027aa9c2d2789181900360600190a1505b73ffffffffffffffffffffffffffffffffffffffff871615801590612c055750600086115b15612e8557604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518891889173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b158015612c7a57600080fd5b505afa158015612c8e573d6000803e3d6000fd5b505050506040513d6020811015612ca457600080fd5b50511015612d1357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e73756666696369656e74207072696e636970616c2062616c616e63650000604482015290519081900360640190fd5b604080517f9dc29fac00000000000000000000000000000000000000000000000000000000815233600482015260248101899052905173ffffffffffffffffffffffffffffffffffffffff831691639dc29fac91604480830192600092919082900301818387803b158015612d8757600080fd5b505af1158015612d9b573d6000803e3d6000fd5b5050604080517f96728a72000000000000000000000000000000000000000000000000000000008152600481018b9052336024820152905173ffffffffffffffffffffffffffffffffffffffff8a1693506396728a729250604480830192600092919082900301818387803b158015612e1357600080fd5b505af1158015612e27573d6000803e3d6000fd5b5050600254612e50925073ffffffffffffffffffffffffffffffffffffffff16905033856146e3565b6040805188815290517ffbcc912eee8a56d51e3708fe32ba15f4191e6f92b2ccae4f00bbb544dba49f029181900360200190a1505b73ffffffffffffffffffffffffffffffffffffffff891615801590612eaa5750600088115b80612ed5575073ffffffffffffffffffffffffffffffffffffffff871615801590612ed55750600086115b612f4057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f6e6f20616374696f6e20706572666f726d656400000000000000000000000000604482015290519081900360640190fd5b505050505050505050565b6013548314612fbb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696d70726f706572206e65772065706f63680000000000000000000000000000604482015290519081900360640190fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461304157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b600e8054600181810190925560007fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd90910181905560408051606081018252828152602081018390529081018290526012805493840181559091526130ce9160039081027fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444019190614e4e565b50604080516060810182526000808252602082018190529181018290526013805460018101825592526131299160039081027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090019190614e4e565b50604080516060810182526000808252602082018190529181018290526014805460018101825592526131849160039081027fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec019190614e4e565b50604080516060810182526000808252602082018190529181018290526015805460018101825592526131df9160039081027f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec475019190614e4e565b506040805160608101825260008082526020820181905291810182905260168054600181018255925261323a9160039081027fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289019190614e4e565b50604080516060810182526000808252602082018190529181018290526017805460018101825592526132959160039081027fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c15019190614e4e565b50604080516060810182526000808252602082018190529181018290526018805460018101825592526132f09160039081027fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e019190614e4e565b506040805160608101825260008082526020820181905291810182905260198054600181018255925261334b9160039081027f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c9695019190614e4e565b506040805160608101909152601090808460008151811061336857fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252018460018151811061339a57fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825201846002815181106133cc57fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff169091528254600181018455600093845292206134139260039081029091019190614e91565b506040805160608101909152601190808360008151811061343057fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252018360018151811061346257fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252018360028151811061349457fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff169091528254600181018455600093845292206134db9260039081029091019190614e91565b506040805160808101825260018152602081018590529081016000815260200160009052601d600084818151811061350f57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff0219169083600281111561359f57fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156135e057fe5b0217905550506040805160808101825260018082526020820187905290925090820190815260200160009052601d60008460018151811061361d57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff021916908360028111156136ad57fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156136ee57fe5b021790555050604080516080810182526001815260208101869052915081016002815260200160009052601d60008460028151811061372957fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff021916908360028111156137b957fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156137fa57fe5b021790555050604080516080810182526001815260208101869052915081016000815260200160019052601d600083818151811061383457fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff021916908360028111156138c457fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600181111561390557fe5b0217905550506040805160808101825260018082526020820187905290925090820190815260200160019052601d60008360018151811061394257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff021916908360028111156139d257fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836001811115613a1357fe5b021790555050604080516080810182526001815260208101869052915081016002815260200160019052601d600083600281518110613a4e57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff02191690836002811115613ade57fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836001811115613b1f57fe5b02179055505050505050565b60055481565b60188281548110611de657600080fd5b60118281548110610cbc57600080fd5b60045481565b60148281548110611de657600080fd5b600b5473ffffffffffffffffffffffffffffffffffffffff163314613bed57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6d75737420626520737472617465677900000000000000000000000000000000604482015290519081900360640190fd5b6000828152600f602052604090205460ff1615613c6b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f65706f636820616c726561647920776f756e6420646f776e0000000000000000604482015290519081900360640190fd5b6000613c756141ff565b9050808310613ce557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f63616e6e6f742077696e6420646f776e206675747572652065706f6368000000604482015290519081900360640190fd5b613ced614efe565b506040805160c081018252600060208201819052918101829052606081018290526080810182905260a08101919091527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201808252613d4c90610cf7565b421015613dba57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f63616e27742063616c6c206265666f72652065706f636820656e646564000000604482015290519081900360640190fd5b601a54613dd090620186a090610ff690866147f0565b60198581548110613ddd57fe5b600091825260208220600391909102010155601b54613e0590620186a090610ff690866147f0565b60198581548110613e1257fe5b6000918252602090912060039091020160010155601c54613e3c90620186a090610ff690866147f0565b60198581548110613e4957fe5b60009182526020909120600390910201600201558051601980547f02ac5b59c8ff91aed9818435a4a06bf88afedae653001d8d7086f29057eca88c92919087908110613e9157fe5b60009182526020822060039190910201015460198781548110613eb057fe5b600091825260209091206003909102016001015460198881548110613ed157fe5b6000918252602090912060039091020160020154604080519485526020850193909352838301919091526060830152519081900360800190a1600754600854604080517f1a2b383200000000000000000000000000000000000000000000000000000000815260048101929092525161010090920473ffffffffffffffffffffffffffffffffffffffff16918291631a2b38329160248083019260209291908290030181600087803b158015613f8657600080fd5b505af1158015613f9a573d6000803e3d6000fd5b505050506040513d6020811015613fb057600080fd5b505160208301819052600454613fc591614775565b600481905550613ffc60128681548110613fdb57fe5b600091825260209091206003909102016002015460128781548110610f7b57fe5b82604001818152505061403d8260400151610ff6670de0b6b3a76400006012898154811061402657fe5b600091825260209091206003909102016002612308565b60608301819052600554602084015161406892610d1091670de0b6b3a764000091610ff691906147f0565b60808301819052602083015161407d916148a5565b60a08301819052601880548790811061409257fe5b600091825260208220600391909102019190915560188054879081106140b457fe5b6000918252602090912060039091020160010155608082015160188054879081106140db57fe5b60009182526020909120600390910201600201819055507fc02e9d57f5d0e6c88fa2bb10be566c735854afd14dfc5c1b0ecf9c334ac6ee35858360a001516000856080015160198a8154811061412d57fe5b60009182526020822060039190910201015460198b8154811061414c57fe5b600091825260209091206003909102016001015460198c8154811061416d57fe5b6000918252602090912060039091020160020154604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190a16000858152600f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556141f7614efe565b505050505050565b600c54600090421161427257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f6265666f72652065706f63682030000000000000000000000000000000000000604482015290519081900360640190fd5b600d54600c5442038161428157fe5b04905090565b60198281548110611de657600080fd5b60138281548110611de657600080fd5b601a54601b54601c5483565b60178281548110611de657600080fd5b600f6020526000908152604090205460ff1681565b60015473ffffffffffffffffffffffffffffffffffffffff1690565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b60085481565b60168281548110611de657600080fd5b60035481565b60158281548110611de657600080fd5b6000610d1f42614368610d16600c60010154610d1060018861477590919063ffffffff16565b906148a5565b600080600061437b6141ff565b905060006143b06016838154811061438f57fe5b600091825260209091206003909102016001015460168481548110611bc857fe5b905060006143e5601784815481106143c457fe5b600091825260209091206003909102016001015460178581548110611bc857fe5b90506000601484815481106143f657fe5b600091825260208220600391909102010154905060006015858154811061441957fe5b600091825260208220600391909102010154905083821161443b57600061443f565b8382035b83821161444d576000614451565b8382035b9650965050505050509091565b60005473ffffffffffffffffffffffffffffffffffffffff1633146144e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b600c54625c490001421161455957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f746f6f20736f6f6e000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b61456560096000614f34565b565b600e818154811061457757600080fd5b600091825260209091200154905081565b600c54600d549091565b600b5473ffffffffffffffffffffffffffffffffffffffff163314806145cf575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61463a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6d75737420626520737472617465677900000000000000000000000000000000604482015290519081900360640190fd5b620151806146486001610cf7565b0342116146b657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f747279696e6720746f2073687574646f776e20746f6f206561726c7900000000604482015290519081900360640190fd5b600780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052614770908490614982565b505050565b6000828201838110156147e957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000826147ff57506000610d1f565b8282028284828161480c57fe5b04146147e9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614f916021913960400191505060405180910390fd5b60006147e983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614a5a565b60006147e983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b16565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261497c908590614982565b50505050565b60606149e4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16614b8a9092919063ffffffff16565b80519091501561477057808060200190516020811015614a0357600080fd5b5051614770576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180614fd9602a913960400191505060405180910390fd5b60008183614b00576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614ac5578181015183820152602001614aad565b50505050905090810190601f168015614af25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581614b0c57fe5b0495945050505050565b60008184841115614b82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315614ac5578181015183820152602001614aad565b505050900390565b6060614b998484600085614ba1565b949350505050565b606082471015614bfc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614f6b6026913960400191505060405180910390fd5b614c0585614d5c565b614c7057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310614cda57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614c9d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614d3c576040519150601f19603f3d011682016040523d82523d6000602084013e614d41565b606091505b5091509150614d51828286614d62565b979650505050505050565b3b151590565b60608315614d715750816147e9565b825115614d815782518084602001fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152845160248401528451859391928392604401919085019080838360008315614ac5578181015183820152602001614aad565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60408051608081018252600080825260208201819052909182019081526020016000905290565b8260038101928215614e81579160200282015b82811115614e81578251829060ff16905591602001919060010190614e61565b50614e8d929150614f55565b5090565b8260038101928215614e81579160200282015b82811115614e8157825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614ea4565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5080546000825590600052602060002090810190614f529190614f55565b50565b5b80821115614e8d5760008155600101614f5656fe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7776313a2063616e2774206164645f6c697175696469747920696e746f204141207472616e6368655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122097d5fecf88b2bcdd4005ee7c397b179c613d1e8b7d00906bcd77e7b404e4c84b64736f6c63430007040033000000000000000000000000c7a70b08c826da7509e48c3e555574292915bd210000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000b753428af26e81097e7fd17f40c88aaa3e04902c00000000000000000000000000000000000000000000001b1ae4d6e2ef5000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102de5760003560e01c80637425ffec11610186578063ac3dbb12116100e3578063df4cbfd811610097578063ebd485fc11610071578063ebd485fc1461086d578063f034c18d1461088a578063fc0e74d114610892576102de565b8063df4cbfd814610840578063dfe537961461085d578063e653be7414610865576102de565b8063bc87f62c116100c8578063bc87f62c146107f2578063c6b483ab14610815578063d2e7a1bb1461081d576102de565b8063ac3dbb12146107e2578063bc4ce844146107ea576102de565b80639b53e3661161013a578063a684b5991161011f578063a684b599146107b5578063a72b6c30146107d2578063a8c62e76146107da576102de565b80639b53e3661461076c578063a20f527214610792576102de565b8063837a9bc71161016b578063837a9bc71461071e57806384518744146107265780639392f6f214610749576102de565b80637425ffec146106d857806380e0f15f146106fb576102de565b806348373cc61161023f5780635b1caa2f116101f35780636bd6f696116101cd5780636bd6f6961461068a57806370cdf476146106ad57806370d4ac4e146106d0576102de565b80635b1caa2f1461050d5780636120f0dc146105545780636acc25be14610682576102de565b806354d0c8a01161022457806354d0c8a0146104da578063580f346f146104e25780635aa6e67514610505576102de565b806348373cc61461048b5780634c1a4259146104a7576102de565b80630f78dac31161029657806322cef9d31161027b57806322cef9d3146104405780632a0ccc88146104485780632b666fcf14610450576102de565b80630f78dac3146103f95780631816f3141461041f576102de565b8063070313fa116102c7578063070313fa1461034b5780630bbb0c581461037e5780630efb8dbd146103ca576102de565b806301681a62146102e357806302b6215914610318575b600080fd5b610316600480360360208110156102f957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661089a565b005b6103166004803603602081101561032e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b0d565b6103166004803603602081101561036157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610bdf565b6103a16004803603604081101561039457600080fd5b5080359060200135610cac565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6103e7600480360360208110156103e057600080fd5b5035610cf7565b60408051918252519081900360200190f35b6103166004803603604081101561040f57600080fd5b508035906020013560ff16610d25565b6104276116ba565b6040805192835260208301919091528051918290030190f35b6103a16116c3565b6103a16116e4565b6103166004803603604081101561046657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611700565b61049361195a565b604080519115158252519081900360200190f35b610316600480360360208110156104bd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611963565b6103a1611dba565b6103e7600480360360408110156104f857600080fd5b5080359060200135611dd6565b6103a1611e0b565b6103166004803603608081101561052357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135169060600135611e27565b6103166004803603606081101561056a57600080fd5b8135919081019060408101602082013564010000000081111561058c57600080fd5b82018360208201111561059e57600080fd5b803590602001918460208302840111640100000000831117156105c057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929594936020810193503591505064010000000081111561061057600080fd5b82018360208201111561062257600080fd5b8035906020019184602083028401116401000000008311171561064457600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612f4b945050505050565b6103e7613b2b565b6103e7600480360360408110156106a057600080fd5b5080359060200135613b31565b6103a1600480360360408110156106c357600080fd5b5080359060200135613b41565b6103e7613b51565b6103e7600480360360408110156106ee57600080fd5b5080359060200135613b57565b6103166004803603604081101561071157600080fd5b5080359060200135613b67565b6103e76141ff565b6103e76004803603604081101561073c57600080fd5b5080359060200135614287565b6103e76004803603604081101561075f57600080fd5b5080359060200135614297565b6107746142a7565b60408051938452602084019290925282820152519081900360600190f35b6103e7600480360360408110156107a857600080fd5b50803590602001356142b3565b610493600480360360208110156107cb57600080fd5b50356142c3565b6103a16142d8565b6103a16142f4565b6103e7614310565b6103e7614316565b6103e76004803603604081101561080857600080fd5b508035906020013561431c565b6103e761432c565b6103e76004803603604081101561083357600080fd5b5080359060200135614332565b6103e76004803603602081101561085657600080fd5b5035614342565b61042761436e565b61031661445e565b6103e76004803603602081101561088357600080fd5b5035614567565b610427614588565b610316614592565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff9092169160009183916370a0823191602480820192602092909190829003018186803b15801561099657600080fd5b505afa1580156109aa573d6000803e3d6000fd5b505050506040513d60208110156109c057600080fd5b505190506109e573ffffffffffffffffffffffffffffffffffffffff831684836146e3565b600154604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff9092169160009183916370a0823191602480820192602092909190829003018186803b158015610a5b57600080fd5b505afa158015610a6f573d6000803e3d6000fd5b505050506040513d6020811015610a8557600080fd5b50519050610aaa73ffffffffffffffffffffffffffffffffffffffff831686836146e3565b6040805133815273ffffffffffffffffffffffffffffffffffffffff871660208201528082018590526060810183905290517f8496dda4d04919fec296be83f4d7d178dafb7c0d3abe1553c092f1466e8f29289181900360800190a15050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b9357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b6007805473ffffffffffffffffffffffffffffffffffffffff909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c6557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60108281548110610cbc57600080fd5b90600052602060002090600302018160038110610cd857600080fd5b015473ffffffffffffffffffffffffffffffffffffffff169150829050565b600d54600090610d1f90610d1690610d10856001614775565b906147f0565b600c5490614775565b92915050565b60075460ff1615610d9757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f706f6f6c2073687574646f776e00000000000000000000000000000000000000604482015290519081900360640190fd5b6000816002811115610da557fe5b1480610dbc57506002816002811115610dba57fe5b145b610e11576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180614fb26027913960400191505060405180910390fd5b6000610e1b6141ff565b905082610e8957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f63616e2774206164642030000000000000000000000000000000000000000000604482015290519081900360640190fd5b80600614610ef857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f76312e363a206d7573742062652065706f63682036206f6e6c79000000000000604482015290519081900360640190fd5b610f00614de2565b6040518061010001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152509050610f4c61436e565b60e083015260c08201526000836002811115610f6457fe5b1415610fc157610f9e8460158481548110610f7b57fe5b600091825260208220600390910201905b60038110610f9657fe5b015490614775565b60158381548110610fab57fe5b6000918252602082206003919091020101558381525b6002836002811115610fcf57fe5b141561110557610ffc600554610ff68360e001518460c0015161477590919063ffffffff16565b90614863565b602082018190528410611013578060200151611015565b835b80825260055461102591906147f0565b6060820181905260c08201511061104557606081015160808201526110b3565b60c081015160808201819052606082015161105f916148a5565b60a08201819052601780546110919291908590811061107a57fe5b600091825260209091206003909102016001610f8c565b6017838154811061109e57fe5b60009182526020909120600390910201600101555b6110c881608001516016848154811061107a57fe5b601683815481106110d557fe5b600091825260209091206003909102016001015580518411156111055780516110ff9085906148a5565b60408201525b600061111b61111384614342565b8351906147f0565b825160035491925061112d9190614775565b6003558151600e805461115f9291908690811061114657fe5b906000526020600020015461477590919063ffffffff16565b600e848154811061116c57fe5b90600052602060002001819055506111a5816012858154811061118b57fe5b9060005260206000209060030201866002811115610f8c57fe5b601284815481106111b257fe5b90600052602060002090600302018560028111156111cc57fe5b600381106111d657fe5b01558151601380546111ee9291908690811061118b57fe5b601384815481106111fb57fe5b906000526020600020906003020185600281111561121557fe5b6003811061121f57fe5b0155815160015461124c9173ffffffffffffffffffffffffffffffffffffffff90911690339030906148e7565b600284600281111561125a57fe5b14156112a1576112a133306006548560000151670de0b6b3a7640000028161127e57fe5b60025473ffffffffffffffffffffffffffffffffffffffff1693929190046148e7565b601083815481106112ae57fe5b90600052602060002090600302018460028111156112c857fe5b600381106112d257fe5b0154604080517f40c10f1900000000000000000000000000000000000000000000000000000000815233600482015260248101849052905173ffffffffffffffffffffffffffffffffffffffff909216916340c10f199160448082019260009290919082900301818387803b15801561134a57600080fd5b505af115801561135e573d6000803e3d6000fd5b505050506011838154811061136f57fe5b906000526020600020906003020184600281111561138957fe5b6003811061139357fe5b01548251604080517f40c10f1900000000000000000000000000000000000000000000000000000000815233600482015260248101929092525173ffffffffffffffffffffffffffffffffffffffff909216916340c10f199160448082019260009290919082900301818387803b15801561140d57600080fd5b505af1158015611421573d6000803e3d6000fd5b505050507f058587cdc5efcef45583dc39e6884e853b5c5aef182afe72ca96db6fa1c85c2184600281111561145257fe5b8360000151846000015185602001518660400151876060015188608001518960a001518a60c001518b60e00151604051808b81526020018a81526020018981526020018881526020018781526020018681526020018581526020018481526020018381526020018281526020019a505050505050505050505060405180910390a17fc7d2d1a5a726dc6005e76316c12eb5ee642296cc38c1b996651599995a480f3c6114fd84614342565b8360000151836010878154811061151057fe5b906000526020600020906003020188600281111561152a57fe5b6003811061153457fe5b015473ffffffffffffffffffffffffffffffffffffffff168789600281111561155957fe5b3360118b8154811061156757fe5b90600052602060002090600302018c600281111561158157fe5b6003811061158b57fe5b01546040805198895260208901979097528787019590955273ffffffffffffffffffffffffffffffffffffffff9384166060880152608087019290925260a0860152811660c08501521660e083015251908190036101000190a17f1d69fb63e4692a6ae9a9b249224c389569da92d8e2e96243d71fd6b3bc3055d9600354600e858154811061161657fe5b906000526020600020015460006013878154811061163057fe5b906000526020600020906003020188600281111561164a57fe5b6003811061165457fe5b01546012888154811061166357fe5b906000526020600020906003020189600281111561167d57fe5b6003811061168757fe5b01546040805195865260208601949094528484019290925260608401526080830152519081900360a00190a15050505050565b600c54600d5482565b600754610100900473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16331461178657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b60015473ffffffffffffffffffffffffffffffffffffffff8381169116148015906117cc575060025473ffffffffffffffffffffffffffffffffffffffff838116911614155b61183757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616e6e6f7420737765657020706f6f6c206173736574730000000000000000604482015290519081900360640190fd5b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051839160009173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b1580156118a857600080fd5b505afa1580156118bc573d6000803e3d6000fd5b505050506040513d60208110156118d257600080fd5b505190506118f773ffffffffffffffffffffffffffffffffffffffff831684836146e3565b6040805133815273ffffffffffffffffffffffffffffffffffffffff80861660208301528616818301526060810183905290517f2c4e64c7c0957a81c0076a0a3f3c7d9f0a5d6158292071c794436f829d12cfb79181900360800190a150505050565b60075460ff1681565b600b5473ffffffffffffffffffffffffffffffffffffffff1633146119e957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6d75737420626520737472617465677900000000000000000000000000000000604482015290519081900360640190fd5b60075460ff1615611a5b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f706f6f6c2073687574646f776e00000000000000000000000000000000000000604482015290519081900360640190fd5b6000611a656141ff565b6007805473ffffffffffffffffffffffffffffffffffffffff808616610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff90921691909117909155600154604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051939450859360009392909216916370a0823191602480820192602092909190829003018186803b158015611b1557600080fd5b505afa158015611b29573d6000803e3d6000fd5b505050506040513d6020811015611b3f57600080fd5b505160158054919250611b759185908110611b5657fe5b60009182526020822060039190910201015460148581548110610f7b57fe5b60148481548110611b8257fe5b600091825260208220600391909102010181905550611bdf60158481548110611ba757fe5b600091825260209091206003909102016002015460148581548110611bc857fe5b600091825260209091206003909102016002610f8c565b60148481548110611bec57fe5b6000918252602090912060039091020160020181905550611c3460178481548110611c1357fe5b60009182526020909120600390910201600101546016858154811061107a57fe5b60168481548110611c4157fe5b600091825260208220600160039092020101919091556015805485908110611c6557fe5b60009182526020822060039190910201919091556015805485908110611c8757fe5b600091825260208220600260039092020101919091556017805485908110611cab57fe5b6000918252602090912060039091020160010155600854611ccc9082614775565b6008556040805173ffffffffffffffffffffffffffffffffffffffff861681526020810183905280820185905290517ffc2f950130d4b652317d4d65735fe2c28b9b137f09199cc20367042dedafb6d59181900360600190a1600154611d499073ffffffffffffffffffffffffffffffffffffffff1685836146e3565b8173ffffffffffffffffffffffffffffffffffffffff16631d2e62d9826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611d9c57600080fd5b505af1158015611db0573d6000803e3d6000fd5b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60128281548110611de657600080fd5b90600052602060002090600302018160038110611e0257600080fd5b01549150829050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6000831180611e365750600081115b611ea157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f63616e27742072656d6f76652030000000000000000000000000000000000000604482015290519081900360640190fd5b60075473ffffffffffffffffffffffffffffffffffffffff610100909104811690600090819081908190891615801590611edb5750600088115b1561246b57611ee8614e27565b73ffffffffffffffffffffffffffffffffffffffff8a166000908152601d60209081526040918290208251608081018452815460ff9081161515825260018301549382019390935260028083015491949293928501929190911690811115611f4c57fe5b6002811115611f5757fe5b81526020016002820160019054906101000a900460ff166001811115611f7957fe5b6001811115611f8457fe5b9052508051909150611ff757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f62616c616e636520746f6b656e206c6f6f6b7570206661696c65640000000000604482015290519081900360640190fd5b604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518b918b9173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b15801561206757600080fd5b505afa15801561207b573d6000803e3d6000fd5b505050506040513d602081101561209157600080fd5b5051101561210057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e73756666696369656e7420647365632062616c616e636500000000000000604482015290519081900360640190fd5b602082015160008360600151600181111561211757fe5b1461218357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6261642064736563206164647265737300000000000000000000000000000000604482015290519081900360640190fd5b806006146121f257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f76312e363a2062616c20746f6b656e2065706f6368206d757374206265203600604482015290519081900360640190fd5b6000818152600f602052604090205460ff1661226f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f63616e27742072656d6f76652066726f6d20776f756e642075702065706f6368604482015290519081900360640190fd5b60006012828154811061227e57fe5b90600052602060002090600302018460400151600281111561229c57fe5b600381106122a657fe5b0154905080156122cb576122c681610ff68e670de0b6b3a76400006147f0565b6122ce565b60005b9450670de0b6b3a764000061231a86601885815481106122ea57fe5b90600052602060002090600302018760400151600281111561230857fe5b6003811061231257fe5b0154906147f0565b8161232157fe5b049750670de0b6b3a764000061233e86601985815481106122ea57fe5b8161234557fe5b049650612389886018848154811061235957fe5b90600052602060002090600302018660400151600281111561237757fe5b6003811061238157fe5b0154906148a5565b6018838154811061239657fe5b9060005260206000209060030201856040015160028111156123b457fe5b600381106123be57fe5b01819055506123d4876019848154811061235957fe5b601983815481106123e157fe5b9060005260206000209060030201856040015160028111156123ff57fe5b6003811061240957fe5b018190555061241f8c6012848154811061235957fe5b6012838154811061242c57fe5b90600052602060002090600302018560400151600281111561244a57fe5b6003811061245457fe5b015560045461246390896148a5565b600455505050505b73ffffffffffffffffffffffffffffffffffffffff8716158015906124905750600086115b156129255761249d614e27565b73ffffffffffffffffffffffffffffffffffffffff88166000908152601d60209081526040918290208251608081018452815460ff908116151582526001830154938201939093526002808301549194929392850192919091169081111561250157fe5b600281111561250c57fe5b81526020016002820160019054906101000a900460ff16600181111561252e57fe5b600181111561253957fe5b90525080519091506125ac57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f62616c616e636520746f6b656e20696e666f206c6f6f6b7570206661696c6564604482015290519081900360640190fd5b604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518991899173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b15801561261c57600080fd5b505afa158015612630573d6000803e3d6000fd5b505050506040513d602081101561264657600080fd5b505110156126b557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e73756666696369656e74207072696e636970616c2062616c616e63650000604482015290519081900360640190fd5b60208201516001836060015160018111156126cc57fe5b1461273857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f6261642062616c616e636520746f6b656e206164647265737300000000000000604482015290519081900360640190fd5b806006146127a757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f76312e363a2062616c20746f6b656e2065706f6368206d757374206265203600604482015290519081900360640190fd5b6000818152600f602052604090205460ff1661282457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f63616e27742072656d6f76652066726f6d20776f756e642075702065706f6368604482015290519081900360640190fd5b612853896013838154811061283557fe5b90600052602060002090600302018560400151600281111561237757fe5b6013828154811061286057fe5b90600052602060002090600302018460400151600281111561287e57fe5b6003811061288857fe5b01819055506128b789600e838154811061289e57fe5b90600052602060002001546148a590919063ffffffff16565b600e82815481106128c457fe5b6000918252602090912001556003546128dd908a6148a5565b6003556008546128ed908a6148a5565b60085560028360400151600281111561290257fe5b14156129215760065489670de0b6b3a7640000028161291d57fe5b0494505b5050505b73ffffffffffffffffffffffffffffffffffffffff89161580159061294a5750600088115b15612be057604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518a918a9173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b1580156129bf57600080fd5b505afa1580156129d3573d6000803e3d6000fd5b505050506040513d60208110156129e957600080fd5b50511015612a5857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e73756666696369656e7420647365632062616c616e636500000000000000604482015290519081900360640190fd5b604080517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b9052905173ffffffffffffffffffffffffffffffffffffffff831691639dc29fac91604480830192600092919082900301818387803b158015612acc57600080fd5b505af1158015612ae0573d6000803e3d6000fd5b505050506000851115612b7a57604080517f96728a7200000000000000000000000000000000000000000000000000000000815260048101879052336024820152905173ffffffffffffffffffffffffffffffffffffffff8816916396728a7291604480830192600092919082900301818387803b158015612b6157600080fd5b505af1158015612b75573d6000803e3d6000fd5b505050505b600254612b9e9073ffffffffffffffffffffffffffffffffffffffff1633866146e3565b604080518381526020810187905280820186905290517f45d0d3545b4cb7d20e6d592c7158c445e3acda72c55074ab88b0027aa9c2d2789181900360600190a1505b73ffffffffffffffffffffffffffffffffffffffff871615801590612c055750600086115b15612e8557604080517f70a0823100000000000000000000000000000000000000000000000000000000815233600482015290518891889173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b158015612c7a57600080fd5b505afa158015612c8e573d6000803e3d6000fd5b505050506040513d6020811015612ca457600080fd5b50511015612d1357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e73756666696369656e74207072696e636970616c2062616c616e63650000604482015290519081900360640190fd5b604080517f9dc29fac00000000000000000000000000000000000000000000000000000000815233600482015260248101899052905173ffffffffffffffffffffffffffffffffffffffff831691639dc29fac91604480830192600092919082900301818387803b158015612d8757600080fd5b505af1158015612d9b573d6000803e3d6000fd5b5050604080517f96728a72000000000000000000000000000000000000000000000000000000008152600481018b9052336024820152905173ffffffffffffffffffffffffffffffffffffffff8a1693506396728a729250604480830192600092919082900301818387803b158015612e1357600080fd5b505af1158015612e27573d6000803e3d6000fd5b5050600254612e50925073ffffffffffffffffffffffffffffffffffffffff16905033856146e3565b6040805188815290517ffbcc912eee8a56d51e3708fe32ba15f4191e6f92b2ccae4f00bbb544dba49f029181900360200190a1505b73ffffffffffffffffffffffffffffffffffffffff891615801590612eaa5750600088115b80612ed5575073ffffffffffffffffffffffffffffffffffffffff871615801590612ed55750600086115b612f4057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f6e6f20616374696f6e20706572666f726d656400000000000000000000000000604482015290519081900360640190fd5b505050505050505050565b6013548314612fbb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696d70726f706572206e65772065706f63680000000000000000000000000000604482015290519081900360640190fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461304157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b600e8054600181810190925560007fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd90910181905560408051606081018252828152602081018390529081018290526012805493840181559091526130ce9160039081027fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444019190614e4e565b50604080516060810182526000808252602082018190529181018290526013805460018101825592526131299160039081027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090019190614e4e565b50604080516060810182526000808252602082018190529181018290526014805460018101825592526131849160039081027fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec019190614e4e565b50604080516060810182526000808252602082018190529181018290526015805460018101825592526131df9160039081027f55f448fdea98c4d29eb340757ef0a66cd03dbb9538908a6a81d96026b71ec475019190614e4e565b506040805160608101825260008082526020820181905291810182905260168054600181018255925261323a9160039081027fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289019190614e4e565b50604080516060810182526000808252602082018190529181018290526017805460018101825592526132959160039081027fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c15019190614e4e565b50604080516060810182526000808252602082018190529181018290526018805460018101825592526132f09160039081027fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e019190614e4e565b506040805160608101825260008082526020820181905291810182905260198054600181018255925261334b9160039081027f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c9695019190614e4e565b506040805160608101909152601090808460008151811061336857fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252018460018151811061339a57fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825201846002815181106133cc57fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff169091528254600181018455600093845292206134139260039081029091019190614e91565b506040805160608101909152601190808360008151811061343057fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252018360018151811061346257fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252018360028151811061349457fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff169091528254600181018455600093845292206134db9260039081029091019190614e91565b506040805160808101825260018152602081018590529081016000815260200160009052601d600084818151811061350f57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff0219169083600281111561359f57fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156135e057fe5b0217905550506040805160808101825260018082526020820187905290925090820190815260200160009052601d60008460018151811061361d57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff021916908360028111156136ad57fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156136ee57fe5b021790555050604080516080810182526001815260208101869052915081016002815260200160009052601d60008460028151811061372957fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff021916908360028111156137b957fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156137fa57fe5b021790555050604080516080810182526001815260208101869052915081016000815260200160019052601d600083818151811061383457fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff021916908360028111156138c457fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600181111561390557fe5b0217905550506040805160808101825260018082526020820187905290925090820190815260200160019052601d60008360018151811061394257fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff021916908360028111156139d257fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836001811115613a1357fe5b021790555050604080516080810182526001815260208101869052915081016002815260200160019052601d600083600281518110613a4e57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548160ff02191690836002811115613ade57fe5b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836001811115613b1f57fe5b02179055505050505050565b60055481565b60188281548110611de657600080fd5b60118281548110610cbc57600080fd5b60045481565b60148281548110611de657600080fd5b600b5473ffffffffffffffffffffffffffffffffffffffff163314613bed57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6d75737420626520737472617465677900000000000000000000000000000000604482015290519081900360640190fd5b6000828152600f602052604090205460ff1615613c6b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f65706f636820616c726561647920776f756e6420646f776e0000000000000000604482015290519081900360640190fd5b6000613c756141ff565b9050808310613ce557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f63616e6e6f742077696e6420646f776e206675747572652065706f6368000000604482015290519081900360640190fd5b613ced614efe565b506040805160c081018252600060208201819052918101829052606081018290526080810182905260a08101919091527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201808252613d4c90610cf7565b421015613dba57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f63616e27742063616c6c206265666f72652065706f636820656e646564000000604482015290519081900360640190fd5b601a54613dd090620186a090610ff690866147f0565b60198581548110613ddd57fe5b600091825260208220600391909102010155601b54613e0590620186a090610ff690866147f0565b60198581548110613e1257fe5b6000918252602090912060039091020160010155601c54613e3c90620186a090610ff690866147f0565b60198581548110613e4957fe5b60009182526020909120600390910201600201558051601980547f02ac5b59c8ff91aed9818435a4a06bf88afedae653001d8d7086f29057eca88c92919087908110613e9157fe5b60009182526020822060039190910201015460198781548110613eb057fe5b600091825260209091206003909102016001015460198881548110613ed157fe5b6000918252602090912060039091020160020154604080519485526020850193909352838301919091526060830152519081900360800190a1600754600854604080517f1a2b383200000000000000000000000000000000000000000000000000000000815260048101929092525161010090920473ffffffffffffffffffffffffffffffffffffffff16918291631a2b38329160248083019260209291908290030181600087803b158015613f8657600080fd5b505af1158015613f9a573d6000803e3d6000fd5b505050506040513d6020811015613fb057600080fd5b505160208301819052600454613fc591614775565b600481905550613ffc60128681548110613fdb57fe5b600091825260209091206003909102016002015460128781548110610f7b57fe5b82604001818152505061403d8260400151610ff6670de0b6b3a76400006012898154811061402657fe5b600091825260209091206003909102016002612308565b60608301819052600554602084015161406892610d1091670de0b6b3a764000091610ff691906147f0565b60808301819052602083015161407d916148a5565b60a08301819052601880548790811061409257fe5b600091825260208220600391909102019190915560188054879081106140b457fe5b6000918252602090912060039091020160010155608082015160188054879081106140db57fe5b60009182526020909120600390910201600201819055507fc02e9d57f5d0e6c88fa2bb10be566c735854afd14dfc5c1b0ecf9c334ac6ee35858360a001516000856080015160198a8154811061412d57fe5b60009182526020822060039190910201015460198b8154811061414c57fe5b600091825260209091206003909102016001015460198c8154811061416d57fe5b6000918252602090912060039091020160020154604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190a16000858152600f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556141f7614efe565b505050505050565b600c54600090421161427257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f6265666f72652065706f63682030000000000000000000000000000000000000604482015290519081900360640190fd5b600d54600c5442038161428157fe5b04905090565b60198281548110611de657600080fd5b60138281548110611de657600080fd5b601a54601b54601c5483565b60178281548110611de657600080fd5b600f6020526000908152604090205460ff1681565b60015473ffffffffffffffffffffffffffffffffffffffff1690565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b60085481565b60168281548110611de657600080fd5b60035481565b60158281548110611de657600080fd5b6000610d1f42614368610d16600c60010154610d1060018861477590919063ffffffff16565b906148a5565b600080600061437b6141ff565b905060006143b06016838154811061438f57fe5b600091825260209091206003909102016001015460168481548110611bc857fe5b905060006143e5601784815481106143c457fe5b600091825260209091206003909102016001015460178581548110611bc857fe5b90506000601484815481106143f657fe5b600091825260208220600391909102010154905060006015858154811061441957fe5b600091825260208220600391909102010154905083821161443b57600061443f565b8382035b83821161444d576000614451565b8382035b9650965050505050509091565b60005473ffffffffffffffffffffffffffffffffffffffff1633146144e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6d75737420626520676f7665726e616e63650000000000000000000000000000604482015290519081900360640190fd5b600c54625c490001421161455957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f746f6f20736f6f6e000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b61456560096000614f34565b565b600e818154811061457757600080fd5b600091825260209091200154905081565b600c54600d549091565b600b5473ffffffffffffffffffffffffffffffffffffffff163314806145cf575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61463a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6d75737420626520737472617465677900000000000000000000000000000000604482015290519081900360640190fd5b620151806146486001610cf7565b0342116146b657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f747279696e6720746f2073687574646f776e20746f6f206561726c7900000000604482015290519081900360640190fd5b600780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052614770908490614982565b505050565b6000828201838110156147e957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000826147ff57506000610d1f565b8282028284828161480c57fe5b04146147e9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180614f916021913960400191505060405180910390fd5b60006147e983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614a5a565b60006147e983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b16565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261497c908590614982565b50505050565b60606149e4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16614b8a9092919063ffffffff16565b80519091501561477057808060200190516020811015614a0357600080fd5b5051614770576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180614fd9602a913960400191505060405180910390fd5b60008183614b00576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614ac5578181015183820152602001614aad565b50505050905090810190601f168015614af25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581614b0c57fe5b0495945050505050565b60008184841115614b82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315614ac5578181015183820152602001614aad565b505050900390565b6060614b998484600085614ba1565b949350505050565b606082471015614bfc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614f6b6026913960400191505060405180910390fd5b614c0585614d5c565b614c7057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310614cda57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614c9d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614d3c576040519150601f19603f3d011682016040523d82523d6000602084013e614d41565b606091505b5091509150614d51828286614d62565b979650505050505050565b3b151590565b60608315614d715750816147e9565b825115614d815782518084602001fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152845160248401528451859391928392604401919085019080838360008315614ac5578181015183820152602001614aad565b60405180610100016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60408051608081018252600080825260208201819052909182019081526020016000905290565b8260038101928215614e81579160200282015b82811115614e81578251829060ff16905591602001919060010190614e61565b50614e8d929150614f55565b5090565b8260038101928215614e81579160200282015b82811115614e8157825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614ea4565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5080546000825590600052602060002090810190614f529190614f55565b50565b5b80821115614e8d5760008155600101614f5656fe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7776313a2063616e2774206164645f6c697175696469747920696e746f204141207472616e6368655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122097d5fecf88b2bcdd4005ee7c397b179c613d1e8b7d00906bcd77e7b404e4c84b64736f6c63430007040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c7a70b08c826da7509e48c3e555574292915bd210000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000b753428af26e81097e7fd17f40c88aaa3e04902c00000000000000000000000000000000000000000000001b1ae4d6e2ef5000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _strategy (address): 0xC7a70b08c826da7509E48c3E555574292915bd21
Arg [1] : _base_asset (address): 0x6B175474E89094C44Da98b954EedeAC495271d0F
Arg [2] : _SFI_address (address): 0xb753428af26E81097e7fD17f40c88aaA3E04902c
Arg [3] : _SFI_ratio (uint256): 500000000000000000000
Arg [4] : epoch_cycle_reset (bool): False
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000c7a70b08c826da7509e48c3e555574292915bd21
Arg [1] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [2] : 000000000000000000000000b753428af26e81097e7fd17f40c88aaa3e04902c
Arg [3] : 00000000000000000000000000000000000000000000001b1ae4d6e2ef500000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
36328:26764:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62645:444;;;;;;;;;;;;;;;;-1:-1:-1;62645:444:0;;;;:::i;:::-;;60011:147;;;;;;;;;;;;;;;;-1:-1:-1;60011:147:0;;;;:::i;59861:144::-;;;;;;;;;;;;;;;;-1:-1:-1;59861:144:0;;;;:::i;38175:40::-;;;;;;;;;;;;;;;;-1:-1:-1;38175:40:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;60200:154;;;;;;;;;;;;;;;;-1:-1:-1;60200:154:0;;:::i;:::-;;;;;;;;;;;;;;;;45061:4137;;;;;;;;;;;;;;;;-1:-1:-1;45061:4137:0;;;;;;;;;:::i;37639:164::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;37195:35;;;:::i;36622:26::-;;;:::i;62172:393::-;;;;;;;;;;;;;;;;-1:-1:-1;62172:393:0;;;;;;;;;;;:::i;37044:29::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;58084:1497;;;;;;;;;;;;;;;;-1:-1:-1;58084:1497:0;;;;:::i;36528:33::-;;;:::i;38348:38::-;;;;;;;;;;;;;;;;-1:-1:-1;38348:38:0;;;;;;;:::i;36434:25::-;;;:::i;53061:4869::-;;;;;;;;;;;;;;;;-1:-1:-1;53061:4869:0;;;;;;;;;;;;;;;;;;;;;:::i;41144:2743::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41144:2743:0;;;;;;;;-1:-1:-1;41144:2743:0;;-1:-1:-1;;41144:2743:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41144:2743:0;;-1:-1:-1;41144:2743:0;;-1:-1:-1;;;;;41144:2743:0:i;36862:35::-;;;:::i;38975:43::-;;;;;;;;;;;;;;;;-1:-1:-1;38975:43:0;;;;;;;:::i;38259:45::-;;;;;;;;;;;;;;;;-1:-1:-1;38259:45:0;;;;;;;:::i;36766:28::-;;;:::i;38523:42::-;;;;;;;;;;;;;;;;-1:-1:-1;38523:42:0;;;;;;;:::i;49749:3157::-;;;;;;;;;;;;;;;;-1:-1:-1;49749:3157:0;;;;;;;:::i;60360:218::-;;;:::i;39079:38::-;;;;;;;;;;;;;;;;-1:-1:-1;39079:38:0;;;;;;;:::i;38432:43::-;;;;;;;;;;;;;;;;-1:-1:-1;38432:43:0;;;;;;;:::i;39448:115::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;38844:48;;;;;;;;;;;;;;;;-1:-1:-1;38844:48:0;;;;;;;:::i;37950:46::-;;;;;;;;;;;;;;;;-1:-1:-1;37950:46:0;;:::i;61686:112::-;;;:::i;37587:23::-;;;:::i;36944:24::-;;;:::i;37293:38::-;;;:::i;38715:46::-;;;;;;;;;;;;;;;;-1:-1:-1;38715:46:0;;;;;;;:::i;36675:29::-;;;:::i;38618:44::-;;;;;;;;;;;;;;;;-1:-1:-1;38618:44:0;;;;;;;:::i;60584:189::-;;;;;;;;;;;;;;;;-1:-1:-1;60584:189:0;;:::i;60800:722::-;;;:::i;61886:205::-;;;:::i;37847:32::-;;;;;;;;;;;;;;;;-1:-1:-1;37847:32:0;;:::i;61530:150::-;;;:::i;59587:244::-;;;:::i;62645:444::-;62709:10;;;;62695;:24;62687:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62779:11;;62816:28;;;;;;62838:4;62816:28;;;;;;62779:11;;;;;62751:10;;62779:11;;62816:13;;:28;;;;;;;;;;;;;;;62779:11;62816:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62816:28:0;;-1:-1:-1;62851:29:0;:16;;;62868:3;62816:28;62851:16;:29::i;:::-;62918:18;;62963:29;;;;;;62986:4;62963:29;;;;;;62918:18;;;;;62889:11;;62918:18;;62963:14;;:29;;;;;;;;;;;;;;;62918:18;62963:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62963:29:0;;-1:-1:-1;62999:31:0;:17;;;63017:3;62963:29;62999:17;:31::i;:::-;63044:39;;;63050:10;63044:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62645:444;;;;;:::o;60011:147::-;60087:10;;;;60073;:24;60065:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60127:20;:25;;;;;;;;;;;;;;;;;;60011:147::o;59861:144::-;59944:10;;;;59930;:24;59922:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59984:10;:15;;;;;;;;;;;;;;;59861:144::o;38175:40::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38175:40:0;;-1:-1:-1;38175:40:0:o;60200:154::-;60326:20;;60259:7;;60282:66;;60309:38;;:12;:5;60326:20;60309:9;:12::i;:::-;:16;;:38::i;:::-;60282:11;:22;;:26;:66::i;:::-;60275:73;60200:154;-1:-1:-1;;60200:154:0:o;45061:4137::-;45151:9;;;;45150:10;45142:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45204:9;45193:7;:20;;;;;;;;;:44;;;-1:-1:-1;45228:9:0;45217:7;:20;;;;;;;;;45193:44;45185:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45288:13;45304:19;:17;:19::i;:::-;45288:35;-1:-1:-1;45338:11:0;45330:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45380:5;45389:1;45380:10;45372:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45428:21;;:::i;:::-;45452:222;;;;;;;;45482:1;45452:222;;;;45503:1;45452:222;;;;45521:1;45452:222;;;;45543:1;45452:222;;;;45572:1;45452:222;;;;45603:1;45452:222;;;;45633:1;45452:222;;;;45665:1;45452:222;;;45428:246;;45732:26;:24;:26::i;:::-;45705:23;;;45681:77;45682:21;;;45681:77;-1:-1:-1;45771:7:0;:20;;;;;;;;;45767:188;;;45856:63;45912:6;45856:24;45881:5;45856:31;;;;;;;;;;;;;;;;;;;;;45888:18;45856:51;;;;;;;;;;:55;:63::i;:::-;45802:24;45827:5;45802:31;;;;;;;;;;;;;;;;;;;;;:51;:117;45928:19;;;45767:188;46071:9;46060:7;:20;;;;;;;;;46056:1265;;;46267:78;46324:20;;46268:50;46294:2;:23;;;46268:2;:21;;;:25;;:50;;;;:::i;:::-;46267:56;;:78::i;:::-;46253:11;;;:92;;;46370:20;;46369:45;;46403:2;:11;;;46369:45;;;46394:6;46369:45;46355:59;;;46452:20;;46437:36;;46355:59;46437:14;:36::i;:::-;46423:11;;;:50;;;46501:21;;;;-1:-1:-1;46482:618:0;;46654:11;;;;46631:20;;;:34;46482:618;;;46842:21;;;;46819:20;;;:44;;;46899:11;;;;:37;;:15;:37::i;:::-;46874:22;;;:62;;;47006:28;:35;;:84;;46874:62;47006:28;47035:5;;47006:35;;;;;;;;;;;;;;;;;;;47050:10;47042:19;;47006:84;46947:28;46976:5;46947:35;;;;;;;;;;;;;;;;;;;;;46991:10;46947:56;:143;46482:618;47165:80;47224:2;:20;;;47165:26;47192:5;47165:33;;;;;;;:80;47108:26;47135:5;47108:33;;;;;;;;;;;;;;;;;;;;;47150:10;47108:54;:137;47258:10;;:19;-1:-1:-1;47254:59:0;;;47302:10;;47291:22;;:6;;:10;:22::i;:::-;47279:9;;;:34;47254:59;47374:12;47389:50;47404:34;47432:5;47404:27;:34::i;:::-;47389:10;;;:14;:50::i;:::-;47538:10;;47519:14;;47374:65;;-1:-1:-1;47519:30:0;;:14;:18;:30::i;:::-;47502:14;:47;47655:10;;47628:15;:22;;:38;;47655:10;47628:15;47644:5;;47628:22;;;;;;;;;;;;;;:26;;:38;;;;:::i;:::-;47603:15;47619:5;47603:22;;;;;;;;;;;;;;;:63;;;;47804:53;47852:4;47804:18;47823:5;47804:25;;;;;;;;;;;;;;;;;;47838:7;47830:16;;;;;;;47804:53;47758:18;47777:5;47758:25;;;;;;;;;;;;;;;;;;47792:7;47784:16;;;;;;;;47758:43;;;;;;;;:99;47968:10;;47915:23;:30;;:64;;47968:10;47915:23;47939:5;;47915:30;;;;;:64;47864:23;47888:5;47864:30;;;;;;;;;;;;;;;;;;47903:7;47895:16;;;;;;;;47864:48;;;;;;;;:115;48096:10;;48032:18;;48025:82;;48032:18;;;;;48069:10;;48089:4;;48025:43;:82::i;:::-;48129:9;48118:7;:20;;;;;;;;;48114:123;;;48140:97;48177:10;48197:4;48227:9;;48204:2;:10;;;48217:7;48204:20;:32;;;;;48147:11;;;;;48140:97;;48204:32;;48140:36;:97::i;:::-;48348:20;48369:5;48348:27;;;;;;;;;;;;;;;;;;48384:7;48376:16;;;;;;;;48348:45;;;;;;;;;48326:91;;;;;;48400:10;48326:91;;;;;;;;;;;;48348:45;;;;;48326:73;;:91;;;;;48348:45;;48326:91;;;;;;;;48348:45;;48326:91;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48533:25;48559:5;48533:32;;;;;;;;;;;;;;;;;;48574:7;48566:16;;;;;;;;48533:50;;;;;;;;;48602:10;;48511:102;;;;;;48590:10;48511:102;;;;;;;;;;;;48533:50;;;;;48511:78;;:102;;;;;48533:50;;48511:102;;;;;;;;48533:50;;48511:102;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48627:187;48650:7;48642:16;;;;;;;;48660:2;:10;;;48672:2;:10;;;48684:2;:11;;;48697:2;:9;;;48708:2;:11;;;48721:2;:20;;;48743:2;:22;;;48767:2;:21;;;48790:2;:23;;;48627:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48826:204;48841:34;48869:5;48841:27;:34::i;:::-;48877:2;:10;;;48889:4;48895:20;48916:5;48895:27;;;;;;;;;;;;;;;;;;48931:7;48923:16;;;;;;;;48895:45;;;;;;;;;;;48942:5;48957:7;48949:16;;;;;;;;48967:10;48979:25;49005:5;48979:32;;;;;;;;;;;;;;;;;;49020:7;49012:16;;;;;;;;48979:50;;;;;;;;;48826:204;;;;;;;;;;;;;;;;;;;;48979:50;48826:204;;;;;;;;;;;;;;;;;;;;;;;;48979:50;48826:204;;;;;;;;;48979:50;48826:204;;;49042:150;49055:14;;49071:15;49087:5;49071:22;;;;;;;;;;;;;;;;49095:1;49098:23;49122:5;49098:30;;;;;;;;;;;;;;;;;;49137:7;49129:16;;;;;;;;49098:48;;;;;;;;;49148:18;49167:5;49148:25;;;;;;;;;;;;;;;;;;49182:7;49174:16;;;;;;;;49148:43;;;;;;;;;49042:150;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45061:4137;;;;;:::o;37639:164::-;;;;;;:::o;37195:35::-;;;;;;;;;:::o;36622:26::-;;;;;;:::o;62172:393::-;62256:10;;;;62242;:24;62234:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62314:18;;;62304:28;;;62314:18;;62304:28;;;;:53;;-1:-1:-1;62346:11:0;;;62336:21;;;62346:11;;62336:21;;62304:53;62296:90;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62444:28;;;;;;62466:4;62444:28;;;;;;62415:6;;62395:10;;62444:13;;;;;;:28;;;;;;;;;;;;;;:13;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62444:28:0;;-1:-1:-1;62479:27:0;:16;;;62496:3;62444:28;62479:16;:27::i;:::-;62520:39;;;62529:10;62520:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62172:393;;;;:::o;37044:29::-;;;;;;:::o;58084:1497::-;58181:8;;;;58167:10;:22;58159:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58226:9;;;;58225:10;58217:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58260:13;58276:19;:17;:19::i;:::-;58302:20;:38;;;;;;;;;;;;;;;;;;;:20;58441:18;58434:51;;;;;;58479:4;58434:51;;;;;;58260:35;;-1:-1:-1;58325:15:0;;-1:-1:-1;;58441:18:0;;;;;58434:36;;:51;;;;;;;;;;;;;;;58441:18;58434:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;58434:51:0;58655:24;:31;;58434:51;;-1:-1:-1;58601:106:0;;58680:5;;58655:31;;;;;;;;;;;;;;;;;;;:51;;58601:22;58624:5;58601:29;;;;;;;:106;58549:22;58572:5;58549:29;;;;;;;;;;;;;;;;;;;;;:49;:158;;;;58766:106;58820:24;58845:5;58820:31;;;;;;;;;;;;;;;;;;;;;58860:9;58820:51;;58766:22;58789:5;58766:29;;;;;;;;;;;;;;;;;;;;;58804:9;58796:18;;58766:106;58714:22;58737:5;58714:29;;;;;;;;;;;;;;;;;;;;;58752:9;58714:49;:158;;;;58936:116;58995:28;59024:5;58995:35;;;;;;;;;;;;;;;;;;;;;59039:10;58995:56;;58936:26;58963:5;58936:33;;;;;;;:116;58879:26;58906:5;58879:33;;;;;;;;;;;;;;;58921:10;58879:33;;;;;:54;:173;;;;59061:24;:31;;59086:5;;59061:31;;;;;;;;;;;;;;;;;;;:55;;;;59123:24;:31;;59148:5;;59123:31;;;;;;;;;;;;;59163:9;59123:31;;;;;:51;:55;;;;59185:28;:35;;59214:5;;59185:35;;;;;;;;;;;;;;;;;;;59229:10;59185:56;:60;59319:23;;:35;;59347:6;59319:27;:35::i;:::-;59293:23;:61;59366:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59476:18;;59469:64;;59476:18;;59509:15;59526:6;59469:39;:64::i;:::-;59540:12;:27;;;59568:6;59540:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58084:1497;;;;:::o;36528:33::-;;;;;;:::o;38348:38::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38348:38:0;;-1:-1:-1;38348:38:0:o;36434:25::-;;;;;;:::o;53061:4869::-;53242:1;53228:11;:15;:39;;;;53266:1;53247:16;:20;53228:39;53220:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53340:20;;;;;;;;;;53293:28;;;;;;;;53526:34;;;;;;:53;;;53578:1;53564:11;:15;53526:53;53522:1798;;;53675:36;;:::i;:::-;53714:41;;;;;;;:21;:41;;;;;;;;;53675:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53714:41;;53675:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;53772:17:0;;53675:80;;-1:-1:-1;53764:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53916:25;;;;;;53930:10;53916:25;;;;;;53880:18;;53945:11;;53916:13;;;;;;:25;;;;;;;;;;;;;;:13;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;53916:25:0;:40;;53908:78;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54062:16;;;;54040:19;54095:10;:21;;;:41;;;;;;;;;54087:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54174:11;54189:1;54174:16;54166:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54243:29;;;;:16;:29;;;;;;;;54235:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54318:20;54341:18;54360:11;54341:31;;;;;;;;;;;;;;;;;;54381:10;:18;;;54373:27;;;;;;;;54341:60;;;;;;;;;;-1:-1:-1;54501:17:0;;54500:68;;54526:42;54555:12;54526:24;:11;54542:7;54526:15;:24::i;:42::-;54500:68;;;54522:1;54500:68;54485:83;;54680:7;54594:83;54664:12;54594:23;54618:11;54594:36;;;;;;;;;;;;;;;;;;54639:10;:18;;;54631:27;;;;;;;;54594:65;;;;;;;;;;:69;:83::i;:::-;:93;;;;;;54577:110;;54788:7;54707:78;54772:12;54707:18;54726:11;54707:31;;;;;;;:78;:88;;;;;;54696:99;;54874:85;54944:14;54874:23;54898:11;54874:36;;;;;;;;;;;;;;;;;;54919:10;:18;;;54911:27;;;;;;;;54874:65;;;;;;;;;;:69;:85::i;:::-;54806:23;54830:11;54806:36;;;;;;;;;;;;;;;;;;54851:10;:18;;;54843:27;;;;;;;;54806:65;;;;;;;;:153;;;;55031:74;55096:8;55031:18;55050:11;55031:31;;;;;;;:74;54968:18;54987:11;54968:31;;;;;;;;;;;;;;;;;;55008:10;:18;;;55000:27;;;;;;;;54968:60;;;;;;;;:137;;;;55177:77;55242:11;55177:18;55196:11;55177:31;;;;;;;:77;55114:18;55133:11;55114:31;;;;;;;;;;;;;;;;;;55154:10;:18;;;55146:27;;;;;;;;55114:60;;;;;;;;:140;55279:13;;:33;;55297:14;55279:17;:33::i;:::-;55263:13;:49;-1:-1:-1;;;;53522:1798:0;55385:39;;;;;;;:63;;;55447:1;55428:16;:20;55385:63;55381:1339;;;55544:36;;:::i;:::-;55583:46;;;;;;;:21;:46;;;;;;;;;55544:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55583:46;;55544:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;55646:17:0;;55544:85;;-1:-1:-1;55638:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55800:25;;;;;;55814:10;55800:25;;;;;;55759:23;;55829:16;;55800:13;;;;;;:25;;;;;;;;;;;;;;:13;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;55800:25:0;:45;;55792:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55956:16;;;;56014:21;55989:10;:21;;;:46;;;;;;;;;55981:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56082:11;56097:1;56082:16;56074:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56151:29;;;;:16;:29;;;;;;;;56143:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56296:87;56366:16;56296:23;56320:11;56296:36;;;;;;;;;;;;;;;;;;56341:10;:18;;;56333:27;;;;;;;56296:87;56228:23;56252:11;56228:36;;;;;;;;;;;;;;;;;;56273:10;:18;;;56265:27;;;;;;;;56228:65;;;;;;;;:155;;;;56423:50;56456:16;56423:15;56439:11;56423:28;;;;;;;;;;;;;;;;:32;;:50;;;;:::i;:::-;56392:15;56408:11;56392:28;;;;;;;;;;;;;;;;;:81;56499:14;;:36;;56518:16;56499:18;:36::i;:::-;56482:14;:53;56570:23;;:45;;56598:16;56570:27;:45::i;:::-;56544:23;:71;56650:9;56628:10;:18;;;:31;;;;;;;;;56624:88;;;56703:9;;56674:16;56693:7;56674:26;:38;;;;;;56661:51;;56624:88;55381:1339;;;;56749:34;;;;;;;:53;;;56801:1;56787:11;:15;56749:53;56745:518;;;56899:25;;;;;;56913:10;56899:25;;;;;;56863:18;;56928:11;;56899:13;;;;;;:25;;;;;;;;;;;;;;:13;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;56899:25:0;:40;;56891:78;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56978:33;;;;;;56987:10;56978:33;;;;;;;;;;;;:8;;;;;;:33;;;;;-1:-1:-1;;56978:33:0;;;;;;;-1:-1:-1;56978:8:0;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57041:1;57024:14;:18;57020:100;;;57055:55;;;;;;;;;;;;57099:10;57055:55;;;;;;:27;;;;;;:55;;;;;-1:-1:-1;;57055:55:0;;;;;;;-1:-1:-1;57055:27:0;:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57020:100;57135:11;;57128:54;;57135:11;;57161:10;57173:8;57128:32;:54::i;:::-;57196:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56745:518;;57273:39;;;;;;;:63;;;57335:1;57316:16;:20;57273:63;57269:491;;;57438:25;;;;;;57452:10;57438:25;;;;;;57397:23;;57467:16;;57438:13;;;;;;:25;;;;;;;;;;;;;;:13;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;57438:25:0;:45;;57430:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57527:38;;;;;;57536:10;57527:38;;;;;;;;;;;;:8;;;;;;:38;;;;;-1:-1:-1;;57527:38:0;;;;;;;-1:-1:-1;57527:8:0;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;57574:57:0;;;;;;;;;;;;57620:10;57574:57;;;;;;:27;;;;-1:-1:-1;57574:27:0;;-1:-1:-1;57574:57:0;;;;;-1:-1:-1;;57574:57:0;;;;;;;-1:-1:-1;57574:27:0;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;57647:11:0;;57640:56;;-1:-1:-1;57647:11:0;;;-1:-1:-1;57673:10:0;57685;57640:32;:56::i;:::-;57710:42;;;;;;;;;;;;;;;;;57269:491;;57777:34;;;;;;;:53;;;57829:1;57815:11;:15;57777:53;57776:124;;;-1:-1:-1;57836:39:0;;;;;;;:63;;;57898:1;57879:16;:20;57836:63;57768:156;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53061:4869;;;;;;;;;:::o;41144:2743::-;41305:23;:30;:39;;41297:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41382:10;;:24;:10;41396;41382:24;41374:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41438:15;:23;;;;;;;;;41459:1;41438:23;;;;;;;41468:32;;;;;;;;;;;41438:23;41468:32;;;;;;;;;;;:18;:32;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;41507:37:0;;;;;;;;-1:-1:-1;41507:37:0;;;;;;;;;;;;;;;:23;:37;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;41551:36:0;;;;;;;;-1:-1:-1;41551:36:0;;;;;;;;;;;;;;;:22;:36;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;41594:38:0;;;;;;;;-1:-1:-1;41594:38:0;;;;;;;;;;;;;;;:24;:38;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;41639:40:0;;;;;;;;-1:-1:-1;41639:40:0;;;;;;;;;;;;;;;:26;:40;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;41686:42:0;;;;;;;;-1:-1:-1;41686:42:0;;;;;;;;;;;;;;;:28;:42;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;41735:37:0;;;;;;;;-1:-1:-1;41735:37:0;;;;;;;;;;;;;;;:23;:37;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;41779:32:0;;;;;;;;-1:-1:-1;41779:32:0;;;;;;;;;;;;;;;:18;:32;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;41820:252:0;;;;;;;;;:20;;:252;41892:31;-1:-1:-1;41892:51:0;;;;;;;;;;;;;;;;;;;41820:252;;;;;41952:31;41992:10;41952:52;;;;;;;;;;;;;;;;;;;41820:252;;;;;42013:31;42053:9;42013:51;;;;;;;;;;;;;;;;;;;41820:252;;;;;;;;;;;;-1:-1:-1;41820:252:0;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;42081:272:0;;;;;;;;;:25;;:272;42158:36;-1:-1:-1;42158:56:0;;;;;;;;;;;;;;;;;;;42081:272;;;;;42223:36;42268:10;42223:57;;;;;;;;;;;;;;;;;;;42081:272;;;;;42289:36;42334:9;42289:56;;;;;;;;;;;;;;;;;;;42081:272;;;;;;;;;;;;-1:-1:-1;42081:272:0;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;42532:133:0;;;;;;;;42568:4;42532:133;;;;;;;;;;;-1:-1:-1;42532:133:0;;;;42641:16;42532:133;;42455:21;:74;42477:31;42455:74;42477:51;;;;;;;;;;;;;;42455:74;;;;;;;;;;;;;;;:210;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42455:210:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;42752:134:0;;;;;;;;42788:4;42752:134;;;;;;;;;;;-1:-1:-1;42752:134:0;;;;;;;;42862:16;42752:134;;42674:21;:75;42696:31;42736:10;42696:52;;;;;;;;;;;;;;42674:75;;;;;;;;;;;;;;;:212;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42674:212:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;42972:133:0;;;;;;;;43008:4;42972:133;;;;;;;;;-1:-1:-1;42972:133:0;;43051:9;42972:133;;;;43081:16;42972:133;;42895:21;:74;42917:31;42957:9;42917:51;;;;;;;;;;;;;;42895:74;;;;;;;;;;;;;;;:210;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42895:210:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;43283:138:0;;;;;;;;43319:4;43283:138;;;;;;;;;-1:-1:-1;43283:138:0;;-1:-1:-1;43283:138:0;;;;43392:21;43283:138;;43201:21;:79;43223:36;43201:79;43223:56;;;;;;;;;;;;;;43201:79;;;;;;;;;;;;;;;:220;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;43201:220:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;43513:139:0;;;;;;;;43549:4;43513:139;;;;;;;;;;;-1:-1:-1;43513:139:0;;;;;;;;43623:21;43513:139;;43430:21;:80;43452:36;43497:10;43452:57;;;;;;;;;;;;;;43430:80;;;;;;;;;;;;;;;:222;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;43430:222:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;43743:138:0;;;;;;;;43779:4;43743:138;;;;;;;;;-1:-1:-1;43743:138:0;;43822:9;43743:138;;;;43852:21;43743:138;;43661:21;:79;43683:36;43728:9;43683:56;;;;;;;;;;;;;;43661:79;;;;;;;;;;;;;;;:220;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;43661:220:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;41144:2743:0:o;36862:35::-;;;;:::o;38975:43::-;;;;;;;;;;;;38259:45;;;;;;;;;;;;36766:28;;;;:::o;38523:42::-;;;;;;;;;;;;49749:3157;49854:8;;;;49840:10;:22;49832:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49899:23;;;;:16;:23;;;;;;;;49898:24;49890:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49958:21;49982:19;:17;:19::i;:::-;49958:43;;50024:13;50016:5;:21;50008:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50078:29;;:::i;:::-;-1:-1:-1;50110:191:0;;;;;;;;-1:-1:-1;50110:191:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50335:17;;;50308:44;;;50386:39;;:13;:39::i;:::-;50367:15;:58;;50359:100;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50560:22;:24;:52;;50605:6;;50560:40;;50589:10;50560:28;:40::i;:52::-;50511:18;50530:5;50511:25;;;;;;;;;;;;;;;;;;;;;:45;:101;50668:25;;:53;;50714:6;;50668:41;;50698:10;50668:29;:41::i;:53::-;50619:18;50638:5;50619:25;;;;;;;;;;;;;;;;;;;;;50653:10;50619:46;:102;50777:24;;:52;;50822:6;;50777:40;;50806:10;50777:28;:40::i;:52::-;50728:18;50747:5;50728:25;;;;;;;;;;;;;;;;;;;;;50762:9;50728:45;:101;50860:24;;50886:18;:25;;50843:184;;50860:24;50886:18;50905:5;;50886:25;;;;;;;;;;;;;;;;;;;:45;;50933:18;50952:5;50933:25;;;;;;;;;;;;;;;;;;;;;50967:10;50933:46;;50981:18;51000:5;50981:25;;;;;;;;;;;;;;;;;;;;;51015:9;50981:45;;50843:184;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51415:20;;51491:23;;51470:45;;;;;;;;;;;;;;51415:20;;;;;;;;;51470;;:45;;;;;;;;;;;;;;-1:-1:-1;51415:20:0;51470:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;51470:45:0;;51443:24;;:72;;;51538:13;;:43;;:17;:43::i;:::-;51522:13;:59;;;;51686:96;51736:18;51755:5;51736:25;;;;;;;;;;;;;;;;;;;;;51770:9;51736:45;;51686:18;51705:5;51686:25;;;;;;;:96;51663:9;:20;;:119;;;;;51826:84;51889:9;:20;;;51826:58;51876:7;51826:18;51845:5;51826:25;;;;;;;;;;;;;;;;;;;;;51860:9;51852:18;;51826:84;51789:34;;;:121;;;52078:20;;51995:24;;;;51994:105;;51995:77;;52064:7;;51995:64;;:24;:28;:64::i;51994:105::-;51963:28;;;:136;;;52137:24;;;;:58;;:28;:58::i;:::-;52106:28;;;:89;;;52246:23;:30;;52270:5;;52246:30;;;;;;;;;;;;;;;;;;;:82;;;;52335:23;:30;;52359:5;;52335:30;;;;;;;;;;;;;;;;;;;52374:10;52335:51;:55;52451:28;;;;52397:23;:30;;52421:5;;52397:30;;;;;;;;;;;;;;;;;;;52436:9;52397:50;:82;;;;52583:257;52602:5;52609:9;:28;;;52639:1;52642:9;:28;;;52680:18;52699:5;52680:25;;;;;;;;;;;;;;;;;;;;;:45;;52736:18;52755:5;52736:25;;;;;;;;;;;;;;;;;;;;;52770:10;52736:46;;52793:18;52812:5;52793:25;;;;;;;;;;;;;;;;;;;;;52827:9;52793:45;;52583:257;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52847:23;;;;:16;:23;;;;;:30;;;;52873:4;52847:30;;;52884:16;;:::i;:::-;-1:-1:-1;;;;;;49749:3157:0:o;60360:218::-;60452:11;:22;60410:7;;60434:15;:40;60426:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60552:20;;:11;60526:22;60508:15;:40;60552:20;60507:65;;;;;60500:72;;60360:218;:::o;39079:38::-;;;;;;;;;;;;38432:43;;;;;;;;;;;;39448:115;;;;;;;;:::o;38844:48::-;;;;;;;;;;;;37950:46;;;;;;;;;;;;;;;:::o;61686:112::-;61774:18;;;;61686:112;:::o;37587:23::-;;;;;;:::o;36944:24::-;;;;:::o;37293:38::-;;;;:::o;38715:46::-;;;;;;;;;;;;36675:29;;;;:::o;38618:44::-;;;;;;;;;;;;60584:189;60657:7;60680:87;60751:15;60680:66;60707:38;60724:11;:20;;;60707:12;60717:1;60707:5;:9;;:12;;;;:::i;60680:66::-;:70;;:87::i;60800:722::-;60856:7;60865;60881:13;60897:19;:17;:19::i;:::-;60881:35;;60923:21;60947:113;61005:26;61032:5;61005:33;;;;;;;;;;;;;;;;;;;;;61047:10;61005:54;;60947:26;60974:5;60947:33;;;;;;;:113;60923:137;;61067:23;61093:117;61153:28;61182:5;61153:35;;;;;;;;;;;;;;;;;;;;;61197:10;61153:56;;61093:28;61122:5;61093:35;;;;;;;:117;61067:143;;61217:18;61238:22;61261:5;61238:29;;;;;;;;;;;;;;;;;;;;;:49;;61217:70;;61294:20;61317:24;61342:5;61317:31;;;;;;;;;;;;;;;;;;;;;:51;;61294:74;;61397:13;61384:10;:26;:59;;61442:1;61384:59;;;61426:13;61413:10;:26;61384:59;61462:15;61447:12;:30;:67;;61513:1;61447:67;;;61495:15;61480:12;:30;61447:67;61375:141;;;;;;;;;60800:722;;:::o;61886:205::-;61951:10;;;;61937;:24;61929:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62017:11;:22;62042:8;62017:33;61999:15;:51;61991:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62070:15;62077:8;;62070:15;:::i;:::-;61886:205::o;37847:32::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;37847:32:0;:::o;61530:150::-;61629:11;:22;61653:20;;61530:150;;:::o;59587:244::-;59654:8;;;;59640:10;:22;;:50;;-1:-1:-1;59680:10:0;;;;59666;:24;59640:50;59632:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59763:6;59744:16;59758:1;59744:13;:16::i;:::-;:25;59726:15;:43;59718:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59809:9;:16;;;;59821:4;59809:16;;;59587:244::o;31206:171::-;31312:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31335:23;31312:58;;;31285:86;;31305:5;;31285:19;:86::i;:::-;31206:171;;;:::o;3386:181::-;3444:7;3476:5;;;3500:6;;;;3492:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3558:1;3386:181;-1:-1:-1;;;3386:181:0:o;4740:471::-;4798:7;5043:6;5039:47;;-1:-1:-1;5073:1:0;5066:8;;5039:47;5110:5;;;5114:1;5110;:5;:1;5134:5;;;;;:10;5126:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5687:132;5745:7;5772:39;5776:1;5779;5772:39;;;;;;;;;;;;;;;;;:3;:39::i;3850:136::-;3908:7;3935:43;3939:1;3942;3935:43;;;;;;;;;;;;;;;;;:3;:43::i;31383:199::-;31507:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31530:27;31507:68;;;31480:96;;31500:5;;31480:19;:96::i;:::-;31383:199;;;;:::o;33407:723::-;33815:23;33841:69;33869:4;33841:69;;;;;;;;;;;;;;;;;33849:5;33841:27;;;;:69;;;;;:::i;:::-;33921:17;;33815:95;;-1:-1:-1;33921:21:0;33917:208;;34051:10;34040:30;;;;;;;;;;;;;;;-1:-1:-1;34040:30:0;34032:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6315:278;6401:7;6436:12;6429:5;6421:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6460:9;6476:1;6472;:5;;;;;;;6315:278;-1:-1:-1;;;;;6315:278:0:o;4289:192::-;4375:7;4411:12;4403:6;;;;4395:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;4447:5:0;;;4289:192::o;15257:195::-;15360:12;15392:52;15414:6;15422:4;15428:1;15431:12;15392:21;:52::i;:::-;15385:59;15257:195;-1:-1:-1;;;;15257:195:0:o;16309:530::-;16436:12;16494:5;16469:21;:30;;16461:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16561:18;16572:6;16561:10;:18::i;:::-;16553:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16687:12;16701:23;16728:6;:11;;16748:5;16756:4;16728:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16686:75;;;;16779:52;16797:7;16806:10;16818:12;16779:17;:52::i;:::-;16772:59;16309:530;-1:-1:-1;;;;;;;16309:530:0:o;12337:422::-;12704:20;12743:8;;;12337:422::o;18849:742::-;18964:12;18993:7;18989:595;;;-1:-1:-1;19024:10:0;19017:17;;18989:595;19138:17;;:21;19134:439;;19401:10;19395:17;19462:15;19449:10;19445:2;19441:19;19434:44;19349:148;19537:20;;;;;;;;;;;;;;;;;;;;19544:12;;19537:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;
Swarm Source
ipfs://97d5fecf88b2bcdd4005ee7c397b179c613d1e8b7d00906bcd77e7b404e4c84b
Loading...
Loading
Loading...
Loading
Net Worth in USD
$17.14
Net Worth in ETH
0.007707
Token Allocations
SFI
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $83.55 | 0.2051 | $17.14 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.