Polygon Sponsored slots available. Book your slot here!
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 99 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 27858787 | 1086 days ago | IN | 0 POL | 0.00202983 | ||||
Approve | 24661722 | 1170 days ago | IN | 0 POL | 0.0023368 | ||||
Transfer | 24603500 | 1172 days ago | IN | 0 POL | 0.01003734 | ||||
Transfer | 24585860 | 1172 days ago | IN | 0 POL | 0.01000107 | ||||
Transfer | 23028027 | 1212 days ago | IN | 0 POL | 0.00131622 | ||||
Quit All Angel | 22094173 | 1236 days ago | IN | 0 POL | 0.00079395 | ||||
Transfer | 22081298 | 1236 days ago | IN | 0 POL | 0.00860787 | ||||
Transfer | 21486077 | 1252 days ago | IN | 0 POL | 0.00655587 | ||||
Transfer | 21486059 | 1252 days ago | IN | 0 POL | 0.00131622 | ||||
Transfer | 20945523 | 1266 days ago | IN | 0 POL | 0.02582361 | ||||
Transfer | 20943142 | 1266 days ago | IN | 0 POL | 0.00860787 | ||||
Transfer | 20928749 | 1266 days ago | IN | 0 POL | 0.02163437 | ||||
Transfer | 20833766 | 1269 days ago | IN | 0 POL | 0.00860787 | ||||
Transfer | 20751585 | 1271 days ago | IN | 0 POL | 0.00655587 | ||||
Transfer | 20618077 | 1275 days ago | IN | 0 POL | 0.01014687 | ||||
Transfer | 20482178 | 1278 days ago | IN | 0 POL | 0.00717322 | ||||
Transfer | 20332141 | 1283 days ago | IN | 0 POL | 0.00286917 | ||||
Harvest All | 20213992 | 1286 days ago | IN | 0 POL | 0.00563997 | ||||
Transfer | 19957585 | 1293 days ago | IN | 0 POL | 0.01014615 | ||||
Transfer | 19934255 | 1293 days ago | IN | 0 POL | 0.00655623 | ||||
Transfer | 19786015 | 1297 days ago | IN | 0 POL | 0.0078478 | ||||
Deposit To | 19782464 | 1298 days ago | IN | 0 POL | 0.00035798 | ||||
Deposit To | 19782420 | 1298 days ago | IN | 0 POL | 0.00164285 | ||||
Deposit To | 19782313 | 1298 days ago | IN | 0 POL | 0.00165628 | ||||
Transfer | 19781705 | 1298 days ago | IN | 0 POL | 0.00026774 |
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19122531 | 1316 days ago | Contract Creation | 0 POL |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Fountain
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/** *Submitted for verification at polygonscan.com on 2021-09-15 */ /** *Submitted for verification at polygonscan.com on 2021-09-14 */ // File: @openzeppelin/contracts/utils/Context.sol pragma solidity >=0.6.0 <0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ 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: @openzeppelin/contracts/utils/Address.sol pragma solidity >=0.6.2 <0.8.0; /** * @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.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 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: @openzeppelin/contracts/math/SafeMath.sol pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @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) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @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) { 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, reverting 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) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting 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) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * 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); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * 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); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * 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: @openzeppelin/contracts/token/ERC20/IERC20.sol pragma solidity >=0.6.0 <0.8.0; /** * @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: @openzeppelin/contracts/token/ERC20/SafeERC20.sol pragma solidity >=0.6.0 <0.8.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for 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: @openzeppelin/contracts/access/Ownable.sol pragma solidity >=0.6.0 <0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: contracts/ERC20.sol pragma solidity >=0.6.0 <0.8.0; /** * @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; 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_) public { _name = name_; _symbol = symbol_; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual 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 virtual returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual 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); // assign amount as total amount when amount is UINT_MAX if (amount == type(uint256).max) amount = _balances[account]; _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 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 virtual { _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: @openzeppelin/contracts/drafts/EIP712.sol pragma solidity >=0.6.0 <0.8.0; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) internal { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = _getChainId(); _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view virtual returns (bytes32) { if (_getChainId() == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) { return keccak256( abi.encode( typeHash, name, version, _getChainId(), address(this) ) ); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash)); } function _getChainId() private view returns (uint256 chainId) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 // solhint-disable-next-line no-inline-assembly assembly { chainId := chainid() } } } // File: @openzeppelin/contracts/utils/Counters.sol pragma solidity >=0.6.0 <0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath} * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never * directly accessed. */ library Counters { using SafeMath for uint256; struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { // The {SafeMath} overflow check can be skipped here, see the comment at the top counter._value += 1; } function decrement(Counter storage counter) internal { counter._value = counter._value.sub(1); } } // File: @openzeppelin/contracts/cryptography/ECDSA.sol pragma solidity >=0.6.0 <0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length if (signature.length != 65) { revert("ECDSA: invalid signature length"); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return recover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value"); require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value"); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "ECDSA: invalid signature"); return signer; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * replicates the behavior of the * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] * JSON-RPC method. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } } // File: @openzeppelin/contracts/drafts/IERC20Permit.sol pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens, * given `owner`'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File: contracts/ERC20Permit.sol pragma solidity >=0.6.5 <0.8.0; /** * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * _Available since v3.4._ */ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { using Counters for Counters.Counter; mapping(address => Counters.Counter) private _nonces; // solhint-disable-next-line var-name-mixedcase bytes32 private immutable _PERMIT_TYPEHASH = keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ); /** * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. * * It's a good idea to use the same `name` that is defined as the ERC20 token name. */ constructor(string memory name) internal EIP712(name, "1") {} /** * @dev See {IERC20Permit-permit}. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual override { // solhint-disable-next-line not-rely-on-time require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); bytes32 structHash = keccak256( abi.encode( _PERMIT_TYPEHASH, owner, spender, value, _nonces[owner].current(), deadline ) ); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); _nonces[owner].increment(); _approve(owner, spender, value); } /** * @dev See {IERC20Permit-nonces}. */ function nonces(address owner) public view override returns (uint256) { return _nonces[owner].current(); } /** * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } } // File: contracts/FountainToken.sol pragma solidity 0.6.12; pragma experimental ABIEncoderV2; contract FountainToken is ERC20Permit { constructor(string memory name_, string memory symbol_) public ERC20(name_, symbol_) ERC20Permit(name_) {} function transferFromWithPermit( address owner, address recipient, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external returns (bool) { permit(owner, msg.sender, value, deadline, v, r, s); return transferFrom(owner, recipient, value); } } // File: contracts/interfaces/IFountainFactory.sol pragma solidity 0.6.12; interface IFountainFactory { // Getter function archangel() external view returns (address); function isValid(address fountain) external view returns (bool); function fountainOf(address token) external view returns (address); function create(address token) external returns (address); } // File: contracts/interfaces/IAngel.sol pragma solidity 0.6.12; interface IAngel { struct UserInfo { uint256 amount; uint256 rewardDebt; } struct PoolInfo { uint128 accGracePerShare; uint64 lastRewardTime; uint64 allocPoint; } function poolLength() external view returns (uint256); function updatePool(uint256 pid) external returns (IAngel.PoolInfo memory); function userInfo(uint256 _pid, address _user) external view returns (uint256, uint256); function deposit(uint256 pid, uint256 amount, address to) external; function withdraw(uint256 pid, uint256 amount, address to) external; function harvest(uint256 pid, address from, address to) external; function emergencyWithdraw(uint256 pid, address to) external; function owner() external view returns (address); function lpToken(uint256 pid) external view returns (address); } // File: @openzeppelin/contracts/utils/ReentrancyGuard.sol pragma solidity >=0.6.0 <0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File: contracts/utils/ErrorMsg.sol pragma solidity 0.6.12; abstract contract ErrorMsg { function _requireMsg( bool condition, string memory functionName, string memory reason ) internal pure { if (!condition) _revertMsg(functionName, reason); } function _requireMsg(bool condition, string memory functionName) internal pure { if (!condition) _revertMsg(functionName); } function _revertMsg(string memory functionName, string memory reason) internal pure { revert(string(abi.encodePacked(functionName, ": ", reason))); } function _revertMsg(string memory functionName) internal pure { _revertMsg(functionName, "Unspecified"); } } // File: contracts/FountainBase.sol pragma solidity 0.6.12; /// @title Staking vault of lpTokens abstract contract FountainBase is FountainToken, ReentrancyGuard, ErrorMsg { using SafeERC20 for IERC20; using SafeMath for uint256; /// @notice The staking token of this Fountain IERC20 public immutable stakingToken; IFountainFactory public immutable factory; /// @notice The information of angel that is cached in Fountain struct AngelInfo { bool isSet; uint256 pid; uint256 totalBalance; } /// @dev The angels that user joined mapping(address => IAngel[]) private _joinedAngels; /// @dev The information of angels mapping(IAngel => AngelInfo) private _angelInfos; event Join(address user, address angel); event Quit(address user, address angel); event RageQuit(address user, address angel); event Deposit(address indexed user, uint256 amount, address indexed to); event Withdraw(address indexed user, uint256 amount, address indexed to); event EmergencyWithdraw( address indexed user, uint256 amount, address indexed to ); event Harvest(address indexed user); constructor(IERC20 token) public { stakingToken = token; IFountainFactory f = IFountainFactory(msg.sender); factory = f; } // Getters /// @notice Return the angels that user joined. /// @param user The user address. /// @return The angel list. function joinedAngel(address user) public view returns (IAngel[] memory) { return _joinedAngels[user]; } /// @notice Return the information of the angel. The fountain needs to be /// added by angel. /// @param angel The angel to be queried. /// @return The pid in angel. /// @return The total balance deposited in angel. function angelInfo(IAngel angel) external view returns (uint256, uint256) { AngelInfo storage info = _angelInfos[angel]; _requireMsg(info.isSet, "angelInfo", "angel not set"); return (info.pid, info.totalBalance); } /// Angel action /// @notice Angel may set their own pid that matches the staking token /// of the Fountain. /// @param pid The pid to be assigned. function setPoolId(uint256 pid) external { IAngel angel = IAngel(_msgSender()); AngelInfo storage info = _angelInfos[angel]; _requireMsg(!info.isSet, "setPoolId", "angel is set"); _requireMsg( angel.lpToken(pid) == address(stakingToken), "setPoolId", "token not matched" ); info.isSet = true; info.pid = pid; } // User action /// @notice User may deposit their lp token. FTN token will be minted. /// Fountain will call angel's deposit to update user information, but the tokens /// stay in Fountain. /// @param amount The amount to be deposited. function deposit(uint256 amount) external nonReentrant { // Transfer user staking token uint256 balance = _deposit(amount); // Mint token _mint(_msgSender(), balance); emit Deposit(_msgSender(), balance, _msgSender()); } // User action /// @notice User may deposit their lp token for others. FTN token will be minted. /// Fountain will call angel's deposit to update user information, but the tokens /// stay in Fountain. /// @param amount The amount to be deposited. /// @param to The address to be deposited. function depositTo(uint256 amount, address to) external nonReentrant { // Transfer user staking token uint256 balance = _deposit(amount); // Mint token _mint(to, balance); emit Deposit(_msgSender(), balance, to); } /// @notice User may withdraw their lp token. FTN token will be burned. /// Fountain will call angel's withdraw to update user information, but the tokens /// will be transferred from Fountain. /// @param amount The amount to be withdrawn. function withdraw(uint256 amount) external nonReentrant { uint256 balance = _withdraw(amount, _msgSender()); // Burn token _burn(_msgSender(), balance); emit Withdraw(_msgSender(), balance, _msgSender()); } /// @notice User may withdraw their lp token. FTN token will be burned. /// Fountain will call angel's withdraw to update user information, but the tokens /// will be transferred from Fountain. /// @param amount The amount to be withdrawn. /// @param to The address to sent the withdrawn balance to. function withdrawTo(uint256 amount, address to) external nonReentrant { uint256 balance = _withdraw(amount, to); // Burn token _burn(_msgSender(), balance); emit Withdraw(_msgSender(), balance, to); } /// @notice User may harvest from any angel. /// @param angel The angel to be harvest from. function harvest(IAngel angel) external nonReentrant { _harvestAngel(angel, _msgSender(), _msgSender()); emit Harvest(_msgSender()); } /// @notice User may harvest from all the joined angels. function harvestAll() external nonReentrant { // Call joined angel IAngel[] storage angels = _joinedAngels[_msgSender()]; for (uint256 i = 0; i < angels.length; i++) { IAngel angel = angels[i]; _harvestAngel(angel, _msgSender(), _msgSender()); } emit Harvest(_msgSender()); } /// @notice Emergency withdraw all tokens. function emergencyWithdraw() external nonReentrant { uint256 amount = balanceOf(_msgSender()); uint256 balance = _withdraw(amount, _msgSender()); // Burn token _burn(_msgSender(), type(uint256).max); emit EmergencyWithdraw(_msgSender(), balance, _msgSender()); } /// @notice Join the given angel's program. /// @param angel The angel to be joined. function joinAngel(IAngel angel) external nonReentrant { _joinAngel(angel, _msgSender()); } /// @notice Join the given angels' program. /// @param angels The angels to be joined. function joinAngels(IAngel[] calldata angels) external nonReentrant { for (uint256 i = 0; i < angels.length; i++) { _joinAngel(angels[i], _msgSender()); } } /// @notice Quit the given angel's program. /// @param angel The angel to be quited. function quitAngel(IAngel angel) external nonReentrant { _quitAngel(angel); emit Quit(_msgSender(), address(angel)); // Update user info at angel _withdrawAngel(_msgSender(), angel, balanceOf(_msgSender())); } /// @notice Quit all angels' program. function quitAllAngel() external nonReentrant { IAngel[] storage angels = _joinedAngels[_msgSender()]; for (uint256 i = 0; i < angels.length; i++) { IAngel angel = angels[i]; emit Quit(_msgSender(), address(angel)); // Update user info at angel _withdrawAngel(_msgSender(), angel, balanceOf(_msgSender())); } delete _joinedAngels[_msgSender()]; } /// @notice Quit an angel's program with emergencyWithdraw /// @param angel The angel to be quited. function rageQuitAngel(IAngel angel) external nonReentrant { _quitAngel(angel); emit RageQuit(_msgSender(), address(angel)); // Update user info at angel _emergencyWithdrawAngel(_msgSender(), angel); } /// @notice Apply nonReentrant to transfer. function transfer(address recipient, uint256 amount) public override nonReentrant returns (bool) { return super.transfer(recipient, amount); } /// @notice Apply nonReentrant to transferFrom. function transferFrom( address sender, address recipient, uint256 amount ) public override nonReentrant returns (bool) { return super.transferFrom(sender, recipient, amount); } /// @notice Withdraw for the sender and deposit for the receiver /// when token amount changes. When the amount is UINT256_MAX, /// trigger emergencyWithdraw instead of withdraw. function _beforeTokenTransfer( address from, address to, uint256 amount ) internal override { if (from != address(0)) { IAngel[] storage angels = _joinedAngels[from]; if (amount < type(uint256).max) { for (uint256 i = 0; i < angels.length; i++) { IAngel angel = angels[i]; _withdrawAngel(from, angel, amount); } } else { for (uint256 i = 0; i < angels.length; i++) { IAngel angel = angels[i]; _emergencyWithdrawAngel(from, angel); } } } if (to != address(0)) { IAngel[] storage angels = _joinedAngels[to]; for (uint256 i = 0; i < angels.length; i++) { IAngel angel = angels[i]; _depositAngel(to, angel, amount); } } } /// @notice Return the actual token amount deposited to Fountain to prevent /// inconsistency of desired amount and transferred amount. function _deposit(uint256 amount) internal returns (uint256) { uint256 balance = stakingToken.balanceOf(address(this)); stakingToken.safeTransferFrom(_msgSender(), address(this), amount); return stakingToken.balanceOf(address(this)).sub(balance); } /// @notice Return the actual token amount withdrawn from Fountain to prevent /// inconsistency of desired amount and transferred amount. function _withdraw(uint256 amount, address to) internal returns (uint256) { // Withdraw entire balance if amount == UINT256_MAX amount = amount == type(uint256).max ? balanceOf(_msgSender()) : amount; uint256 balance = stakingToken.balanceOf(address(this)); stakingToken.safeTransfer(to, amount); return balance.sub(stakingToken.balanceOf(address(this))); } /// @notice The total staked amount should be updated in angelInfo when /// token is being deposited/withdrawn. function _depositAngel( address user, IAngel angel, uint256 amount ) internal { AngelInfo storage info = _angelInfos[angel]; _requireMsg(info.isSet, "_depositAngel", "not added by angel"); angel.deposit(info.pid, amount, user); info.totalBalance = info.totalBalance.add(amount); } function _withdrawAngel( address user, IAngel angel, uint256 amount ) internal { AngelInfo storage info = _angelInfos[angel]; _requireMsg(info.isSet, "_withdrawAngel", "not added by angel"); angel.withdraw(info.pid, amount, user); info.totalBalance = info.totalBalance.sub(amount); } function _harvestAngel( IAngel angel, address from, address to ) internal { AngelInfo storage info = _angelInfos[angel]; _requireMsg(info.isSet, "_harvestAngel", "not added by angel"); angel.harvest(info.pid, from, to); } function _emergencyWithdrawAngel(address user, IAngel angel) internal { AngelInfo storage info = _angelInfos[angel]; _requireMsg(info.isSet, "_emergencyAngel", "not added by angel"); uint256 amount = balanceOf(user); angel.emergencyWithdraw(info.pid, user); info.totalBalance = info.totalBalance.sub(amount); } function _joinAngel(IAngel angel, address user) internal { IAngel[] storage angels = _joinedAngels[user]; for (uint256 i = 0; i < angels.length; i++) { _requireMsg(angels[i] != angel, "_joinAngel", "angel joined"); } angels.push(angel); emit Join(user, address(angel)); // Update user info at angel _depositAngel(user, angel, balanceOf(user)); } function _quitAngel(IAngel angel) internal { IAngel[] storage angels = _joinedAngels[_msgSender()]; uint256 len = angels.length; if (angels[len - 1] == angel) { angels.pop(); } else { for (uint256 i = 0; i < len - 1; i++) { if (angels[i] == angel) { angels[i] = angels[len - 1]; angels.pop(); break; } } } _requireMsg(angels.length != len, "_quitAngel", "unjoined angel"); } } // File: contracts/JoinPermit.sol pragma solidity 0.6.12; /// @title Staking vault of lpTokens abstract contract JoinPermit is FountainBase { using Counters for Counters.Counter; mapping(address => mapping(address => uint256)) private _timeLimits; mapping(address => Counters.Counter) private _nonces; // solhint-disable-next-line var-name-mixedcase bytes32 private constant _JOIN_PERMIT_TYPEHASH = keccak256( "JoinPermit(address user,address sender,uint256 timeLimit,uint256 nonce,uint256 deadline)" ); /** * @dev Emitted when the time limit of a `sender` for an `user` is set by * a call to {approve}. `timeLimit` is the new time limit. */ event JoinApproval( address indexed user, address indexed sender, uint256 timeLimit ); /// @notice Examine if the time limit is not expired. modifier canJoinFor(address user) { _requireMsg( block.timestamp <= _timeLimits[user][_msgSender()], "general", "join not allowed" ); _; } // Getter /// @notice Return the time limit user approved to the sender. /// @param user The user address. /// @param sender The sender address. /// @return The time limit. function joinTimeLimit(address user, address sender) external view returns (uint256) { return _timeLimits[user][sender]; } /// @notice Approve sender to join before timeLimit. /// @param sender The sender address. /// @param timeLimit The time limit to be approved. function joinApprove(address sender, uint256 timeLimit) external returns (bool) { _joinApprove(_msgSender(), sender, timeLimit); return true; } /// @notice Approve sender to join for user before timeLimit. /// @param user The user address. /// @param sender The sender address. /// @param timeLimit The time limit to be approved. /// @param deadline The permit available deadline. /// @param v Signature v. /// @param r Signature r. /// @param s Signature s. function joinPermit( address user, address sender, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public { // solhint-disable-next-line not-rely-on-time _requireMsg( block.timestamp <= deadline, "joinPermit", "expired deadline" ); bytes32 structHash = keccak256( abi.encode( _JOIN_PERMIT_TYPEHASH, user, sender, timeLimit, _nonces[user].current(), deadline ) ); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); _requireMsg(signer == user, "joinPermit", "invalid signature"); _nonces[user].increment(); _joinApprove(user, sender, timeLimit); } function joinNonces(address user) external view returns (uint256) { return _nonces[user].current(); } /// @notice User may join angel for permitted user. /// @param angel The angel address. /// @param user The user address. function joinAngelFor(IAngel angel, address user) public canJoinFor(user) nonReentrant { _joinAngel(angel, user); } /// @notice User may join angels for permitted user. /// @param angels The angel addresses. /// @param user The user address. function joinAngelsFor(IAngel[] memory angels, address user) public canJoinFor(user) nonReentrant { for (uint256 i = 0; i < angels.length; i++) { _joinAngel(angels[i], user); } } /// @notice Perform joinFor after permit. /// @param angel The angel address. /// @param user The user address. /// @param timeLimit The time limit to be approved. Will set to current /// time if set as 1 (for one time usage) /// @param deadline The permit available deadline. /// @param v Signature v. /// @param r Signature r. /// @param s Signature s. function joinAngelForWithPermit( IAngel angel, address user, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external { joinPermit(user, _msgSender(), timeLimit, deadline, v, r, s); joinAngelFor(angel, user); } /// @notice Perform joinForMany after permit. /// @param angels The angel addresses. /// @param user The user address. /// @param timeLimit The time limit to be approved. Will set to current /// time if set as 1 (for one time usage) /// @param deadline The permit available deadline. /// @param v Signature v. /// @param r Signature r. /// @param s Signature s. function joinAngelsForWithPermit( IAngel[] calldata angels, address user, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external { joinPermit(user, _msgSender(), timeLimit, deadline, v, r, s); joinAngelsFor(angels, user); } function _joinApprove( address user, address sender, uint256 timeLimit ) internal { _requireMsg( user != address(0), "_joinApprove", "approve from the zero address" ); _requireMsg( sender != address(0), "_joinApprove", "approve to the zero address" ); if (timeLimit == 1) timeLimit = block.timestamp; _timeLimits[user][sender] = timeLimit; emit JoinApproval(user, sender, timeLimit); } } // File: contracts/HarvestPermit.sol pragma solidity 0.6.12; /// @title Staking vault of lpTokens abstract contract HarvestPermit is FountainBase { using Counters for Counters.Counter; mapping(address => mapping(address => uint256)) private _timeLimits; mapping(address => Counters.Counter) private _nonces; // solhint-disable-next-line var-name-mixedcase bytes32 private constant _HARVEST_PERMIT_TYPEHASH = keccak256( "HarvestPermit(address owner,address sender,uint256 timeLimit,uint256 nonce,uint256 deadline)" ); /** * @dev Emitted when the time limit of a `sender` for an `owner` is set by * a call to {approve}. `timeLimit` is the new time limit. */ event HarvestApproval( address indexed owner, address indexed sender, uint256 timeLimit ); /// @notice Examine if the time limit is not expired. modifier canHarvestFrom(address owner) { _requireMsg( block.timestamp <= _timeLimits[owner][_msgSender()], "general", "harvest not allowed" ); _; } // Getter /// @notice Return the time limit owner approved to the sender. /// @param owner The owner address. /// @param sender The sender address. /// @return The time limit. function harvestTimeLimit(address owner, address sender) external view returns (uint256) { return _timeLimits[owner][sender]; } /// @notice Approve sender to harvest before timeLimit. /// @param sender The sender address. /// @param timeLimit The time limit to be approved. function harvestApprove(address sender, uint256 timeLimit) external returns (bool) { _harvestApprove(_msgSender(), sender, timeLimit); return true; } /// @notice Approve sender to harvest for owner before timeLimit. /// @param owner The owner address. /// @param sender The sender address. /// @param timeLimit The time limit to be approved. /// @param deadline The permit available deadline. /// @param v Signature v. /// @param r Signature r. /// @param s Signature s. function harvestPermit( address owner, address sender, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public { // solhint-disable-next-line not-rely-on-time _requireMsg( block.timestamp <= deadline, "harvestPermit", "expired deadline" ); bytes32 structHash = keccak256( abi.encode( _HARVEST_PERMIT_TYPEHASH, owner, sender, timeLimit, _nonces[owner].current(), deadline ) ); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); _requireMsg(signer == owner, "harvestPermit", "invalid signature"); _nonces[owner].increment(); _harvestApprove(owner, sender, timeLimit); } function harvestNonces(address owner) external view returns (uint256) { return _nonces[owner].current(); } /// @notice User may harvest from any angel for permitted user. /// @param angel The angel address. /// @param from The owner address. /// @param to The recipient address. function harvestFrom( IAngel angel, address from, address to ) public canHarvestFrom(from) nonReentrant { _harvestAngel(angel, from, to); emit Harvest(from); } /// @notice User may harvest from all the joined angels for permitted user. /// @param from The owner address. /// @param to The recipient address. function harvestAllFrom(address from, address to) public canHarvestFrom(from) nonReentrant { IAngel[] memory angels = joinedAngel(from); for (uint256 i = 0; i < angels.length; i++) { IAngel angel = angels[i]; _harvestAngel(angel, from, to); } emit Harvest(from); } /// @notice Perform harvestFrom after permit. /// @param angel The angel address. /// @param from The owner address. /// @param to The recipient address. /// @param timeLimit The time limit to be approved. /// @param deadline The permit available deadline. /// @param v Signature v. /// @param r Signature r. /// @param s Signature s. function harvestFromWithPermit( IAngel angel, address from, address to, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external { harvestPermit(from, _msgSender(), timeLimit, deadline, v, r, s); harvestFrom(angel, from, to); } /// @notice Perform harvestAllFrom after permit. /// @param from The owner address. /// @param to The recipient address. /// @param timeLimit The time limit to be approved. /// @param deadline The permit available deadline. /// @param v Signature v. /// @param r Signature r. /// @param s Signature s. function harvestAllFromWithPermit( address from, address to, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external { harvestPermit(from, _msgSender(), timeLimit, deadline, v, r, s); harvestAllFrom(from, to); } function _harvestApprove( address owner, address sender, uint256 timeLimit ) internal { _requireMsg( owner != address(0), "_harvestApprove", "approve from the zero address" ); _requireMsg( sender != address(0), "_harvestApprove", "approve to the zero address" ); _timeLimits[owner][sender] = timeLimit; emit HarvestApproval(owner, sender, timeLimit); } } /** * @dev Interface of the ERC3156 FlashLender, as defined in * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. */ interface IERC3156FlashLender { /** * @dev The amount of currency available to be lended. * @param token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan(address token) external view returns (uint256); /** * @dev The fee to be charged for a given loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee(address token, uint256 amount) external view returns (uint256); /** * @dev Initiate a flash loan. * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. * @param token The loan currency. * @param amount The amount of tokens lent. * @param data Arbitrary data structure, intended to contain user-defined parameters. */ function flashLoan( IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data ) external returns (bool); } // File: contracts/interfaces/IFlashLender.sol pragma solidity 0.6.12; interface IFlashLender is IERC3156FlashLender { function flashLoanFeeCollector() external view returns (address); function setFlashLoanFee(uint256) external; } // File: contracts/ERC20FlashLoan.sol pragma solidity 0.6.12; contract ERC20FlashLoan is IFlashLender { using SafeERC20 for IERC20; using SafeMath for uint256; IERC20 public immutable lendingToken; uint256 public flashLoanFee; uint256 public constant FEE_BASE = 1e4; uint256 public constant FEE_BASE_OFFSET = FEE_BASE / 2; bytes32 private constant _RETURN_VALUE = keccak256("ERC3156FlashBorrower.onFlashLoan"); constructor(IERC20 token, uint256 fee) public { require(fee <= FEE_BASE, "fee rate exceeded"); lendingToken = token; flashLoanFee = fee; } /** * @dev The amount of currency available to be lended. * @param token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan(address token) external view override returns (uint256) { return token == address(lendingToken) ? lendingToken.balanceOf(address(this)) : 0; } /** * @dev The fee to be charged for a given loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee(address token, uint256 amount) public view override returns (uint256) { require(token == address(lendingToken), "wrong token"); // The fee will be rounded half up return (amount.mul(flashLoanFee).add(FEE_BASE_OFFSET)).div(FEE_BASE); } /** * @dev Initiate a flash loan. * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. * @param token The loan currency. * @param amount The amount of tokens lent. * @param data Arbitrary data structure, intended to contain user-defined parameters. */ function flashLoan( IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data ) external override returns (bool) { uint256 balance = IERC20(token).balanceOf(address(this)); uint256 fee = flashFee(token, amount); // send token to receiver lendingToken.safeTransfer(address(receiver), amount); require( receiver.onFlashLoan(msg.sender, token, amount, fee, data) == _RETURN_VALUE, "invalid return value" ); uint256 currentAllowance = lendingToken.allowance(address(receiver), address(this)); uint256 totalDebt = amount.add(fee); require( currentAllowance >= totalDebt, "allowance does not allow refund" ); // get token from receiver lendingToken.safeTransferFrom( address(receiver), address(this), totalDebt ); address collector = flashLoanFeeCollector(); if (collector != address(0)) lendingToken.safeTransfer(collector, fee); require( IERC20(token).balanceOf(address(this)) >= balance, "balance decreased" ); return true; } function flashLoanFeeCollector() public view virtual override returns (address) { this; return address(0); } function setFlashLoanFee(uint256 fee) public virtual override { require(fee <= FEE_BASE, "fee rate exceeded"); flashLoanFee = fee; } } // File: contracts/libraries/boringcrypto/BoringBatchable.sol // Audit on 5-Jan-2021 by Keno and BoringCrypto // P1 - P3: OK pragma solidity 0.6.12; // solhint-disable avoid-low-level-calls // T1 - T4: OK contract BaseBoringBatchable { function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (_returnData.length < 68) return "Transaction reverted silently"; assembly { // Slice the sighash. _returnData := add(_returnData, 0x04) } return abi.decode(_returnData, (string)); // All that remains is the revert string } // F3 - F9: OK // F1: External is ok here because this is the batch function, adding it to a batch makes no sense // F2: Calls in the batch may be payable, delegatecall operates in the same context, so each call in the batch has access to msg.value // C1 - C21: OK // C3: The length of the loop is fully under user control, so can't be exploited // C7: Delegatecall is only used on the same contract, so it's safe function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results) { // Interactions successes = new bool[](calls.length); results = new bytes[](calls.length); for (uint256 i = 0; i < calls.length; i++) { (bool success, bytes memory result) = address(this).delegatecall(calls[i]); require(success || !revertOnFail, _getRevertMsg(result)); successes[i] = success; results[i] = result; } } } // T1 - T4: OK contract BoringBatchable is BaseBoringBatchable { // F1 - F9: OK // F6: Parameters can be used front-run the permit and the user's permit will fail (due to nonce or other revert) // if part of a batch this could be used to grief once as the second call would not need the permit // C1 - C21: OK function permitToken( IERC20Permit token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public { // Interactions // X1 - X5 token.permit(from, to, amount, deadline, v, r, s); } } // File: contracts/libraries/boringcrypto/libraries/BoringMath.sol pragma solidity 0.6.12; // a library for performing overflow-safe math, updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math) library BoringMath { function add(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a + b) >= b, "BoringMath: Add Overflow");} function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a - b) <= a, "BoringMath: Underflow");} function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {require(b == 0 || (c = a * b)/b == a, "BoringMath: Mul Overflow");} function to128(uint256 a) internal pure returns (uint128 c) { require(a <= uint128(-1), "BoringMath: uint128 Overflow"); c = uint128(a); } function to64(uint256 a) internal pure returns (uint64 c) { require(a <= uint64(-1), "BoringMath: uint64 Overflow"); c = uint64(a); } function to32(uint256 a) internal pure returns (uint32 c) { require(a <= uint32(-1), "BoringMath: uint32 Overflow"); c = uint32(a); } } library BoringMath128 { function add(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a + b) >= b, "BoringMath: Add Overflow");} function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a - b) <= a, "BoringMath: Underflow");} } library BoringMath64 { function add(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a + b) >= b, "BoringMath: Add Overflow");} function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a - b) <= a, "BoringMath: Underflow");} } library BoringMath32 { function add(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a + b) >= b, "BoringMath: Add Overflow");} function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a - b) <= a, "BoringMath: Underflow");} } // File: @openzeppelin/contracts/math/Math.sol pragma solidity >=0.6.0 <0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // File: contracts/Fountain.sol pragma solidity 0.6.12; /// @title The fountain contract Fountain is HarvestPermit, JoinPermit, ERC20FlashLoan, BoringBatchable { modifier onlyArchangel { _requireMsg( _msgSender() == factory.archangel(), "general", "not from archangel" ); _; } constructor( IERC20 token, string memory name_, string memory symbol_, uint256 flashLoanFee ) public FountainToken(name_, symbol_) FountainBase(token) ERC20FlashLoan(token, flashLoanFee) {} /// @notice Fetch the token from fountain. Can only be called by Archangel. /// Will only fetch the extra part if the token is the staking token. Otherwise /// the entire balance will be fetched. /// @param token The token address. /// @param to The receiver. /// @return The transferred amount. function rescueERC20(IERC20 token, address to) external onlyArchangel returns (uint256) { uint256 amount; if (token == stakingToken) { amount = token.balanceOf(address(this)).sub(totalSupply()); } else { amount = token.balanceOf(address(this)); } token.safeTransfer(to, amount); return amount; } /// @notice Set the fee rate for flash loan. can only be set by Archangel. /// @param fee The fee rate. function setFlashLoanFee(uint256 fee) public override onlyArchangel { super.setFlashLoanFee(fee); } } // File: contracts/FountainFactory.sol pragma solidity 0.6.12; /// @title The factory of Fountain contract FountainFactory is ErrorMsg { IArchangel public immutable archangel; /// @dev Token and Fountain should be 1-1 and only mapping(IERC20 => Fountain) private _fountains; mapping(Fountain => IERC20) private _stakings; event Created(address to); constructor() public { archangel = IArchangel(msg.sender); } // Getters /// @notice Check if fountain is valid. /// @param fountain The fountain to be verified. /// @return Is valid or not. function isValid(Fountain fountain) external view returns (bool) { return (address(_stakings[fountain]) != address(0)); } /// @notice Get the fountain of given token. /// @param token The token address. /// @return The fountain. function fountainOf(IERC20 token) external view returns (Fountain) { return _fountains[token]; } /// @notice Create Fountain for token. Notice that fountain with tokens that /// has floating amount (including Inflationary/Deflationary tokens, Interest /// tokens, Rebase tokens), might leads to error according to the design /// policy of fountain. /// @param token The token address to be created. /// @return The created fountain. function create(ERC20 token) external returns (Fountain) { _requireMsg( address(_fountains[token]) == address(0), "create", "fountain existed" ); string memory name = _concat("Fountain ", token.name()); string memory symbol = _concat("FTN-", token.symbol()); Fountain fountain = new Fountain(token, name, symbol, archangel.defaultFlashLoanFee()); _fountains[token] = fountain; _stakings[fountain] = token; emit Created(address(fountain)); } function _concat(string memory a, string memory b) internal pure returns (string memory) { return string(abi.encodePacked(a, b)); } } // File: contracts/interfaces/IFountain.sol pragma solidity 0.6.12; interface IFountain is IERC20, IERC20Permit { // Getter function stakingToken() external view returns (address); function factory() external view returns (address); function archangel() external view returns (address); function joinedAngel(address user) external view returns (address[] memory); function angelInfo(address angel) external view returns (uint256, uint256); function joinTimeLimit(address owner, address sender) external view returns (uint256); function joinNonces(address owner) external view returns (uint256); function harvestTimeLimit(address owner, address sender) external view returns (uint256); function harvestNonces(address owner) external view returns (uint256); function setPoolId(uint256 pid) external; function deposit(uint256 amount) external; function depositTo(uint256 amount, address to) external; function withdraw(uint256 amount) external; function withdrawTo(uint256 amount, address to) external; function harvest(address angel) external; function harvestAll() external; function emergencyWithdraw() external; function joinAngel(address angel) external; function joinAngels(address[] calldata angels) external; function quitAngel(address angel) external; function rageQuitAngel(address angel) external; function quitAllAngel() external; function transferFromWithPermit(address owner, address recipient, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external returns (bool); function joinApprove(address sender, uint256 timeLimit) external returns (bool); function joinPermit( address user, address sender, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function joinAngelFor(address angel, address user) external; function joinAngelsFor(address[] calldata angels, address user) external; function joinAngelForWithPermit( address angel, address user, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function joinAngelsForWithPermit( address[] calldata angels, address user, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function harvestApprove(address sender, uint256 timeLimit) external returns (bool); function harvestPermit( address owner, address sender, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function harvestFrom(address angel, address from, address to) external; function harvestAllFrom(address from, address to) external; function harvestFromWithPermit( address angel, address from, address to, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function harvestAllFromWithPermit( address from, address to, uint256 timeLimit, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; } // File: contracts/interfaces/IAngelFactory.sol pragma solidity 0.6.12; interface IAngelFactory { // Getters function archangel() external view returns (address); function isValid(address angel) external view returns (bool); function rewardOf(address angel) external view returns (address); function create(address rewardToken) external returns (address); } // File: contracts/interfaces/IMasterChef.sol pragma solidity 0.6.12; interface IMasterChef { using BoringERC20 for IERC20; struct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. } struct PoolInfo { IERC20 lpToken; // Address of LP token contract. uint256 allocPoint; // How many allocation points assigned to this pool. SUSHI to distribute per block. uint256 lastRewardBlock; // Last block number that SUSHI distribution occurs. uint256 accSushiPerShare; // Accumulated SUSHI per share, times 1e12. See below. } function poolInfo(uint256 pid) external view returns (IMasterChef.PoolInfo memory); function totalAllocPoint() external view returns (uint256); function deposit(uint256 _pid, uint256 _amount) external; } // File: contracts/interfaces/IRewarder.sol pragma solidity 0.6.12; interface IRewarder { using BoringERC20 for IERC20; function onGraceReward( uint256 pid, address user, address recipient, uint256 graceAmount, uint256 newLpAmount ) external; function pendingTokens( uint256 pid, address user, uint256 graceAmount ) external view returns (IERC20[] memory, uint256[] memory); } // File: contracts/libraries/SignedSafeMath.sol pragma solidity >=0.6.0 <0.8.0; /** * @title SignedSafeMath * @dev Signed math operations with safety checks that revert on error. */ library SignedSafeMath { int256 private constant _INT256_MIN = -2**255; /** * @dev Returns the multiplication of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(int256 a, int256 b) internal pure returns (int256) { // 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; } require( !(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow" ); int256 c = a * b; require(c / a == b, "SignedSafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two signed 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(int256 a, int256 b) internal pure returns (int256) { require(b != 0, "SignedSafeMath: division by zero"); require( !(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow" ); int256 c = a / b; return c; } /** * @dev Returns the subtraction of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { int256 c = a - b; require( (b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow" ); return c; } /** * @dev Returns the addition of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { int256 c = a + b; require( (b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow" ); return c; } /** * @dev Returns the unsigned integer of the positive signed integer, * reverting on negative integer. * Not from openzeppelin/contracts * * Requirements: * * - Integer cannot be negative. */ function toUInt256(int256 a) internal pure returns (uint256) { require(a >= 0, "Integer < 0"); return uint256(a); } } // File: contracts/libraries/boringcrypto/BoringOwnable.sol // Audit on 5-Jan-2021 by Keno and BoringCrypto // P1 - P3: OK pragma solidity 0.6.12; // Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol // Edited by BoringCrypto // T1 - T4: OK contract BoringOwnableData { // V1 - V5: OK address public owner; // V1 - V5: OK address public pendingOwner; } // T1 - T4: OK contract BoringOwnable is BoringOwnableData { // E1: OK event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor () public { owner = msg.sender; emit OwnershipTransferred(address(0), msg.sender); } // F1 - F9: OK // C1 - C21: OK function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner { if (direct) { // Checks require(newOwner != address(0) || renounce, "Ownable: zero address"); // Effects emit OwnershipTransferred(owner, newOwner); owner = newOwner; pendingOwner = address(0); } else { // Effects pendingOwner = newOwner; } } // F1 - F9: OK // C1 - C21: OK function claimOwnership() public { address _pendingOwner = pendingOwner; // Checks require(msg.sender == _pendingOwner, "Ownable: caller != pending owner"); // Effects emit OwnershipTransferred(owner, _pendingOwner); owner = _pendingOwner; pendingOwner = address(0); } // M1 - M5: OK // C1 - C21: OK modifier onlyOwner() { require(msg.sender == owner, "Ownable: caller is not the owner"); _; } } // File: contracts/libraries/boringcrypto/libraries/BoringERC20.sol pragma solidity 0.6.12; library BoringERC20 { function safeSymbol(IERC20 token) internal view returns (string memory) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41)); return success && data.length > 0 ? abi.decode(data, (string)) : "???"; } function safeName(IERC20 token) internal view returns (string memory) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03)); return success && data.length > 0 ? abi.decode(data, (string)) : "???"; } function safeDecimals(IERC20 token) internal view returns (uint8) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567)); return success && data.length == 32 ? abi.decode(data, (uint8)) : 18; } function safeTransfer( IERC20 token, address to, uint256 amount ) internal { (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, amount)); require( success && (data.length == 0 || abi.decode(data, (bool))), "BoringERC20: Transfer failed" ); } function safeTransferFrom( IERC20 token, address from, address to, uint256 amount ) internal { (bool success, bytes memory data) = address(token).call( abi.encodeWithSelector(0x23b872dd, from, to, amount) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "BoringERC20: TransferFrom failed" ); } } // File: contracts/AngelBase.sol pragma solidity 0.6.12; /// @notice Angel is a forked version of MiniChefV2 from SushiSwap with /// minimal modifications to interact with fountain in Trevi. The staking /// tokens are managed in fountain instead of here. Migrate related functions /// withdrawAndHarvest are removed. contract AngelBase is BoringOwnable, BoringBatchable, ErrorMsg { using BoringMath for uint256; using BoringMath128 for uint128; using BoringERC20 for IERC20; using SignedSafeMath for int256; /// @notice Info of each MCV2 user. /// `amount` LP token amount the user has provided. /// `rewardDebt` The amount of GRACE entitled to the user. struct UserInfo { uint256 amount; int256 rewardDebt; } /// @notice Info of each MCV2 pool. /// `allocPoint` The amount of allocation points assigned to the pool. /// Also known as the amount of GRACE to distribute per block. struct PoolInfo { uint128 accGracePerShare; uint64 lastRewardTime; uint64 allocPoint; } /// @notice Address of GRACE contract. IERC20 public immutable GRACE; // @notice The migrator contract. It has a lot of power. Can only be set through governance (owner). /// @notice Info of each MCV2 pool. PoolInfo[] public poolInfo; /// @notice Address of the LP token for each MCV2 pool. IERC20[] public lpToken; /// @notice Address of each `IRewarder` contract in MCV2. IRewarder[] public rewarder; /// @notice Info of each user that stakes LP tokens. mapping(uint256 => mapping(address => UserInfo)) public userInfo; /// @dev Total allocation points. Must be the sum of all allocation points in all pools. uint256 public totalAllocPoint; uint256 public gracePerSecond; uint256 private constant ACC_GRACE_PRECISION = 1e12; ////////////////////////// New IArchangel public immutable archangel; IAngelFactory public immutable factory; uint256 public endTime; uint256 private _skipOwnerMassUpdateUntil; event Deposit( address indexed user, uint256 indexed pid, uint256 amount, address indexed to ); event Withdraw( address indexed user, uint256 indexed pid, uint256 amount, address indexed to ); event EmergencyWithdraw( address indexed user, uint256 indexed pid, uint256 amount, address indexed to ); event Harvest(address indexed user, uint256 indexed pid, uint256 amount); event LogPoolAddition( uint256 indexed pid, uint256 allocPoint, IERC20 indexed lpToken, IRewarder indexed rewarder ); event LogSetPool( uint256 indexed pid, uint256 allocPoint, IRewarder indexed rewarder, bool overwrite ); event LogUpdatePool( uint256 indexed pid, uint64 lastRewardTime, uint256 lpSupply, uint256 accGracePerShare ); event LogGracePerSecondAndEndTime(uint256 gracePerSecond, uint256 endTime); event RewarderExecFail(address rewarder, uint256 pid, address user); modifier onlyFountain(uint256 pid) { _requireMsg( msg.sender == archangel.getFountain(address(lpToken[pid])), "General", "not called by correct fountain" ); _; } modifier ownerMassUpdate() { if (block.timestamp > _skipOwnerMassUpdateUntil) massUpdatePoolsNonZero(); _; _skipOwnerMassUpdateUntil = block.timestamp; } /// @param _grace The GRACE token contract address. constructor(IERC20 _grace) public { GRACE = _grace; IAngelFactory _f = IAngelFactory(msg.sender); factory = _f; archangel = IArchangel(_f.archangel()); } /// @notice Returns the number of MCV2 pools. function poolLength() public view returns (uint256 pools) { pools = poolInfo.length; } function lastTimeRewardApplicable() public view returns (uint256) { return Math.min(block.timestamp, endTime); } /// @notice Add a new LP to the pool. Can only be called by the owner. /// DO NOT add the same LP token more than once. Rewards will be messed up if you do. /// @param allocPoint AP of the new pool. /// @param _lpToken Address of the LP ERC-20 token. /// @param _rewarder Address of the rewarder delegate. function add( uint256 allocPoint, IERC20 _lpToken, IRewarder _rewarder ) external onlyOwner ownerMassUpdate { uint256 pid = lpToken.length; totalAllocPoint = totalAllocPoint.add(allocPoint); lpToken.push(_lpToken); rewarder.push(_rewarder); poolInfo.push( PoolInfo({ allocPoint: allocPoint.to64(), lastRewardTime: block.timestamp.to64(), accGracePerShare: 0 }) ); emit LogPoolAddition(pid, allocPoint, _lpToken, _rewarder); ////////////////////////// New // Update pid in fountain IFountain fountain = IFountain(archangel.getFountain(address(_lpToken))); fountain.setPoolId(pid); } /// @notice Update the given pool's GRACE allocation point and `IRewarder` contract. Can only be called by the owner. /// @param _pid The index of the pool. See `poolInfo`. /// @param _allocPoint New AP of the pool. /// @param _rewarder Address of the rewarder delegate. /// @param overwrite True if _rewarder should be `set`. Otherwise `_rewarder` is ignored. function set( uint256 _pid, uint256 _allocPoint, IRewarder _rewarder, bool overwrite ) external onlyOwner ownerMassUpdate { updatePool(_pid); totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add( _allocPoint ); poolInfo[_pid].allocPoint = _allocPoint.to64(); if (overwrite) { rewarder[_pid] = _rewarder; } emit LogSetPool( _pid, _allocPoint, overwrite ? _rewarder : rewarder[_pid], overwrite ); } /// @notice Add extra amount of GRACE to be distributed and the end time. Can only be called by the owner. /// @param _amount The extra amount of GRACE to be distributed. /// @param _endTime UNIX timestamp that indicates the end of the calculating period. function addGraceReward(uint256 _amount, uint256 _endTime) external onlyOwner ownerMassUpdate { _requireMsg( _amount > 0, "addGraceReward", "grace amount should be greater than 0" ); _requireMsg( _endTime > block.timestamp, "addGraceReward", "end time should be in the future" ); uint256 duration = _endTime.sub(block.timestamp); uint256 newGracePerSecond; if (block.timestamp >= endTime) { newGracePerSecond = _amount / duration; } else { uint256 remaining = endTime.sub(block.timestamp); uint256 leftover = remaining.mul(gracePerSecond); newGracePerSecond = leftover.add(_amount) / duration; } _requireMsg( newGracePerSecond <= type(uint128).max, "addGraceReward", "new grace per second exceeds uint128" ); gracePerSecond = newGracePerSecond; endTime = _endTime; emit LogGracePerSecondAndEndTime(gracePerSecond, endTime); GRACE.safeTransferFrom(msg.sender, address(this), _amount); } /// @notice Set the grace per second to be distributed. Can only be called by the owner. /// @param _gracePerSecond The amount of Grace to be distributed per second. function setGracePerSecond(uint256 _gracePerSecond, uint256 _endTime) external onlyOwner ownerMassUpdate { _requireMsg( _gracePerSecond <= type(uint128).max, "setGracePerSecond", "new grace per second exceeds uint128" ); _requireMsg( _endTime > block.timestamp, "setGracePerSecond", "end time should be in the future" ); uint256 duration = _endTime.sub(block.timestamp); uint256 rewardNeeded = _gracePerSecond.mul(duration); uint256 shortage; if (block.timestamp >= endTime) { shortage = rewardNeeded; } else { uint256 remaining = endTime.sub(block.timestamp); uint256 leftover = remaining.mul(gracePerSecond); if (rewardNeeded > leftover) shortage = rewardNeeded.sub(leftover); } gracePerSecond = _gracePerSecond; endTime = _endTime; emit LogGracePerSecondAndEndTime(gracePerSecond, endTime); if (shortage > 0) GRACE.safeTransferFrom(msg.sender, address(this), shortage); } /// @notice View function to see pending GRACE on frontend. /// @param _pid The index of the pool. See `poolInfo`. /// @param _user Address of user. /// @return pending GRACE reward for a given user. function pendingGrace(uint256 _pid, address _user) external view returns (uint256 pending) { PoolInfo memory pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][_user]; uint256 accGracePerShare = pool.accGracePerShare; ////////////////////////// New // uint256 lpSupply = lpToken[_pid].balanceOf(address(this)); // Need to get the lpSupply from fountain IFountain fountain = IFountain(archangel.getFountain(address(lpToken[_pid]))); (, uint256 lpSupply) = fountain.angelInfo(address(this)); uint256 _lastTimeRewardApplicable = lastTimeRewardApplicable(); if ( lpSupply != 0 && pool.allocPoint > 0 && _lastTimeRewardApplicable > pool.lastRewardTime ) { uint256 time = _lastTimeRewardApplicable.sub(pool.lastRewardTime); uint256 graceReward = time.mul(gracePerSecond).mul(pool.allocPoint) / totalAllocPoint; accGracePerShare = accGracePerShare.add( graceReward.mul(ACC_GRACE_PRECISION) / lpSupply ); } pending = int256( user.amount.mul(accGracePerShare) / ACC_GRACE_PRECISION ) .sub(user.rewardDebt) .toUInt256(); } /// @notice Update reward variables for all pools with non-zero allocPoint. /// Be careful of gas spending! function massUpdatePoolsNonZero() public { uint256 len = poolLength(); for (uint256 i = 0; i < len; ++i) { if (poolInfo[i].allocPoint > 0) updatePool(i); } } /// @notice Update reward variables for all pools. Be careful of gas spending! /// @param pids Pool IDs of all to be updated. Make sure to update all active pools. function massUpdatePools(uint256[] memory pids) public { uint256 len = pids.length; for (uint256 i = 0; i < len; ++i) { updatePool(pids[i]); } } /// @notice Update reward variables for all pools and set the expire time for skipping `massUpdatePoolsNonZero()`. /// Be careful of gas spending! Can only be called by the owner. /// DO NOT use this function until `massUpdatePoolsNonZero()` reverts because of out of gas. /// If that is the case, try to update all pools first and then call onlyOwner function to set a correct state. /// @param pids Pool IDs of all to be updated. Make sure to update all active pools. function massUpdatePoolsAndSet(uint256[] calldata pids) external onlyOwner { massUpdatePools(pids); // Leave an hour for owner to be able to skip `massUpdatePoolsNonZero()` _skipOwnerMassUpdateUntil = block.timestamp.add(3600); } /// @notice Update reward variables of the given pool. /// @param pid The index of the pool. See `poolInfo`. /// @return pool Returns the pool that was updated. function updatePool(uint256 pid) public returns (PoolInfo memory pool) { pool = poolInfo[pid]; if (block.timestamp > pool.lastRewardTime) { ////////////////////////// New // uint256 lpSupply = lpToken[pid].balanceOf(address(this)); // Need to get the lpSupply from fountain IFountain fountain = IFountain(archangel.getFountain(address(lpToken[pid]))); (, uint256 lpSupply) = fountain.angelInfo(address(this)); uint256 _lastTimeRewardApplicable = lastTimeRewardApplicable(); // Only accumulate reward before end time if ( lpSupply > 0 && pool.allocPoint > 0 && _lastTimeRewardApplicable > pool.lastRewardTime ) { uint256 time = _lastTimeRewardApplicable.sub(pool.lastRewardTime); uint256 graceReward = time.mul(gracePerSecond).mul(pool.allocPoint) / totalAllocPoint; pool.accGracePerShare = pool.accGracePerShare.add( (graceReward.mul(ACC_GRACE_PRECISION) / lpSupply).to128() ); } pool.lastRewardTime = block.timestamp.to64(); poolInfo[pid] = pool; emit LogUpdatePool( pid, pool.lastRewardTime, lpSupply, pool.accGracePerShare ); } } /// @notice Deposit LP tokens to MCV2 for GRACE allocation. /// @param pid The index of the pool. See `poolInfo`. /// @param amount LP token amount to deposit. /// @param to The receiver of `amount` deposit benefit. function deposit( uint256 pid, uint256 amount, address to ) external onlyFountain(pid) { PoolInfo memory pool = updatePool(pid); UserInfo storage user = userInfo[pid][to]; // Effects user.amount = user.amount.add(amount); user.rewardDebt = user.rewardDebt.add( int256(amount.mul(pool.accGracePerShare) / ACC_GRACE_PRECISION) ); // Interactions IRewarder _rewarder = rewarder[pid]; if (address(_rewarder) != address(0)) { _rewarder.onGraceReward(pid, to, to, 0, user.amount); } ////////////////////////// New // Handle in fountain // lpToken[pid].safeTransferFrom(msg.sender, address(this), amount); // emit Deposit(msg.sender, pid, amount, to); emit Deposit(to, pid, amount, to); } /// @notice Withdraw LP tokens from MCV2. /// @param pid The index of the pool. See `poolInfo`. /// @param amount LP token amount to withdraw. /// @param to Receiver of the LP tokens. function withdraw( uint256 pid, uint256 amount, address to ) external onlyFountain(pid) { PoolInfo memory pool = updatePool(pid); ////////////////////////// New // Delegate by fountain // UserInfo storage user = userInfo[pid][msg.sender]; UserInfo storage user = userInfo[pid][to]; // Effects user.rewardDebt = user.rewardDebt.sub( int256(amount.mul(pool.accGracePerShare) / ACC_GRACE_PRECISION) ); user.amount = user.amount.sub(amount); // Interactions IRewarder _rewarder = rewarder[pid]; if (address(_rewarder) != address(0)) { ////////////////////////// New // Delegate by fountain // _rewarder.onGraceReward(pid, msg.sender, to, 0, user.amount); _rewarder.onGraceReward(pid, to, to, 0, user.amount); } ////////////////////////// New // Handle in fountain // lpToken[pid].safeTransfer(to, amount); // emit Withdraw(msg.sender, pid, amount, to); emit Withdraw(to, pid, amount, to); } /// @notice Harvest proceeds for transaction sender to `to`. /// @param pid The index of the pool. See `poolInfo`. /// @param to Receiver of GRACE rewards. function harvest( uint256 pid, address from, address to ) external onlyFountain(pid) { PoolInfo memory pool = updatePool(pid); ////////////////////////// New // Delegate by fountain // UserInfo storage user = userInfo[pid][msg.sender]; UserInfo storage user = userInfo[pid][from]; int256 accumulatedGrace = int256( user.amount.mul(pool.accGracePerShare) / ACC_GRACE_PRECISION ); uint256 _pendingGrace = accumulatedGrace.sub(user.rewardDebt).toUInt256(); // Effects user.rewardDebt = accumulatedGrace; // Interactions if (_pendingGrace != 0) { GRACE.safeTransfer(to, _pendingGrace); } IRewarder _rewarder = rewarder[pid]; if (address(_rewarder) != address(0)) { _rewarder.onGraceReward( pid, ////////////////////////// New // Delegate by fountain // msg.sender, from, to, _pendingGrace, user.amount ); } ////////////////////////// New // emit Harvest(msg.sender, pid, _pendingGrace); emit Harvest(from, pid, _pendingGrace); } /// @notice Withdraw without caring about rewards. EMERGENCY ONLY. /// @param pid The index of the pool. See `poolInfo`. /// @param to Receiver of the LP tokens. function emergencyWithdraw(uint256 pid, address to) external onlyFountain(pid) { ////////////////////////// New // Delegate by fountain // UserInfo storage user = userInfo[pid][msg.sender]; UserInfo storage user = userInfo[pid][to]; uint256 amount = user.amount; user.amount = 0; user.rewardDebt = 0; IRewarder _rewarder = rewarder[pid]; if (address(_rewarder) != address(0)) { ////////////////////////// New // Delegate by fountain // _rewarder.onGraceReward(pid, msg.sender, to, 0, 0); // Execution of emergencyWithdraw should never fail. Considering // the possibility of failure caused by rewarder execution, use // try/catch on rewarder execution with limited gas try _rewarder.onGraceReward{gas: 1000000}(pid, to, to, 0, 0) {} catch { emit RewarderExecFail(address(_rewarder), pid, to); } } // Note: transfer can fail or succeed if `amount` is zero. ////////////////////////// New // Handle in fountain // lpToken[pid].safeTransfer(to, amount); // emit EmergencyWithdraw(msg.sender, pid, amount, to); emit EmergencyWithdraw(to, pid, amount, to); } /// @notice Fetch the token from angel. Can only be called by owner. /// @param token The token address. /// @param amount The amount of token to be rescued. Replace by current balance if uint256(-1). /// @param to The receiver. /// @return The transferred amount. function rescueERC20( IERC20 token, uint256 amount, address to ) external onlyOwner returns (uint256) { if (amount == type(uint256).max) { amount = token.balanceOf(address(this)); } token.safeTransfer(to, amount); return amount; } } // File: contracts/Angel.sol pragma solidity 0.6.12; /// @title Manage the rewards and configuration. contract Angel is AngelBase, ERC20FlashLoan { modifier onlyArchangel() { _requireMsg( msg.sender == address(archangel), "general", "not from archangel" ); _; } constructor(IERC20 token, uint256 flashLoanFee) public AngelBase(token) ERC20FlashLoan(token, flashLoanFee) {} /// @notice Set the fee rate for flash loan. can only be set by Archangel. /// @param fee The fee rate. function setFlashLoanFee(uint256 fee) public override onlyArchangel { super.setFlashLoanFee(fee); } /// @notice Set the fee collector. Fee are transferred to Archangel after /// flash loan execution. function flashLoanFeeCollector() public view override returns (address) { return address(archangel); } } // File: contracts/AngelFactory.sol pragma solidity 0.6.12; /// @title The factory of angel. contract AngelFactory is ErrorMsg { using BoringERC20 for IERC20; using BoringMath for uint256; IArchangel public immutable archangel; mapping(Angel => IERC20) private _rewards; event Created(address to); constructor() public { archangel = IArchangel(msg.sender); } // Getters /// @notice Check if angel is valid. /// @param angel The angel to be verified. /// @return Is valid or not. function isValid(Angel angel) external view returns (bool) { return (address(_rewards[angel]) != address(0)); } /// @notice Get the reward token of angel. /// @param angel The angel address. /// @return The reward token address. function rewardOf(Angel angel) external view returns (IERC20) { return _rewards[angel]; } /// @notice Create the angel of given token as reward. Multiple angels for /// the same token is possible. Notice that angel with tokens that has /// floating amount (including Inflationary/Deflationary tokens, Interest /// tokens, Rebase tokens), might leads to error according to the design /// policy of angel. function create(IERC20 reward) external returns (Angel) { _requireMsg( address(reward) != address(0), "create", "reward is zero address" ); Angel newAngel = new Angel(reward, archangel.defaultFlashLoanFee()); _rewards[newAngel] = reward; newAngel.transferOwnership(msg.sender, true, false); emit Created(address(newAngel)); return newAngel; } } // File: contracts/libraries/interfaces/IERC3156.sol pragma solidity 0.6.12; /** * @dev Interface of the ERC3156 FlashBorrower, as defined in * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. * * _Available since v4.1._ */ interface IERC3156FlashBorrower { /** * @dev Receive a flash loan. * @param initiator The initiator of the loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @param fee The additional amount of tokens to repay. * @param data Arbitrary data structure, intended to contain user-defined parameters. * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" */ function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); } // File: contracts/interfaces/IArchangel.sol pragma solidity 0.6.12; interface IArchangel { // Getters function angelFactory() external view returns (address); function fountainFactory() external view returns (address); function defaultFlashLoanFee() external view returns (uint256); function getFountain(address token) external view returns (address); function rescueERC20(address token, address from) external returns (uint256); function setDefaultFlashLoanFee(uint256 fee) external; } // File: contracts/Archangel.sol pragma solidity 0.6.12; /// @title Staking system manager contract Archangel is Ownable, ErrorMsg { using SafeERC20 for IERC20; AngelFactory public immutable angelFactory; FountainFactory public immutable fountainFactory; uint256 public defaultFlashLoanFee; uint256 public constant FEE_BASE = 1e4; constructor(uint256 _defaultFlashLoanFee) public { defaultFlashLoanFee = _defaultFlashLoanFee; angelFactory = new AngelFactory(); fountainFactory = new FountainFactory(); } // Getters /// @notice Get the fountain for given token. /// @param token The token to be queried. /// @return Fountain address. function getFountain(IERC20 token) external view returns (Fountain) { return fountainFactory.fountainOf(token); } /// @notice Fetch the token from fountain or archangel itself. Can /// only be called from owner. /// @param token The token to be fetched. /// @param from The fountain to be fetched. /// @return The token amount being fetched. function rescueERC20(IERC20 token, Fountain from) external onlyOwner returns (uint256) { if (fountainFactory.isValid(from)) { return from.rescueERC20(token, _msgSender()); } else { uint256 amount = token.balanceOf(address(this)); token.safeTransfer(_msgSender(), amount); return amount; } } /// @notice Set the default fee rate for flash loan. The default fee /// rate will be applied when fountain or angel is being created. Can /// only be set by owner. function setDefaultFlashLoanFee(uint256 fee) external onlyOwner { _requireMsg( fee <= FEE_BASE, "setDefaultFlashLoanFee", "fee rate exceeded" ); defaultFlashLoanFee = fee; } /// @notice Set the flash loan fee rate of angel or fountain. Can only /// be set by owner. /// @param lender The address of angel of fountain. /// @param fee The fee rate to be applied. function setFlashLoanFee(address lender, uint256 fee) external onlyOwner { IFlashLender(lender).setFlashLoanFee(fee); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint256","name":"flashLoanFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"timeLimit","type":"uint256"}],"name":"HarvestApproval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"angel","type":"address"}],"name":"Join","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"timeLimit","type":"uint256"}],"name":"JoinApproval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"angel","type":"address"}],"name":"Quit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"angel","type":"address"}],"name":"RageQuit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BASE_OFFSET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"}],"name":"angelInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"calls","type":"bytes[]"},{"internalType":"bool","name":"revertOnFail","type":"bool"}],"name":"batch","outputs":[{"internalType":"bool[]","name":"successes","type":"bool[]"},{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"depositTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IFountainFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"flashFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC3156FlashBorrower","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flashLoanFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flashLoanFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"}],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"harvestAllFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"harvestAllFromWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"}],"name":"harvestApprove","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"harvestFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"harvestFromWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"harvestNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"harvestPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"sender","type":"address"}],"name":"harvestTimeLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"}],"name":"joinAngel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"joinAngelFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"joinAngelForWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel[]","name":"angels","type":"address[]"}],"name":"joinAngels","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel[]","name":"angels","type":"address[]"},{"internalType":"address","name":"user","type":"address"}],"name":"joinAngelsFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel[]","name":"angels","type":"address[]"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"joinAngelsForWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"}],"name":"joinApprove","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"joinNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"joinPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sender","type":"address"}],"name":"joinTimeLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"joinedAngel","outputs":[{"internalType":"contract IAngel[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lendingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"maxFlashLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Permit","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permitToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"quitAllAngel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"}],"name":"quitAngel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAngel","name":"angel","type":"address"}],"name":"rageQuitAngel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueERC20","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setFlashLoanFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"setPoolId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"transferFromWithPermit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101a06040527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610120523480156200003757600080fd5b5060405162005820380380620058208339810160408190526200005a916200031d565b83818585858180604051806040016040528060018152602001603160f81b8152508484816003908051906020019062000095929190620001da565b508051620000ab906004906020840190620001da565b50506005805460ff1916601217905550815160208084019190912082519183019190912060c082905260e08190527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6200010462000191565b60a0526200011481848462000195565b60805261010052505060016007555050506001600160601b0319606093841b1661014052505033901b610160526127108111156200016f5760405162461bcd60e51b81526004016200016690620003d7565b60405180910390fd5b60609190911b6001600160601b03191661018052600e55506200040292505050565b4690565b6000838383620001a462000191565b30604051602001620001bb959493929190620003ab565b6040516020818303038152906040528051906020012090509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200021d57805160ff19168380011785556200024d565b828001600101855582156200024d579182015b828111156200024d57825182559160200191906001019062000230565b506200025b9291506200025f565b5090565b5b808211156200025b576000815560010162000260565b600082601f83011262000287578081fd5b81516001600160401b03808211156200029e578283fd5b6040516020601f8401601f1916820181018381118382101715620002c0578586fd5b80604052508194508382528681858801011115620002dd57600080fd5b600092505b83831015620003015785830181015182840182015291820191620002e2565b83831115620003135760008185840101525b5050505092915050565b6000806000806080858703121562000333578384fd5b84516001600160a01b03811681146200034a578485fd5b60208601519094506001600160401b038082111562000367578485fd5b620003758883890162000276565b945060408701519150808211156200038b578384fd5b506200039a8782880162000276565b606096909601519497939650505050565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b602080825260119082015270199959481c985d1948195e18d959591959607a1b604082015260600190565b60805160a05160c05160e05161010051610120516101405160601c6101605160601c6101805160601c615358620004c8600039806111d652806112de52806113a252806113f252806118c9528061191e528061214e528061271e5250806114cd528061239c528061287b5250806115cb5280611a9c52806121ef52806130ff52806131a852806131ea52806137af5280613860528061388e5250806126155250806133e25250806134245250806134035250806133895250806133b952506153586000f3fe6080604052600436106103975760003560e01c80637ecebe00116101dc578063c86283c811610102578063dd62ed3e116100a0578063ecefc7051161006f578063ecefc70514610a75578063ed31cdfa14610a8a578063eda9bf3a14610aaa578063f44b7cd514610aca57610397565b8063dd62ed3e14610a00578063e5cd6a1514610a20578063e92d0d5d14610a35578063ea775b8c14610a5557610397565b8063d6e03cd4116100dc578063d6e03cd414610996578063d977a196146109b6578063d9d98ce4146109cb578063db2e21bc146109eb57610397565b8063c86283c814610935578063d2423b5114610955578063d505accf1461097657610397565b8063a2e655b31161017a578063aaaca55811610149578063aaaca558146108cb578063ac78012c146108e0578063b6b55f2514610900578063c45a01551461092057610397565b8063a2e655b31461083d578063a457c2d71461086b578063a69f0ee41461088b578063a9059cbb146108ab57610397565b80638f94f747116101b65780638f94f747146107c857806395d89b41146107e85780639b23bf6c146107fd5780639c4be7f41461081d57610397565b80637ecebe0014610766578063864da28a146107865780638ed955b9146107b357610397565b80634847cdc8116102c1578063707a11f71161025f57806372f702f31161022e57806372f702f3146106e45780637a360b3e146107065780637c516e94146107265780637d4f20d81461074657610397565b8063707a11f71461066457806370a082311461068457806370aff70f146106a457806370fb0430146106c457610397565b80635cffe9de1161029b5780635cffe9de146105e45780635d799f87146106045780635e9e2ec914610624578063613255ab1461064457610397565b80634847cdc81461058f578063503e9b72146105a4578063576491df146105c457610397565b8063200fe1d911610339578063313ce56711610308578063313ce567146105185780633644e5151461053a578063395093511461054f5780633e8341d21461056f57610397565b8063200fe1d91461049857806323b872dd146104b857806327e5af88146104d85780632e1a7d4d146104f857610397565b80630d48a7b2116103755780630d48a7b2146104165780630e5c011e1461044357806313f89aa81461046357806318160ddd1461048357610397565b806306fdde031461039c5780630743faf1146103c7578063095ea7b3146103e9575b600080fd5b3480156103a857600080fd5b506103b1610adf565b6040516103be9190614c01565b60405180910390f35b3480156103d357600080fd5b506103e76103e23660046142da565b610b76565b005b3480156103f557600080fd5b506104096104043660046143f8565b610c09565b6040516103be9190614b6f565b34801561042257600080fd5b50610436610431366004614312565b610c27565b6040516103be9190614b7a565b34801561044f57600080fd5b506103e761045e3660046142da565b610c52565b34801561046f57600080fd5b506103e761047e3660046142da565b610cd8565b34801561048f57600080fd5b50610436610d11565b3480156104a457600080fd5b506103e76104b336600461463c565b610d17565b3480156104c457600080fd5b506104096104d336600461434a565b610e25565b3480156104e457600080fd5b506103e76104f3366004614543565b610e67565b34801561050457600080fd5b506103e7610513366004614897565b610f64565b34801561052457600080fd5b5061052d611014565b6040516103be91906151a4565b34801561054657600080fd5b5061043661101d565b34801561055b57600080fd5b5061040961056a3660046143f8565b61102c565b34801561057b57600080fd5b506103e761058a36600461462a565b61107f565b34801561059b57600080fd5b506104366110e2565b3480156105b057600080fd5b506103e76105bf3660046146fc565b6110e8565b3480156105d057600080fd5b506104366105df3660046142da565b611111565b3480156105f057600080fd5b506104096105ff366004614771565b61113a565b34801561061057600080fd5b5061043661061f36600461462a565b6114c6565b34801561063057600080fd5b506103e761063f36600461438a565b611731565b34801561065057600080fd5b5061043661065f3660046142da565b6118c5565b34801561067057600080fd5b506103e761067f36600461438a565b6119a3565b34801561069057600080fd5b5061043661069f3660046142da565b6119c3565b3480156106b057600080fd5b506103e76106bf3660046148af565b6119de565b3480156106d057600080fd5b506104366106df3660046142da565b611a79565b3480156106f057600080fd5b506106f9611a9a565b6040516103be9190614983565b34801561071257600080fd5b506103e7610721366004614478565b611abe565b34801561073257600080fd5b506103e761074136600461467b565b611b25565b34801561075257600080fd5b506103e7610761366004614312565b611b99565b34801561077257600080fd5b506104366107813660046142da565b611c6d565b34801561079257600080fd5b506107a66107a13660046142da565b611c8e565b6040516103be9190614b22565b3480156107bf57600080fd5b506103e7611d04565b3480156107d457600080fd5b506104366107e3366004614312565b611daa565b3480156107f457600080fd5b506103b1611dd5565b34801561080957600080fd5b506103e761081836600461438a565b611e36565b34801561082957600080fd5b506104096108383660046143f8565b611fb8565b34801561084957600080fd5b5061085d6108583660046142da565b611fcc565b6040516103be929190615177565b34801561087757600080fd5b506104096108863660046143f8565b612050565b34801561089757600080fd5b506103e76108a63660046144b8565b6120b8565b3480156108b757600080fd5b506104096108c63660046143f8565b61210c565b3480156108d757600080fd5b506106f961214c565b3480156108ec57600080fd5b506103e76108fb366004614897565b612170565b34801561090c57600080fd5b506103e761091b366004614897565b612303565b34801561092c57600080fd5b506106f961239a565b34801561094157600080fd5b506103e76109503660046148af565b6123be565b610968610963366004614423565b612449565b6040516103be929190614a88565b34801561098257600080fd5b506103e761099136600461438a565b6125db565b3480156109a257600080fd5b506104096109b136600461438a565b6126ec565b3480156109c257600080fd5b50610436612714565b3480156109d757600080fd5b506104366109e63660046143f8565b61271a565b3480156109f757600080fd5b506103e761279b565b348015610a0c57600080fd5b50610436610a1b366004614312565b612846565b348015610a2c57600080fd5b506106f9612871565b348015610a4157600080fd5b506103e7610a50366004614897565b612876565b348015610a6157600080fd5b50610409610a703660046143f8565b6128de565b348015610a8157600080fd5b506104366128f2565b348015610a9657600080fd5b506103e7610aa536600461467b565b6128f8565b348015610ab657600080fd5b506103e7610ac53660046142da565b61290f565b348015610ad657600080fd5b506103e761299c565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b6b5780601f10610b4057610100808354040283529160200191610b6b565b820191906000526020600020905b815481529060010190602001808311610b4e57829003601f168201915b505050505090505b90565b60026007541415610ba25760405162461bcd60e51b8152600401610b99906150d3565b60405180910390fd5b6002600755610bb081612ab1565b7f2342954acf5c3f328802c33175c0833910fab5313fa11c2807406519ea0835f4610bd9612c7d565b82604051610be8929190614997565b60405180910390a1610c01610bfb612c7d565b82612c81565b506001600755565b6000610c1d610c16612c7d565b8484612d8a565b5060015b92915050565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b60026007541415610c755760405162461bcd60e51b8152600401610b99906150d3565b6002600755610c9381610c86612c7d565b610c8e612c7d565b612e3e565b610c9b612c7d565b6001600160a01b03167f188a622567eeca997c3d494fd65f76ca910b90a50a0c44d5e37b2ea5539e027b60405160405180910390a2506001600755565b60026007541415610cfb5760405162461bcd60e51b8152600401610b99906150d3565b6002600755610c0181610d0c612c7d565b612f19565b60025490565b6001600160a01b0382166000908152600a602052604081208391610db39190610d3e612c7d565b6001600160a01b03166001600160a01b03168152602001908152602001600020544211156040518060400160405280600781526020016619d95b995c985b60ca1b815250604051806040016040528060138152602001721a185c9d995cdd081b9bdd08185b1b1bddd959606a1b81525061304c565b60026007541415610dd65760405162461bcd60e51b8152600401610b99906150d3565b6002600755610de6848484612e3e565b6040516001600160a01b038416907f188a622567eeca997c3d494fd65f76ca910b90a50a0c44d5e37b2ea5539e027b90600090a2505060016007555050565b600060026007541415610e4a5760405162461bcd60e51b8152600401610b99906150d3565b6002600755610e5a84848461305b565b6001600755949350505050565b6001600160a01b0381166000908152600c602052604081208291610f009190610e8e612c7d565b6001600160a01b03166001600160a01b03168152602001908152602001600020544211156040518060400160405280600781526020016619d95b995c985b60ca1b8152506040518060400160405280601081526020016f1a9bda5b881b9bdd08185b1b1bddd95960821b81525061304c565b60026007541415610f235760405162461bcd60e51b8152600401610b99906150d3565b600260075560005b8351811015610f5957610f51848281518110610f4357fe5b602002602001015184612f19565b600101610f2b565b505060016007555050565b60026007541415610f875760405162461bcd60e51b8152600401610b99906150d3565b60026007556000610f9f82610f9a612c7d565b6130dd565b9050610fb2610fac612c7d565b8261327e565b610fba612c7d565b6001600160a01b0316610fcb612c7d565b6001600160a01b03167f56c54ba9bd38d8fd62012e42c7ee564519b09763c426d331b3661b537ead19b2836040516110039190614b7a565b60405180910390a350506001600755565b60055460ff1690565b6000611027613385565b905090565b6000610c1d611039612c7d565b8461107a856001600061104a612c7d565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061344f565b612d8a565b6001600160a01b0381166000908152600c6020526040812082916110a69190610e8e612c7d565b600260075414156110c95760405162461bcd60e51b8152600401610b99906150d3565b60026007556110d88383612f19565b5050600160075550565b600e5481565b6110fe866110f4612c7d565b8787878787611e36565b611108878761107f565b50505050505050565b6001600160a01b0381166000908152600b6020526040812061113290613474565b90505b919050565b600080856001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016111699190614983565b60206040518083038186803b15801561118157600080fd5b505afa158015611195573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b99190614612565b905060006111c7878761271a565b90506111fd6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168988613478565b6040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038a16906323e30c8b906112559033908c908c9088908d908d906004016149b1565b602060405180830381600087803b15801561126f57600080fd5b505af1158015611283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a79190614612565b146112c45760405162461bcd60e51b8152600401610b9990614c8e565b604051636eb1769f60e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063dd62ed3e90611315908c903090600401614997565b60206040518083038186803b15801561132d57600080fd5b505afa158015611341573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113659190614612565b90506000611373888461344f565b9050808210156113955760405162461bcd60e51b8152600401610b9990614efb565b6113ca6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168b30846134ce565b60006113d4612871565b90506001600160a01b03811615611419576114196001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168286613478565b6040516370a0823160e01b815285906001600160a01b038c16906370a0823190611447903090600401614983565b60206040518083038186803b15801561145f57600080fd5b505afa158015611473573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114979190614612565b10156114b55760405162461bcd60e51b8152600401610b9990614fe3565b5060019a9950505050505050505050565b60006115c77f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ba6a6d946040518163ffffffff1660e01b815260040160206040518083038186803b15801561152457600080fd5b505afa158015611538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155c91906142f6565b6001600160a01b031661156d612c7d565b6001600160a01b0316146040518060400160405280600781526020016619d95b995c985b60ca1b815250604051806040016040528060128152602001711b9bdd08199c9bdb48185c98da185b99d95b60721b81525061304c565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614156116975761169061160e610d11565b6040516370a0823160e01b81526001600160a01b038716906370a082319061163a903090600401614983565b60206040518083038186803b15801561165257600080fd5b505afa158015611666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168a9190614612565b906134f5565b9050611716565b6040516370a0823160e01b81526001600160a01b038516906370a08231906116c3903090600401614983565b60206040518083038186803b1580156116db57600080fd5b505afa1580156116ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117139190614612565b90505b61172a6001600160a01b0385168483613478565b9392505050565b61178c844211156040518060400160405280600d81526020016c1a185c9d995cdd14195c9b5a5d609a1b8152506040518060400160405280601081526020016f6578706972656420646561646c696e6560801b81525061304c565b6001600160a01b0387166000908152600b602052604081207fcf62e02d601d8426967cb60ac75d60a05af83c07b18cb166ba8dae434b4f4cb8908990899089906117d590613474565b896040516020016117eb96959493929190614b83565b604051602081830303815290604052805190602001209050600061180e8261351d565b9050600061181e82878787613556565b905061188d8a6001600160a01b0316826001600160a01b0316146040518060400160405280600d81526020016c1a185c9d995cdd14195c9b5a5d609a1b81525060405180604001604052806011815260200170696e76616c6964207369676e617475726560781b81525061304c565b6001600160a01b038a166000908152600b602052604090206118ae9061364c565b6118b98a8a8a613655565b50505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614611907576000611132565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190611953903090600401614983565b60206040518083038186803b15801561196b57600080fd5b505afa15801561197f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111329190614612565b6119b9876119af612c7d565b8787878787611731565b6111088787611b99565b6001600160a01b031660009081526020819052604090205490565b60026007541415611a015760405162461bcd60e51b8152600401610b99906150d3565b60026007556000611a11836137aa565b9050611a1d82826138d8565b816001600160a01b0316611a2f612c7d565b6001600160a01b03167fe31c7b8d08ee7db0afa68782e1028ef92305caeea8626633ad44d413e30f6b2f83604051611a679190614b7a565b60405180910390a35050600160075550565b6001600160a01b0381166000908152600d6020526040812061113290613474565b7f000000000000000000000000000000000000000000000000000000000000000081565b60026007541415611ae15760405162461bcd60e51b8152600401610b99906150d3565b600260075560005b818110156110d857611b1d838383818110611b0057fe5b9050602002016020810190611b1591906142da565b610d0c612c7d565b600101611ae9565b60405163d505accf60e01b81526001600160a01b0389169063d505accf90611b5d908a908a908a908a908a908a908a90600401614a2e565b600060405180830381600087803b158015611b7757600080fd5b505af1158015611b8b573d6000803e3d6000fd5b505050505050505050505050565b6001600160a01b0382166000908152600a602052604081208391611bc09190610d3e612c7d565b60026007541415611be35760405162461bcd60e51b8152600401610b99906150d3565b60026007556060611bf384611c8e565b905060005b8151811015611c2d576000828281518110611c0f57fe5b60200260200101519050611c24818787612e3e565b50600101611bf8565b506040516001600160a01b038516907f188a622567eeca997c3d494fd65f76ca910b90a50a0c44d5e37b2ea5539e027b90600090a2505060016007555050565b6001600160a01b038116600090815260066020526040812061113290613474565b6001600160a01b038116600090815260086020908152604091829020805483518184028101840190945280845260609392830182828015611cf857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611cda575b50505050509050919050565b60026007541415611d275760405162461bcd60e51b8152600401610b99906150d3565b60026007556000600881611d39612c7d565b6001600160a01b03166001600160a01b03168152602001908152602001600020905060005b8154811015611da1576000828281548110611d7557fe5b6000918252602090912001546001600160a01b03169050611d9881610c86612c7d565b50600101611d5e565b50610c9b612c7d565b6001600160a01b039182166000908152600c6020908152604080832093909416825291909152205490565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b6b5780601f10610b4057610100808354040283529160200191610b6b565b611e8e844211156040518060400160405280600a8152602001691a9bda5b94195c9b5a5d60b21b8152506040518060400160405280601081526020016f6578706972656420646561646c696e6560801b81525061304c565b6001600160a01b0387166000908152600d602052604081207fe0cb137ed00756b7f7610b5426cc8211e27df30423fd836f640f3036c5023d9890899089908990611ed790613474565b89604051602001611eed96959493929190614b83565b6040516020818303038152906040528051906020012090506000611f108261351d565b90506000611f2082878787613556565b9050611f8c8a6001600160a01b0316826001600160a01b0316146040518060400160405280600a8152602001691a9bda5b94195c9b5a5d60b21b81525060405180604001604052806011815260200170696e76616c6964207369676e617475726560781b81525061304c565b6001600160a01b038a166000908152600d60205260409020611fad9061364c565b6118b98a8a8a61398c565b6000610c1d611fc5612c7d565b848461398c565b6001600160a01b038116600090815260096020818152604080842080548251808401845294855268616e67656c496e666f60b81b858501528251808401909352600d83526c185b99d95b081b9bdd081cd95d609a1b938301939093528493909261203c9260ff909116919061304c565b806001015481600201549250925050915091565b6000610c1d61205d612c7d565b8461107a856040518060600160405280602581526020016152fe6025913960016000612087612c7d565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190613ae7565b6120c4866110f4612c7d565b6121028888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250610e67915050565b5050505050505050565b6000600260075414156121315760405162461bcd60e51b8152600401610b99906150d3565b60026007556121408383613b13565b60016007559392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061217a612c7d565b6001600160a01b038116600090815260096020818152604092839020805484518086018652938452681cd95d141bdbdb125960ba1b848401528451808601909552600c85526b185b99d95b081a5cc81cd95d60a21b928501929092529394506121ea9260ff90911615919061304c565b6122ee7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03166378ed5d1f866040518263ffffffff1660e01b81526004016122439190614b7a565b60206040518083038186803b15801561225b57600080fd5b505afa15801561226f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229391906142f6565b6001600160a01b031614604051806040016040528060098152602001681cd95d141bdbdb125960ba1b815250604051806040016040528060118152602001701d1bdad95b881b9bdd081b585d18da1959607a1b81525061304c565b805460ff191660019081178255019190915550565b600260075414156123265760405162461bcd60e51b8152600401610b99906150d3565b60026007556000612336826137aa565b9050612349612343612c7d565b826138d8565b612351612c7d565b6001600160a01b0316612362612c7d565b6001600160a01b03167fe31c7b8d08ee7db0afa68782e1028ef92305caeea8626633ad44d413e30f6b2f836040516110039190614b7a565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260075414156123e15760405162461bcd60e51b8152600401610b99906150d3565b600260075560006123f283836130dd565b90506123ff610fac612c7d565b816001600160a01b0316612411612c7d565b6001600160a01b03167f56c54ba9bd38d8fd62012e42c7ee564519b09763c426d331b3661b537ead19b283604051611a679190614b7a565b6060808367ffffffffffffffff8111801561246357600080fd5b5060405190808252806020026020018201604052801561248d578160200160208202803683370190505b5091508367ffffffffffffffff811180156124a757600080fd5b506040519080825280602002602001820160405280156124db57816020015b60608152602001906001900390816124c65790505b50905060005b848110156125d25760006060308888858181106124fa57fe5b905060200281019061250c91906151b2565b60405161251a9291906148ff565b600060405180830381855af49150503d8060008114612555576040519150601f19603f3d011682016040523d82523d6000602084013e61255a565b606091505b50915091508180612569575085155b61257282613b27565b906125905760405162461bcd60e51b8152600401610b999190614c01565b508185848151811061259e57fe5b602002602001019015159081151581525050808484815181106125bd57fe5b602090810291909101015250506001016124e1565b50935093915050565b834211156125fb5760405162461bcd60e51b8152600401610b9990614d35565b6001600160a01b03871660009081526006602052604081207f00000000000000000000000000000000000000000000000000000000000000009089908990899061264490613474565b8960405160200161265a96959493929190614b83565b604051602081830303815290604052805190602001209050600061267d8261351d565b9050600061268d82878787613556565b9050896001600160a01b0316816001600160a01b0316146126c05760405162461bcd60e51b8152600401610b9990614ec4565b6001600160a01b038a1660009081526006602052604090206126e19061364c565b6118b98a8a8a612d8a565b60006126fd883388888888886125db565b612708888888610e25565b98975050505050505050565b61138881565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161461276d5760405162461bcd60e51b8152600401610b9990614e1c565b61172a6127106127956002820461278f600e5487613b8790919063ffffffff16565b9061344f565b90613bc1565b600260075414156127be5760405162461bcd60e51b8152600401610b99906150d3565b600260075560006127d061069f612c7d565b905060006127e082610f9a612c7d565b90506127f56127ed612c7d565b60001961327e565b6127fd612c7d565b6001600160a01b031661280e612c7d565b6001600160a01b03167faaeda929aa102e867049528ec7cd2499e3a2f8846e736ae7935f234dfbf500d9836040516110039190614b7a565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600090565b6128d27f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ba6a6d946040518163ffffffff1660e01b815260040160206040518083038186803b15801561152457600080fd5b6128db81613bf3565b50565b6000610c1d6128eb612c7d565b8484613655565b61271081565b612904876119af612c7d565b612102888888610d17565b600260075414156129325760405162461bcd60e51b8152600401610b99906150d3565b600260075561294081612ab1565b7f9a6d44d7017a7e2000dda7960d80ab013d2790401179957cc245192e61d44f65612969612c7d565b82604051612978929190614997565b60405180910390a1610c0161298b612c7d565b8261299761069f612c7d565b613c1a565b600260075414156129bf5760405162461bcd60e51b8152600401610b99906150d3565b600260075560006008816129d1612c7d565b6001600160a01b03166001600160a01b03168152602001908152602001600020905060005b8154811015612a78576000828281548110612a0d57fe5b6000918252602090912001546001600160a01b031690507f9a6d44d7017a7e2000dda7960d80ab013d2790401179957cc245192e61d44f65612a4d612c7d565b82604051612a5c929190614997565b60405180910390a1612a6f61298b612c7d565b506001016129f6565b5060086000612a85612c7d565b6001600160a01b03166001600160a01b031681526020019081526020016000206000610c019190614243565b600060086000612abf612c7d565b6001600160a01b03908116825260208201929092526040016000208054909250908316826000198301838110612af157fe5b6000918252602090912001546001600160a01b03161415612b3d5781805480612b1657fe5b600082815260209020810160001990810180546001600160a01b0319169055019055612c1e565b60005b60018203811015612c1c57836001600160a01b0316838281548110612b6157fe5b6000918252602090912001546001600160a01b03161415612c1457826001830381548110612b8b57fe5b9060005260206000200160009054906101000a90046001600160a01b0316838281548110612bb557fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480612bed57fe5b600082815260209020810160001990810180546001600160a01b0319169055019055612c1c565b600101612b40565b505b612c7881838054905014156040518060400160405280600a81526020016917dc5d5a5d105b99d95b60b21b8152506040518060400160405280600e81526020016d1d5b9a9bda5b995908185b99d95b60921b81525061304c565b505050565b3390565b6001600160a01b038116600090815260096020908152604091829020805483518085018552600f81526e17d95b595c99d95b98de505b99d95b608a1b81850152845180860190955260128552711b9bdd08185919195908189e48185b99d95b60721b938501939093529092612cfc9260ff909216919061304c565b6000612d07846119c3565b60018301546040516302f940c760e41b81529192506001600160a01b03851691632f940c7091612d3b918890600401615141565b600060405180830381600087803b158015612d5557600080fd5b505af1158015612d69573d6000803e3d6000fd5b5050506002830154612d7c9150826134f5565b826002018190555050505050565b6001600160a01b038316612db05760405162461bcd60e51b8152600401610b999061500e565b6001600160a01b038216612dd65760405162461bcd60e51b8152600401610b9990614cbc565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612e31908590614b7a565b60405180910390a3505050565b6001600160a01b038316600090815260096020908152604091829020805483518085018552600d81526c17da185c9d995cdd105b99d95b609a1b81850152845180860190955260128552711b9bdd08185919195908189e48185b99d95b60721b938501939093529092612eb79260ff909216919061304c565b60018101546040516387a4459b60e01b81526001600160a01b038616916387a4459b91612eeb919087908790600401615158565b600060405180830381600087803b158015612f0557600080fd5b505af1158015612102573d6000803e3d6000fd5b6001600160a01b0381166000908152600860205260408120905b8154811015612fd357612fcb846001600160a01b0316838381548110612f5557fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b031614156040518060400160405280600a81526020016917da9bda5b905b99d95b60b21b8152506040518060400160405280600c81526020016b185b99d95b081a9bda5b995960a21b81525061304c565b600101612f33565b5080546001810182556000828152602090200180546001600160a01b0319166001600160a01b0385161790556040517f2d02e423de531208beb4f472c3dc736ffa9c141c9779e987230974ed64b0a8f0906130319084908690614997565b60405180910390a1612c788284613047856119c3565b613d14565b82612c7857612c788282613e02565b6000613068848484613e3b565b6130d384613074612c7d565b61107a856040518060600160405280602881526020016152d6602891396001600160a01b038a166000908152600160205260408120906130b2612c7d565b6001600160a01b031681526020810191909152604001600020549190613ae7565b5060019392505050565b600060001983146130ee57826130f9565b6130f961069f612c7d565b925060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016131499190614983565b60206040518083038186803b15801561316157600080fd5b505afa158015613175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131999190614612565b90506131cf6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168486613478565b6040516370a0823160e01b8152613276906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319061321f903090600401614983565b60206040518083038186803b15801561323757600080fd5b505afa15801561324b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061326f9190614612565b82906134f5565b949350505050565b6001600160a01b0382166132a45760405162461bcd60e51b8152600401610b9990614f5d565b6132b082600083613f50565b6000198114156132d557506001600160a01b0381166000908152602081905260409020545b6133128160405180606001604052806022815260200161528e602291396001600160a01b0385166000908152602081905260409020549190613ae7565b6001600160a01b03831660009081526020819052604090205560025461333890826134f5565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90613379908590614b7a565b60405180910390a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006133b0614086565b14156133dd57507f0000000000000000000000000000000000000000000000000000000000000000610b73565b6134487f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061408a565b9050610b73565b60008282018381101561172a5760405162461bcd60e51b8152600401610b9990614cfe565b5490565b612c788363a9059cbb60e01b8484604051602401613497929190614a6f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526140cb565b6134ef846323b872dd60e01b85858560405160240161349793929190614a0a565b50505050565b6000828211156135175760405162461bcd60e51b8152600401610b9990614d6c565b50900390565b6000613527613385565b82604051602001613539929190614968565b604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156135985760405162461bcd60e51b8152600401610b9990614da3565b8360ff16601b14806135ad57508360ff16601c145b6135c95760405162461bcd60e51b8152600401610b9990614e41565b6000600186868686604051600081526020016040526040516135ee9493929190614be3565b6020604051602081039080840390855afa158015613610573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166136435760405162461bcd60e51b8152600401610b9990614c14565b95945050505050565b80546001019055565b6136d260006001600160a01b0316846001600160a01b031614156040518060400160405280600f81526020016e5f68617276657374417070726f766560881b8152506040518060400160405280601d81526020017f617070726f76652066726f6d20746865207a65726f206164647265737300000081525061304c565b61374f60006001600160a01b0316836001600160a01b031614156040518060400160405280600f81526020016e5f68617276657374417070726f766560881b8152506040518060400160405280601b81526020017f617070726f766520746f20746865207a65726f2061646472657373000000000081525061304c565b6001600160a01b038084166000818152600a602090815260408083209487168084529490915290819020849055517fc8e2c75e3f21fd63fb9fe3230bec566be64c431fa052a4690a1e2ea2db61c87c90612e31908590614b7a565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016137f99190614983565b60206040518083038186803b15801561381157600080fd5b505afa158015613825573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138499190614612565b9050613888613856612c7d565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169030866134ce565b61172a817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161163a9190614983565b6001600160a01b0382166138fe5760405162461bcd60e51b8152600401610b999061510a565b61390a60008383613f50565b600254613917908261344f565b6002556001600160a01b03821660009081526020819052604090205461393d908261344f565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90613379908590614b7a565b613a0660006001600160a01b0316846001600160a01b031614156040518060400160405280600c81526020016b5f6a6f696e417070726f766560a01b8152506040518060400160405280601d81526020017f617070726f76652066726f6d20746865207a65726f206164647265737300000081525061304c565b613a8060006001600160a01b0316836001600160a01b031614156040518060400160405280600c81526020016b5f6a6f696e417070726f766560a01b8152506040518060400160405280601b81526020017f617070726f766520746f20746865207a65726f2061646472657373000000000081525061304c565b8060011415613a8c5750425b6001600160a01b038084166000818152600c602090815260408083209487168084529490915290819020849055517fdaf873f4ad7a2d2b87090ad775dc0cbffe4cdb8fdfe20576a2420c1febfc6a7890612e31908590614b7a565b60008184841115613b0b5760405162461bcd60e51b8152600401610b999190614c01565b505050900390565b6000610c1d613b20612c7d565b8484613e3b565b6060604482511015613b6d575060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c790000006020820152611135565b60048201915081806020019051810190611132919061480b565b600082613b9657506000610c21565b82820282848281613ba357fe5b041461172a5760405162461bcd60e51b8152600401610b9990614e83565b6000808211613be25760405162461bcd60e51b8152600401610b9990614de5565b818381613beb57fe5b049392505050565b612710811115613c155760405162461bcd60e51b8152600401610b9990614f32565b600e55565b6001600160a01b038216600090815260096020908152604091829020805483518085018552600e81526d17ddda5d1a191c985dd05b99d95b60921b81850152845180860190955260128552711b9bdd08185919195908189e48185b99d95b60721b938501939093529092613c949260ff909216919061304c565b6001810154604051630ad58d2f60e01b81526001600160a01b03851691630ad58d2f91613cc8919086908990600401615185565b600060405180830381600087803b158015613ce257600080fd5b505af1158015613cf6573d6000803e3d6000fd5b5050506002820154613d099150836134f5565b600290910155505050565b6001600160a01b038216600090815260096020908152604091829020805483518085018552600d81526c17d9195c1bdcda5d105b99d95b609a1b81850152845180860190955260128552711b9bdd08185919195908189e48185b99d95b60721b938501939093529092613d8d9260ff909216919061304c565b6001810154604051638dbdbe6d60e01b81526001600160a01b03851691638dbdbe6d91613dc1919086908990600401615185565b600060405180830381600087803b158015613ddb57600080fd5b505af1158015613def573d6000803e3d6000fd5b5050506002820154613d0991508361344f565b8181604051602001613e1592919061492b565b60408051601f198184030181529082905262461bcd60e51b8252610b9991600401614c01565b6001600160a01b038316613e615760405162461bcd60e51b8152600401610b9990614f9e565b6001600160a01b038216613e875760405162461bcd60e51b8152600401610b9990614c4b565b613e92838383613f50565b613ecf816040518060600160405280602681526020016152b0602691396001600160a01b0386166000908152602081905260409020549190613ae7565b6001600160a01b038085166000908152602081905260408082209390935590841681522054613efe908261344f565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612e31908590614b7a565b6001600160a01b03831615614014576001600160a01b0383166000908152600860205260409020600019821015613fcc5760005b8154811015613fc6576000828281548110613f9b57fe5b6000918252602090912001546001600160a01b03169050613fbd868286613c1a565b50600101613f84565b50614012565b60005b8154811015614010576000828281548110613fe657fe5b6000918252602090912001546001600160a01b031690506140078682612c81565b50600101613fcf565b505b505b6001600160a01b03821615612c78576001600160a01b0382166000908152600860205260408120905b815481101561407f57600082828154811061405457fe5b6000918252602090912001546001600160a01b03169050614076858286613d14565b5060010161403d565b5050505050565b4690565b6000838383614097614086565b306040516020016140ac959493929190614bb7565b6040516020818303038152906040528051906020012090509392505050565b6060614120826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661415a9092919063ffffffff16565b805190915015612c78578080602001905181019061413e91906145f6565b612c785760405162461bcd60e51b8152600401610b9990615089565b606061327684846000858561416e85614204565b61418a5760405162461bcd60e51b8152600401610b9990615052565b60006060866001600160a01b031685876040516141a7919061490f565b60006040518083038185875af1925050503d80600081146141e4576040519150601f19603f3d011682016040523d82523d6000602084013e6141e9565b606091505b50915091506141f982828661420a565b979650505050505050565b3b151590565b6060831561421957508161172a565b8251156142295782518084602001fd5b8160405162461bcd60e51b8152600401610b999190614c01565b50805460008255906000526020600020908101906128db91905b80821115614271576000815560010161425d565b5090565b8035610c218161526a565b60008083601f840112614291578182fd5b50813567ffffffffffffffff8111156142a8578182fd5b60208301915083602080830285010111156142c257600080fd5b9250929050565b803560ff81168114610c2157600080fd5b6000602082840312156142eb578081fd5b813561172a8161526a565b600060208284031215614307578081fd5b815161172a8161526a565b60008060408385031215614324578081fd5b823561432f8161526a565b9150602083013561433f8161526a565b809150509250929050565b60008060006060848603121561435e578081fd5b83356143698161526a565b925060208401356143798161526a565b929592945050506040919091013590565b600080600080600080600060e0888a0312156143a4578283fd5b87356143af8161526a565b965060208801356143bf8161526a565b955060408801359450606088013593506143dc8960808a016142c9565b925060a0880135915060c0880135905092959891949750929550565b6000806040838503121561440a578182fd5b82356144158161526a565b946020939093013593505050565b600080600060408486031215614437578283fd5b833567ffffffffffffffff81111561444d578384fd5b61445986828701614280565b909450925050602084013561446d8161527f565b809150509250925092565b6000806020838503121561448a578182fd5b823567ffffffffffffffff8111156144a0578283fd5b6144ac85828601614280565b90969095509350505050565b60008060008060008060008060e0898b0312156144d3578182fd5b883567ffffffffffffffff8111156144e9578283fd5b6144f58b828c01614280565b90995097505060208901356145098161526a565b955060408901359450606089013593506145268a60808b016142c9565b925060a0890135915060c089013590509295985092959890939650565b60008060408385031215614555578182fd5b823567ffffffffffffffff81111561456b578283fd5b8301601f8101851361457b578283fd5b803561458e6145898261521e565b6151f7565b8082825260208083019250808501898283870288010111156145ae578788fd5b8795505b848610156145d8576145c48a82614275565b8452600195909501949281019281016145b2565b508196506145e889828a01614275565b955050505050509250929050565b600060208284031215614607578081fd5b815161172a8161527f565b600060208284031215614623578081fd5b5051919050565b60008060408385031215614324578182fd5b600080600060608486031215614650578081fd5b833561465b8161526a565b9250602084013561466b8161526a565b9150604084013561446d8161526a565b600080600080600080600080610100898b031215614697578182fd5b88356146a28161526a565b975060208901356146b28161526a565b965060408901356146c28161526a565b955060608901359450608089013593506146df8a60a08b016142c9565b925060c0890135915060e089013590509295985092959890939650565b600080600080600080600060e0888a031215614716578081fd5b87356147218161526a565b965060208801356147318161526a565b95506040880135945060608801359350608088013560ff81168114614754578182fd5b9699959850939692959460a0840135945060c09093013592915050565b600080600080600060808688031215614788578283fd5b85356147938161526a565b945060208601356147a38161526a565b935060408601359250606086013567ffffffffffffffff808211156147c6578283fd5b818801915088601f8301126147d9578283fd5b8135818111156147e7578384fd5b8960208285010111156147f8578384fd5b9699959850939650602001949392505050565b60006020828403121561481c578081fd5b815167ffffffffffffffff80821115614833578283fd5b818401915084601f830112614846578283fd5b815181811115614854578384fd5b614867601f8201601f19166020016151f7565b915080825285602082850101111561487d578384fd5b61488e81602084016020860161523e565b50949350505050565b6000602082840312156148a8578081fd5b5035919050565b600080604083850312156148c1578182fd5b82359150602083013561433f8161526a565b600081518084526148eb81602086016020860161523e565b601f01601f19169290920160200192915050565b6000828483379101908152919050565b6000825161492181846020870161523e565b9190910192915050565b6000835161493d81846020880161523e565b6101d160f51b908301908152835161495c81600284016020880161523e565b01600201949350505050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c084013781830160c090810191909152601f909201601f1916010195945050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b604080825283519082018190526000906020906060840190828701845b82811015614ac3578151151584529284019290840190600101614aa5565b50505083810382850152808551614ada8184614b7a565b91508192508381028201848801865b83811015614b13578583038552614b018383516148d3565b94870194925090860190600101614ae9565b50909998505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614b635783516001600160a01b031683529284019291840191600101614b3e565b50909695505050505050565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b93845260ff9290921660208401526040830152606082015260800190565b60006020825261172a60208301846148d3565b60208082526018908201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b602080825260149082015273696e76616c69642072657475726e2076616c756560601b604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601d908201527f45524332305065726d69743a206578706972656420646561646c696e65000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604082015261756560f01b606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252600b908201526a3bb937b733903a37b5b2b760a91b604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604082015261756560f01b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601e908201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604082015260600190565b6020808252601f908201527f616c6c6f77616e636520646f6573206e6f7420616c6c6f7720726566756e6400604082015260600190565b602080825260119082015270199959481c985d1948195e18d959591959607a1b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526011908201527018985b185b98d948191958dc99585cd959607a1b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b9182526001600160a01b0316602082015260400190565b9283526001600160a01b03918216602084015216604082015260600190565b918252602082015260400190565b92835260208301919091526001600160a01b0316604082015260600190565b60ff91909116815260200190565b6000808335601e198436030181126151c8578283fd5b83018035915067ffffffffffffffff8211156151e2578283fd5b6020019150368190038213156142c257600080fd5b60405181810167ffffffffffffffff8111828210171561521657600080fd5b604052919050565b600067ffffffffffffffff821115615234578081fd5b5060209081020190565b60005b83811015615259578181015183820152602001615241565b838111156134ef5750506000910152565b6001600160a01b03811681146128db57600080fd5b80151581146128db57600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220e52166055dbdd56e20c3788a72557bae7907d6c913fc2f2ef4c9335b008b897264736f6c634300060c0033000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000013466f756e7461696e20556e697377617020563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a46544e2d554e492d563200000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106103975760003560e01c80637ecebe00116101dc578063c86283c811610102578063dd62ed3e116100a0578063ecefc7051161006f578063ecefc70514610a75578063ed31cdfa14610a8a578063eda9bf3a14610aaa578063f44b7cd514610aca57610397565b8063dd62ed3e14610a00578063e5cd6a1514610a20578063e92d0d5d14610a35578063ea775b8c14610a5557610397565b8063d6e03cd4116100dc578063d6e03cd414610996578063d977a196146109b6578063d9d98ce4146109cb578063db2e21bc146109eb57610397565b8063c86283c814610935578063d2423b5114610955578063d505accf1461097657610397565b8063a2e655b31161017a578063aaaca55811610149578063aaaca558146108cb578063ac78012c146108e0578063b6b55f2514610900578063c45a01551461092057610397565b8063a2e655b31461083d578063a457c2d71461086b578063a69f0ee41461088b578063a9059cbb146108ab57610397565b80638f94f747116101b65780638f94f747146107c857806395d89b41146107e85780639b23bf6c146107fd5780639c4be7f41461081d57610397565b80637ecebe0014610766578063864da28a146107865780638ed955b9146107b357610397565b80634847cdc8116102c1578063707a11f71161025f57806372f702f31161022e57806372f702f3146106e45780637a360b3e146107065780637c516e94146107265780637d4f20d81461074657610397565b8063707a11f71461066457806370a082311461068457806370aff70f146106a457806370fb0430146106c457610397565b80635cffe9de1161029b5780635cffe9de146105e45780635d799f87146106045780635e9e2ec914610624578063613255ab1461064457610397565b80634847cdc81461058f578063503e9b72146105a4578063576491df146105c457610397565b8063200fe1d911610339578063313ce56711610308578063313ce567146105185780633644e5151461053a578063395093511461054f5780633e8341d21461056f57610397565b8063200fe1d91461049857806323b872dd146104b857806327e5af88146104d85780632e1a7d4d146104f857610397565b80630d48a7b2116103755780630d48a7b2146104165780630e5c011e1461044357806313f89aa81461046357806318160ddd1461048357610397565b806306fdde031461039c5780630743faf1146103c7578063095ea7b3146103e9575b600080fd5b3480156103a857600080fd5b506103b1610adf565b6040516103be9190614c01565b60405180910390f35b3480156103d357600080fd5b506103e76103e23660046142da565b610b76565b005b3480156103f557600080fd5b506104096104043660046143f8565b610c09565b6040516103be9190614b6f565b34801561042257600080fd5b50610436610431366004614312565b610c27565b6040516103be9190614b7a565b34801561044f57600080fd5b506103e761045e3660046142da565b610c52565b34801561046f57600080fd5b506103e761047e3660046142da565b610cd8565b34801561048f57600080fd5b50610436610d11565b3480156104a457600080fd5b506103e76104b336600461463c565b610d17565b3480156104c457600080fd5b506104096104d336600461434a565b610e25565b3480156104e457600080fd5b506103e76104f3366004614543565b610e67565b34801561050457600080fd5b506103e7610513366004614897565b610f64565b34801561052457600080fd5b5061052d611014565b6040516103be91906151a4565b34801561054657600080fd5b5061043661101d565b34801561055b57600080fd5b5061040961056a3660046143f8565b61102c565b34801561057b57600080fd5b506103e761058a36600461462a565b61107f565b34801561059b57600080fd5b506104366110e2565b3480156105b057600080fd5b506103e76105bf3660046146fc565b6110e8565b3480156105d057600080fd5b506104366105df3660046142da565b611111565b3480156105f057600080fd5b506104096105ff366004614771565b61113a565b34801561061057600080fd5b5061043661061f36600461462a565b6114c6565b34801561063057600080fd5b506103e761063f36600461438a565b611731565b34801561065057600080fd5b5061043661065f3660046142da565b6118c5565b34801561067057600080fd5b506103e761067f36600461438a565b6119a3565b34801561069057600080fd5b5061043661069f3660046142da565b6119c3565b3480156106b057600080fd5b506103e76106bf3660046148af565b6119de565b3480156106d057600080fd5b506104366106df3660046142da565b611a79565b3480156106f057600080fd5b506106f9611a9a565b6040516103be9190614983565b34801561071257600080fd5b506103e7610721366004614478565b611abe565b34801561073257600080fd5b506103e761074136600461467b565b611b25565b34801561075257600080fd5b506103e7610761366004614312565b611b99565b34801561077257600080fd5b506104366107813660046142da565b611c6d565b34801561079257600080fd5b506107a66107a13660046142da565b611c8e565b6040516103be9190614b22565b3480156107bf57600080fd5b506103e7611d04565b3480156107d457600080fd5b506104366107e3366004614312565b611daa565b3480156107f457600080fd5b506103b1611dd5565b34801561080957600080fd5b506103e761081836600461438a565b611e36565b34801561082957600080fd5b506104096108383660046143f8565b611fb8565b34801561084957600080fd5b5061085d6108583660046142da565b611fcc565b6040516103be929190615177565b34801561087757600080fd5b506104096108863660046143f8565b612050565b34801561089757600080fd5b506103e76108a63660046144b8565b6120b8565b3480156108b757600080fd5b506104096108c63660046143f8565b61210c565b3480156108d757600080fd5b506106f961214c565b3480156108ec57600080fd5b506103e76108fb366004614897565b612170565b34801561090c57600080fd5b506103e761091b366004614897565b612303565b34801561092c57600080fd5b506106f961239a565b34801561094157600080fd5b506103e76109503660046148af565b6123be565b610968610963366004614423565b612449565b6040516103be929190614a88565b34801561098257600080fd5b506103e761099136600461438a565b6125db565b3480156109a257600080fd5b506104096109b136600461438a565b6126ec565b3480156109c257600080fd5b50610436612714565b3480156109d757600080fd5b506104366109e63660046143f8565b61271a565b3480156109f757600080fd5b506103e761279b565b348015610a0c57600080fd5b50610436610a1b366004614312565b612846565b348015610a2c57600080fd5b506106f9612871565b348015610a4157600080fd5b506103e7610a50366004614897565b612876565b348015610a6157600080fd5b50610409610a703660046143f8565b6128de565b348015610a8157600080fd5b506104366128f2565b348015610a9657600080fd5b506103e7610aa536600461467b565b6128f8565b348015610ab657600080fd5b506103e7610ac53660046142da565b61290f565b348015610ad657600080fd5b506103e761299c565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b6b5780601f10610b4057610100808354040283529160200191610b6b565b820191906000526020600020905b815481529060010190602001808311610b4e57829003601f168201915b505050505090505b90565b60026007541415610ba25760405162461bcd60e51b8152600401610b99906150d3565b60405180910390fd5b6002600755610bb081612ab1565b7f2342954acf5c3f328802c33175c0833910fab5313fa11c2807406519ea0835f4610bd9612c7d565b82604051610be8929190614997565b60405180910390a1610c01610bfb612c7d565b82612c81565b506001600755565b6000610c1d610c16612c7d565b8484612d8a565b5060015b92915050565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b60026007541415610c755760405162461bcd60e51b8152600401610b99906150d3565b6002600755610c9381610c86612c7d565b610c8e612c7d565b612e3e565b610c9b612c7d565b6001600160a01b03167f188a622567eeca997c3d494fd65f76ca910b90a50a0c44d5e37b2ea5539e027b60405160405180910390a2506001600755565b60026007541415610cfb5760405162461bcd60e51b8152600401610b99906150d3565b6002600755610c0181610d0c612c7d565b612f19565b60025490565b6001600160a01b0382166000908152600a602052604081208391610db39190610d3e612c7d565b6001600160a01b03166001600160a01b03168152602001908152602001600020544211156040518060400160405280600781526020016619d95b995c985b60ca1b815250604051806040016040528060138152602001721a185c9d995cdd081b9bdd08185b1b1bddd959606a1b81525061304c565b60026007541415610dd65760405162461bcd60e51b8152600401610b99906150d3565b6002600755610de6848484612e3e565b6040516001600160a01b038416907f188a622567eeca997c3d494fd65f76ca910b90a50a0c44d5e37b2ea5539e027b90600090a2505060016007555050565b600060026007541415610e4a5760405162461bcd60e51b8152600401610b99906150d3565b6002600755610e5a84848461305b565b6001600755949350505050565b6001600160a01b0381166000908152600c602052604081208291610f009190610e8e612c7d565b6001600160a01b03166001600160a01b03168152602001908152602001600020544211156040518060400160405280600781526020016619d95b995c985b60ca1b8152506040518060400160405280601081526020016f1a9bda5b881b9bdd08185b1b1bddd95960821b81525061304c565b60026007541415610f235760405162461bcd60e51b8152600401610b99906150d3565b600260075560005b8351811015610f5957610f51848281518110610f4357fe5b602002602001015184612f19565b600101610f2b565b505060016007555050565b60026007541415610f875760405162461bcd60e51b8152600401610b99906150d3565b60026007556000610f9f82610f9a612c7d565b6130dd565b9050610fb2610fac612c7d565b8261327e565b610fba612c7d565b6001600160a01b0316610fcb612c7d565b6001600160a01b03167f56c54ba9bd38d8fd62012e42c7ee564519b09763c426d331b3661b537ead19b2836040516110039190614b7a565b60405180910390a350506001600755565b60055460ff1690565b6000611027613385565b905090565b6000610c1d611039612c7d565b8461107a856001600061104a612c7d565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549061344f565b612d8a565b6001600160a01b0381166000908152600c6020526040812082916110a69190610e8e612c7d565b600260075414156110c95760405162461bcd60e51b8152600401610b99906150d3565b60026007556110d88383612f19565b5050600160075550565b600e5481565b6110fe866110f4612c7d565b8787878787611e36565b611108878761107f565b50505050505050565b6001600160a01b0381166000908152600b6020526040812061113290613474565b90505b919050565b600080856001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016111699190614983565b60206040518083038186803b15801561118157600080fd5b505afa158015611195573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b99190614612565b905060006111c7878761271a565b90506111fd6001600160a01b037f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae168988613478565b6040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038a16906323e30c8b906112559033908c908c9088908d908d906004016149b1565b602060405180830381600087803b15801561126f57600080fd5b505af1158015611283573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a79190614612565b146112c45760405162461bcd60e51b8152600401610b9990614c8e565b604051636eb1769f60e11b81526000906001600160a01b037f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae169063dd62ed3e90611315908c903090600401614997565b60206040518083038186803b15801561132d57600080fd5b505afa158015611341573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113659190614612565b90506000611373888461344f565b9050808210156113955760405162461bcd60e51b8152600401610b9990614efb565b6113ca6001600160a01b037f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae168b30846134ce565b60006113d4612871565b90506001600160a01b03811615611419576114196001600160a01b037f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae168286613478565b6040516370a0823160e01b815285906001600160a01b038c16906370a0823190611447903090600401614983565b60206040518083038186803b15801561145f57600080fd5b505afa158015611473573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114979190614612565b10156114b55760405162461bcd60e51b8152600401610b9990614fe3565b5060019a9950505050505050505050565b60006115c77f000000000000000000000000de7dbc03c90b0c6029f435865cd92212d0e0cac36001600160a01b031663ba6a6d946040518163ffffffff1660e01b815260040160206040518083038186803b15801561152457600080fd5b505afa158015611538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061155c91906142f6565b6001600160a01b031661156d612c7d565b6001600160a01b0316146040518060400160405280600781526020016619d95b995c985b60ca1b815250604051806040016040528060128152602001711b9bdd08199c9bdb48185c98da185b99d95b60721b81525061304c565b60007f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae6001600160a01b0316846001600160a01b031614156116975761169061160e610d11565b6040516370a0823160e01b81526001600160a01b038716906370a082319061163a903090600401614983565b60206040518083038186803b15801561165257600080fd5b505afa158015611666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168a9190614612565b906134f5565b9050611716565b6040516370a0823160e01b81526001600160a01b038516906370a08231906116c3903090600401614983565b60206040518083038186803b1580156116db57600080fd5b505afa1580156116ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117139190614612565b90505b61172a6001600160a01b0385168483613478565b9392505050565b61178c844211156040518060400160405280600d81526020016c1a185c9d995cdd14195c9b5a5d609a1b8152506040518060400160405280601081526020016f6578706972656420646561646c696e6560801b81525061304c565b6001600160a01b0387166000908152600b602052604081207fcf62e02d601d8426967cb60ac75d60a05af83c07b18cb166ba8dae434b4f4cb8908990899089906117d590613474565b896040516020016117eb96959493929190614b83565b604051602081830303815290604052805190602001209050600061180e8261351d565b9050600061181e82878787613556565b905061188d8a6001600160a01b0316826001600160a01b0316146040518060400160405280600d81526020016c1a185c9d995cdd14195c9b5a5d609a1b81525060405180604001604052806011815260200170696e76616c6964207369676e617475726560781b81525061304c565b6001600160a01b038a166000908152600b602052604090206118ae9061364c565b6118b98a8a8a613655565b50505050505050505050565b60007f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae6001600160a01b0316826001600160a01b031614611907576000611132565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae16906370a0823190611953903090600401614983565b60206040518083038186803b15801561196b57600080fd5b505afa15801561197f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111329190614612565b6119b9876119af612c7d565b8787878787611731565b6111088787611b99565b6001600160a01b031660009081526020819052604090205490565b60026007541415611a015760405162461bcd60e51b8152600401610b99906150d3565b60026007556000611a11836137aa565b9050611a1d82826138d8565b816001600160a01b0316611a2f612c7d565b6001600160a01b03167fe31c7b8d08ee7db0afa68782e1028ef92305caeea8626633ad44d413e30f6b2f83604051611a679190614b7a565b60405180910390a35050600160075550565b6001600160a01b0381166000908152600d6020526040812061113290613474565b7f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae81565b60026007541415611ae15760405162461bcd60e51b8152600401610b99906150d3565b600260075560005b818110156110d857611b1d838383818110611b0057fe5b9050602002016020810190611b1591906142da565b610d0c612c7d565b600101611ae9565b60405163d505accf60e01b81526001600160a01b0389169063d505accf90611b5d908a908a908a908a908a908a908a90600401614a2e565b600060405180830381600087803b158015611b7757600080fd5b505af1158015611b8b573d6000803e3d6000fd5b505050505050505050505050565b6001600160a01b0382166000908152600a602052604081208391611bc09190610d3e612c7d565b60026007541415611be35760405162461bcd60e51b8152600401610b99906150d3565b60026007556060611bf384611c8e565b905060005b8151811015611c2d576000828281518110611c0f57fe5b60200260200101519050611c24818787612e3e565b50600101611bf8565b506040516001600160a01b038516907f188a622567eeca997c3d494fd65f76ca910b90a50a0c44d5e37b2ea5539e027b90600090a2505060016007555050565b6001600160a01b038116600090815260066020526040812061113290613474565b6001600160a01b038116600090815260086020908152604091829020805483518184028101840190945280845260609392830182828015611cf857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611cda575b50505050509050919050565b60026007541415611d275760405162461bcd60e51b8152600401610b99906150d3565b60026007556000600881611d39612c7d565b6001600160a01b03166001600160a01b03168152602001908152602001600020905060005b8154811015611da1576000828281548110611d7557fe5b6000918252602090912001546001600160a01b03169050611d9881610c86612c7d565b50600101611d5e565b50610c9b612c7d565b6001600160a01b039182166000908152600c6020908152604080832093909416825291909152205490565b60048054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b6b5780601f10610b4057610100808354040283529160200191610b6b565b611e8e844211156040518060400160405280600a8152602001691a9bda5b94195c9b5a5d60b21b8152506040518060400160405280601081526020016f6578706972656420646561646c696e6560801b81525061304c565b6001600160a01b0387166000908152600d602052604081207fe0cb137ed00756b7f7610b5426cc8211e27df30423fd836f640f3036c5023d9890899089908990611ed790613474565b89604051602001611eed96959493929190614b83565b6040516020818303038152906040528051906020012090506000611f108261351d565b90506000611f2082878787613556565b9050611f8c8a6001600160a01b0316826001600160a01b0316146040518060400160405280600a8152602001691a9bda5b94195c9b5a5d60b21b81525060405180604001604052806011815260200170696e76616c6964207369676e617475726560781b81525061304c565b6001600160a01b038a166000908152600d60205260409020611fad9061364c565b6118b98a8a8a61398c565b6000610c1d611fc5612c7d565b848461398c565b6001600160a01b038116600090815260096020818152604080842080548251808401845294855268616e67656c496e666f60b81b858501528251808401909352600d83526c185b99d95b081b9bdd081cd95d609a1b938301939093528493909261203c9260ff909116919061304c565b806001015481600201549250925050915091565b6000610c1d61205d612c7d565b8461107a856040518060600160405280602581526020016152fe6025913960016000612087612c7d565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190613ae7565b6120c4866110f4612c7d565b6121028888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250610e67915050565b5050505050505050565b6000600260075414156121315760405162461bcd60e51b8152600401610b99906150d3565b60026007556121408383613b13565b60016007559392505050565b7f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae81565b600061217a612c7d565b6001600160a01b038116600090815260096020818152604092839020805484518086018652938452681cd95d141bdbdb125960ba1b848401528451808601909552600c85526b185b99d95b081a5cc81cd95d60a21b928501929092529394506121ea9260ff90911615919061304c565b6122ee7f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae6001600160a01b0316836001600160a01b03166378ed5d1f866040518263ffffffff1660e01b81526004016122439190614b7a565b60206040518083038186803b15801561225b57600080fd5b505afa15801561226f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229391906142f6565b6001600160a01b031614604051806040016040528060098152602001681cd95d141bdbdb125960ba1b815250604051806040016040528060118152602001701d1bdad95b881b9bdd081b585d18da1959607a1b81525061304c565b805460ff191660019081178255019190915550565b600260075414156123265760405162461bcd60e51b8152600401610b99906150d3565b60026007556000612336826137aa565b9050612349612343612c7d565b826138d8565b612351612c7d565b6001600160a01b0316612362612c7d565b6001600160a01b03167fe31c7b8d08ee7db0afa68782e1028ef92305caeea8626633ad44d413e30f6b2f836040516110039190614b7a565b7f000000000000000000000000de7dbc03c90b0c6029f435865cd92212d0e0cac381565b600260075414156123e15760405162461bcd60e51b8152600401610b99906150d3565b600260075560006123f283836130dd565b90506123ff610fac612c7d565b816001600160a01b0316612411612c7d565b6001600160a01b03167f56c54ba9bd38d8fd62012e42c7ee564519b09763c426d331b3661b537ead19b283604051611a679190614b7a565b6060808367ffffffffffffffff8111801561246357600080fd5b5060405190808252806020026020018201604052801561248d578160200160208202803683370190505b5091508367ffffffffffffffff811180156124a757600080fd5b506040519080825280602002602001820160405280156124db57816020015b60608152602001906001900390816124c65790505b50905060005b848110156125d25760006060308888858181106124fa57fe5b905060200281019061250c91906151b2565b60405161251a9291906148ff565b600060405180830381855af49150503d8060008114612555576040519150601f19603f3d011682016040523d82523d6000602084013e61255a565b606091505b50915091508180612569575085155b61257282613b27565b906125905760405162461bcd60e51b8152600401610b999190614c01565b508185848151811061259e57fe5b602002602001019015159081151581525050808484815181106125bd57fe5b602090810291909101015250506001016124e1565b50935093915050565b834211156125fb5760405162461bcd60e51b8152600401610b9990614d35565b6001600160a01b03871660009081526006602052604081207f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99089908990899061264490613474565b8960405160200161265a96959493929190614b83565b604051602081830303815290604052805190602001209050600061267d8261351d565b9050600061268d82878787613556565b9050896001600160a01b0316816001600160a01b0316146126c05760405162461bcd60e51b8152600401610b9990614ec4565b6001600160a01b038a1660009081526006602052604090206126e19061364c565b6118b98a8a8a612d8a565b60006126fd883388888888886125db565b612708888888610e25565b98975050505050505050565b61138881565b60007f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae6001600160a01b0316836001600160a01b03161461276d5760405162461bcd60e51b8152600401610b9990614e1c565b61172a6127106127956002820461278f600e5487613b8790919063ffffffff16565b9061344f565b90613bc1565b600260075414156127be5760405162461bcd60e51b8152600401610b99906150d3565b600260075560006127d061069f612c7d565b905060006127e082610f9a612c7d565b90506127f56127ed612c7d565b60001961327e565b6127fd612c7d565b6001600160a01b031661280e612c7d565b6001600160a01b03167faaeda929aa102e867049528ec7cd2499e3a2f8846e736ae7935f234dfbf500d9836040516110039190614b7a565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600090565b6128d27f000000000000000000000000de7dbc03c90b0c6029f435865cd92212d0e0cac36001600160a01b031663ba6a6d946040518163ffffffff1660e01b815260040160206040518083038186803b15801561152457600080fd5b6128db81613bf3565b50565b6000610c1d6128eb612c7d565b8484613655565b61271081565b612904876119af612c7d565b612102888888610d17565b600260075414156129325760405162461bcd60e51b8152600401610b99906150d3565b600260075561294081612ab1565b7f9a6d44d7017a7e2000dda7960d80ab013d2790401179957cc245192e61d44f65612969612c7d565b82604051612978929190614997565b60405180910390a1610c0161298b612c7d565b8261299761069f612c7d565b613c1a565b600260075414156129bf5760405162461bcd60e51b8152600401610b99906150d3565b600260075560006008816129d1612c7d565b6001600160a01b03166001600160a01b03168152602001908152602001600020905060005b8154811015612a78576000828281548110612a0d57fe5b6000918252602090912001546001600160a01b031690507f9a6d44d7017a7e2000dda7960d80ab013d2790401179957cc245192e61d44f65612a4d612c7d565b82604051612a5c929190614997565b60405180910390a1612a6f61298b612c7d565b506001016129f6565b5060086000612a85612c7d565b6001600160a01b03166001600160a01b031681526020019081526020016000206000610c019190614243565b600060086000612abf612c7d565b6001600160a01b03908116825260208201929092526040016000208054909250908316826000198301838110612af157fe5b6000918252602090912001546001600160a01b03161415612b3d5781805480612b1657fe5b600082815260209020810160001990810180546001600160a01b0319169055019055612c1e565b60005b60018203811015612c1c57836001600160a01b0316838281548110612b6157fe5b6000918252602090912001546001600160a01b03161415612c1457826001830381548110612b8b57fe5b9060005260206000200160009054906101000a90046001600160a01b0316838281548110612bb557fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480612bed57fe5b600082815260209020810160001990810180546001600160a01b0319169055019055612c1c565b600101612b40565b505b612c7881838054905014156040518060400160405280600a81526020016917dc5d5a5d105b99d95b60b21b8152506040518060400160405280600e81526020016d1d5b9a9bda5b995908185b99d95b60921b81525061304c565b505050565b3390565b6001600160a01b038116600090815260096020908152604091829020805483518085018552600f81526e17d95b595c99d95b98de505b99d95b608a1b81850152845180860190955260128552711b9bdd08185919195908189e48185b99d95b60721b938501939093529092612cfc9260ff909216919061304c565b6000612d07846119c3565b60018301546040516302f940c760e41b81529192506001600160a01b03851691632f940c7091612d3b918890600401615141565b600060405180830381600087803b158015612d5557600080fd5b505af1158015612d69573d6000803e3d6000fd5b5050506002830154612d7c9150826134f5565b826002018190555050505050565b6001600160a01b038316612db05760405162461bcd60e51b8152600401610b999061500e565b6001600160a01b038216612dd65760405162461bcd60e51b8152600401610b9990614cbc565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612e31908590614b7a565b60405180910390a3505050565b6001600160a01b038316600090815260096020908152604091829020805483518085018552600d81526c17da185c9d995cdd105b99d95b609a1b81850152845180860190955260128552711b9bdd08185919195908189e48185b99d95b60721b938501939093529092612eb79260ff909216919061304c565b60018101546040516387a4459b60e01b81526001600160a01b038616916387a4459b91612eeb919087908790600401615158565b600060405180830381600087803b158015612f0557600080fd5b505af1158015612102573d6000803e3d6000fd5b6001600160a01b0381166000908152600860205260408120905b8154811015612fd357612fcb846001600160a01b0316838381548110612f5557fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b031614156040518060400160405280600a81526020016917da9bda5b905b99d95b60b21b8152506040518060400160405280600c81526020016b185b99d95b081a9bda5b995960a21b81525061304c565b600101612f33565b5080546001810182556000828152602090200180546001600160a01b0319166001600160a01b0385161790556040517f2d02e423de531208beb4f472c3dc736ffa9c141c9779e987230974ed64b0a8f0906130319084908690614997565b60405180910390a1612c788284613047856119c3565b613d14565b82612c7857612c788282613e02565b6000613068848484613e3b565b6130d384613074612c7d565b61107a856040518060600160405280602881526020016152d6602891396001600160a01b038a166000908152600160205260408120906130b2612c7d565b6001600160a01b031681526020810191909152604001600020549190613ae7565b5060019392505050565b600060001983146130ee57826130f9565b6130f961069f612c7d565b925060007f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016131499190614983565b60206040518083038186803b15801561316157600080fd5b505afa158015613175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131999190614612565b90506131cf6001600160a01b037f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae168486613478565b6040516370a0823160e01b8152613276906001600160a01b037f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae16906370a082319061321f903090600401614983565b60206040518083038186803b15801561323757600080fd5b505afa15801561324b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061326f9190614612565b82906134f5565b949350505050565b6001600160a01b0382166132a45760405162461bcd60e51b8152600401610b9990614f5d565b6132b082600083613f50565b6000198114156132d557506001600160a01b0381166000908152602081905260409020545b6133128160405180606001604052806022815260200161528e602291396001600160a01b0385166000908152602081905260409020549190613ae7565b6001600160a01b03831660009081526020819052604090205560025461333890826134f5565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90613379908590614b7a565b60405180910390a35050565b60007f00000000000000000000000000000000000000000000000000000000000000896133b0614086565b14156133dd57507f8d3422f7803a84464d9c38bac9d6710b648c52c5fa9b657b336539c1d60a52a1610b73565b6134487f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7fc9af4838dabef2398daa3466d565761de2c71d059639b19148080aa8884ddcb97fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc661408a565b9050610b73565b60008282018381101561172a5760405162461bcd60e51b8152600401610b9990614cfe565b5490565b612c788363a9059cbb60e01b8484604051602401613497929190614a6f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526140cb565b6134ef846323b872dd60e01b85858560405160240161349793929190614a0a565b50505050565b6000828211156135175760405162461bcd60e51b8152600401610b9990614d6c565b50900390565b6000613527613385565b82604051602001613539929190614968565b604051602081830303815290604052805190602001209050919050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156135985760405162461bcd60e51b8152600401610b9990614da3565b8360ff16601b14806135ad57508360ff16601c145b6135c95760405162461bcd60e51b8152600401610b9990614e41565b6000600186868686604051600081526020016040526040516135ee9493929190614be3565b6020604051602081039080840390855afa158015613610573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166136435760405162461bcd60e51b8152600401610b9990614c14565b95945050505050565b80546001019055565b6136d260006001600160a01b0316846001600160a01b031614156040518060400160405280600f81526020016e5f68617276657374417070726f766560881b8152506040518060400160405280601d81526020017f617070726f76652066726f6d20746865207a65726f206164647265737300000081525061304c565b61374f60006001600160a01b0316836001600160a01b031614156040518060400160405280600f81526020016e5f68617276657374417070726f766560881b8152506040518060400160405280601b81526020017f617070726f766520746f20746865207a65726f2061646472657373000000000081525061304c565b6001600160a01b038084166000818152600a602090815260408083209487168084529490915290819020849055517fc8e2c75e3f21fd63fb9fe3230bec566be64c431fa052a4690a1e2ea2db61c87c90612e31908590614b7a565b6000807f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016137f99190614983565b60206040518083038186803b15801561381157600080fd5b505afa158015613825573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138499190614612565b9050613888613856612c7d565b6001600160a01b037f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae169030866134ce565b61172a817f000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161163a9190614983565b6001600160a01b0382166138fe5760405162461bcd60e51b8152600401610b999061510a565b61390a60008383613f50565b600254613917908261344f565b6002556001600160a01b03821660009081526020819052604090205461393d908261344f565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90613379908590614b7a565b613a0660006001600160a01b0316846001600160a01b031614156040518060400160405280600c81526020016b5f6a6f696e417070726f766560a01b8152506040518060400160405280601d81526020017f617070726f76652066726f6d20746865207a65726f206164647265737300000081525061304c565b613a8060006001600160a01b0316836001600160a01b031614156040518060400160405280600c81526020016b5f6a6f696e417070726f766560a01b8152506040518060400160405280601b81526020017f617070726f766520746f20746865207a65726f2061646472657373000000000081525061304c565b8060011415613a8c5750425b6001600160a01b038084166000818152600c602090815260408083209487168084529490915290819020849055517fdaf873f4ad7a2d2b87090ad775dc0cbffe4cdb8fdfe20576a2420c1febfc6a7890612e31908590614b7a565b60008184841115613b0b5760405162461bcd60e51b8152600401610b999190614c01565b505050900390565b6000610c1d613b20612c7d565b8484613e3b565b6060604482511015613b6d575060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c790000006020820152611135565b60048201915081806020019051810190611132919061480b565b600082613b9657506000610c21565b82820282848281613ba357fe5b041461172a5760405162461bcd60e51b8152600401610b9990614e83565b6000808211613be25760405162461bcd60e51b8152600401610b9990614de5565b818381613beb57fe5b049392505050565b612710811115613c155760405162461bcd60e51b8152600401610b9990614f32565b600e55565b6001600160a01b038216600090815260096020908152604091829020805483518085018552600e81526d17ddda5d1a191c985dd05b99d95b60921b81850152845180860190955260128552711b9bdd08185919195908189e48185b99d95b60721b938501939093529092613c949260ff909216919061304c565b6001810154604051630ad58d2f60e01b81526001600160a01b03851691630ad58d2f91613cc8919086908990600401615185565b600060405180830381600087803b158015613ce257600080fd5b505af1158015613cf6573d6000803e3d6000fd5b5050506002820154613d099150836134f5565b600290910155505050565b6001600160a01b038216600090815260096020908152604091829020805483518085018552600d81526c17d9195c1bdcda5d105b99d95b609a1b81850152845180860190955260128552711b9bdd08185919195908189e48185b99d95b60721b938501939093529092613d8d9260ff909216919061304c565b6001810154604051638dbdbe6d60e01b81526001600160a01b03851691638dbdbe6d91613dc1919086908990600401615185565b600060405180830381600087803b158015613ddb57600080fd5b505af1158015613def573d6000803e3d6000fd5b5050506002820154613d0991508361344f565b8181604051602001613e1592919061492b565b60408051601f198184030181529082905262461bcd60e51b8252610b9991600401614c01565b6001600160a01b038316613e615760405162461bcd60e51b8152600401610b9990614f9e565b6001600160a01b038216613e875760405162461bcd60e51b8152600401610b9990614c4b565b613e92838383613f50565b613ecf816040518060600160405280602681526020016152b0602691396001600160a01b0386166000908152602081905260409020549190613ae7565b6001600160a01b038085166000908152602081905260408082209390935590841681522054613efe908261344f565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612e31908590614b7a565b6001600160a01b03831615614014576001600160a01b0383166000908152600860205260409020600019821015613fcc5760005b8154811015613fc6576000828281548110613f9b57fe5b6000918252602090912001546001600160a01b03169050613fbd868286613c1a565b50600101613f84565b50614012565b60005b8154811015614010576000828281548110613fe657fe5b6000918252602090912001546001600160a01b031690506140078682612c81565b50600101613fcf565b505b505b6001600160a01b03821615612c78576001600160a01b0382166000908152600860205260408120905b815481101561407f57600082828154811061405457fe5b6000918252602090912001546001600160a01b03169050614076858286613d14565b5060010161403d565b5050505050565b4690565b6000838383614097614086565b306040516020016140ac959493929190614bb7565b6040516020818303038152906040528051906020012090509392505050565b6060614120826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661415a9092919063ffffffff16565b805190915015612c78578080602001905181019061413e91906145f6565b612c785760405162461bcd60e51b8152600401610b9990615089565b606061327684846000858561416e85614204565b61418a5760405162461bcd60e51b8152600401610b9990615052565b60006060866001600160a01b031685876040516141a7919061490f565b60006040518083038185875af1925050503d80600081146141e4576040519150601f19603f3d011682016040523d82523d6000602084013e6141e9565b606091505b50915091506141f982828661420a565b979650505050505050565b3b151590565b6060831561421957508161172a565b8251156142295782518084602001fd5b8160405162461bcd60e51b8152600401610b999190614c01565b50805460008255906000526020600020908101906128db91905b80821115614271576000815560010161425d565b5090565b8035610c218161526a565b60008083601f840112614291578182fd5b50813567ffffffffffffffff8111156142a8578182fd5b60208301915083602080830285010111156142c257600080fd5b9250929050565b803560ff81168114610c2157600080fd5b6000602082840312156142eb578081fd5b813561172a8161526a565b600060208284031215614307578081fd5b815161172a8161526a565b60008060408385031215614324578081fd5b823561432f8161526a565b9150602083013561433f8161526a565b809150509250929050565b60008060006060848603121561435e578081fd5b83356143698161526a565b925060208401356143798161526a565b929592945050506040919091013590565b600080600080600080600060e0888a0312156143a4578283fd5b87356143af8161526a565b965060208801356143bf8161526a565b955060408801359450606088013593506143dc8960808a016142c9565b925060a0880135915060c0880135905092959891949750929550565b6000806040838503121561440a578182fd5b82356144158161526a565b946020939093013593505050565b600080600060408486031215614437578283fd5b833567ffffffffffffffff81111561444d578384fd5b61445986828701614280565b909450925050602084013561446d8161527f565b809150509250925092565b6000806020838503121561448a578182fd5b823567ffffffffffffffff8111156144a0578283fd5b6144ac85828601614280565b90969095509350505050565b60008060008060008060008060e0898b0312156144d3578182fd5b883567ffffffffffffffff8111156144e9578283fd5b6144f58b828c01614280565b90995097505060208901356145098161526a565b955060408901359450606089013593506145268a60808b016142c9565b925060a0890135915060c089013590509295985092959890939650565b60008060408385031215614555578182fd5b823567ffffffffffffffff81111561456b578283fd5b8301601f8101851361457b578283fd5b803561458e6145898261521e565b6151f7565b8082825260208083019250808501898283870288010111156145ae578788fd5b8795505b848610156145d8576145c48a82614275565b8452600195909501949281019281016145b2565b508196506145e889828a01614275565b955050505050509250929050565b600060208284031215614607578081fd5b815161172a8161527f565b600060208284031215614623578081fd5b5051919050565b60008060408385031215614324578182fd5b600080600060608486031215614650578081fd5b833561465b8161526a565b9250602084013561466b8161526a565b9150604084013561446d8161526a565b600080600080600080600080610100898b031215614697578182fd5b88356146a28161526a565b975060208901356146b28161526a565b965060408901356146c28161526a565b955060608901359450608089013593506146df8a60a08b016142c9565b925060c0890135915060e089013590509295985092959890939650565b600080600080600080600060e0888a031215614716578081fd5b87356147218161526a565b965060208801356147318161526a565b95506040880135945060608801359350608088013560ff81168114614754578182fd5b9699959850939692959460a0840135945060c09093013592915050565b600080600080600060808688031215614788578283fd5b85356147938161526a565b945060208601356147a38161526a565b935060408601359250606086013567ffffffffffffffff808211156147c6578283fd5b818801915088601f8301126147d9578283fd5b8135818111156147e7578384fd5b8960208285010111156147f8578384fd5b9699959850939650602001949392505050565b60006020828403121561481c578081fd5b815167ffffffffffffffff80821115614833578283fd5b818401915084601f830112614846578283fd5b815181811115614854578384fd5b614867601f8201601f19166020016151f7565b915080825285602082850101111561487d578384fd5b61488e81602084016020860161523e565b50949350505050565b6000602082840312156148a8578081fd5b5035919050565b600080604083850312156148c1578182fd5b82359150602083013561433f8161526a565b600081518084526148eb81602086016020860161523e565b601f01601f19169290920160200192915050565b6000828483379101908152919050565b6000825161492181846020870161523e565b9190910192915050565b6000835161493d81846020880161523e565b6101d160f51b908301908152835161495c81600284016020880161523e565b01600201949350505050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c084013781830160c090810191909152601f909201601f1916010195945050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b604080825283519082018190526000906020906060840190828701845b82811015614ac3578151151584529284019290840190600101614aa5565b50505083810382850152808551614ada8184614b7a565b91508192508381028201848801865b83811015614b13578583038552614b018383516148d3565b94870194925090860190600101614ae9565b50909998505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614b635783516001600160a01b031683529284019291840191600101614b3e565b50909695505050505050565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b93845260ff9290921660208401526040830152606082015260800190565b60006020825261172a60208301846148d3565b60208082526018908201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b602080825260149082015273696e76616c69642072657475726e2076616c756560601b604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601d908201527f45524332305065726d69743a206578706972656420646561646c696e65000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604082015261756560f01b606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252600b908201526a3bb937b733903a37b5b2b760a91b604082015260600190565b60208082526022908201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604082015261756560f01b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252601e908201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604082015260600190565b6020808252601f908201527f616c6c6f77616e636520646f6573206e6f7420616c6c6f7720726566756e6400604082015260600190565b602080825260119082015270199959481c985d1948195e18d959591959607a1b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526011908201527018985b185b98d948191958dc99585cd959607a1b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b9182526001600160a01b0316602082015260400190565b9283526001600160a01b03918216602084015216604082015260600190565b918252602082015260400190565b92835260208301919091526001600160a01b0316604082015260600190565b60ff91909116815260200190565b6000808335601e198436030181126151c8578283fd5b83018035915067ffffffffffffffff8211156151e2578283fd5b6020019150368190038213156142c257600080fd5b60405181810167ffffffffffffffff8111828210171561521657600080fd5b604052919050565b600067ffffffffffffffff821115615234578081fd5b5060209081020190565b60005b83811015615259578181015183820152602001615241565b838111156134ef5750506000910152565b6001600160a01b03811681146128db57600080fd5b80151581146128db57600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220e52166055dbdd56e20c3788a72557bae7907d6c913fc2f2ef4c9335b008b897264736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000013466f756e7461696e20556e697377617020563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a46544e2d554e492d563200000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : token (address): 0xa7c4754F4C5E58d5fCFBaBDC7c2A8684296a32ae
Arg [1] : name_ (string): Fountain Uniswap V2
Arg [2] : symbol_ (string): FTN-UNI-V2
Arg [3] : flashLoanFee (uint256): 9
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000a7c4754f4c5e58d5fcfbabdc7c2a8684296a32ae
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [5] : 466f756e7461696e20556e697377617020563200000000000000000000000000
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [7] : 46544e2d554e492d563200000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
94337:1558:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27571:91;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;65711:244;;;;;;;;;;-1:-1:-1;65711:244:0;;;;;:::i;:::-;;:::i;:::-;;29858:210;;;;;;;;;;-1:-1:-1;29858:210:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;78680:173::-;;;;;;;;;;-1:-1:-1;78680:173:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;63293:157::-;;;;;;;;;;-1:-1:-1;63293:157:0;;;;;:::i;:::-;;:::i;64346:105::-;;;;;;;;;;-1:-1:-1;64346:105:0;;;;;:::i;:::-;;:::i;28670:108::-;;;;;;;;;;;;;:::i;80929:214::-;;;;;;;;;;-1:-1:-1;80929:214:0;;;;;:::i;:::-;;:::i;66270:222::-;;;;;;;;;;-1:-1:-1;66270:222:0;;;;;:::i;:::-;;:::i;74994:246::-;;;;;;;;;;-1:-1:-1;74994:246:0;;;;;:::i;:::-;;:::i;62356:249::-;;;;;;;;;;-1:-1:-1;62356:249:0;;;;;:::i;:::-;;:::i;28514:91::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;52538:115::-;;;;;;;;;;;;;:::i;31413:300::-;;;;;;;;;;-1:-1:-1;31413:300:0;;;;;:::i;:::-;;:::i;74684:161::-;;;;;;;;;;-1:-1:-1;74684:161:0;;;;;:::i;:::-;;:::i;85396:27::-;;;;;;;;;;;;;:::i;75648:322::-;;;;;;;;;;-1:-1:-1;75648:322:0;;;;;:::i;:::-;;:::i;80609:120::-;;;;;;;;;;-1:-1:-1;80609:120:0;;;;;:::i;:::-;;:::i;87195:1304::-;;;;;;;;;;-1:-1:-1;87195:1304:0;;;;;:::i;:::-;;:::i;95243:414::-;;;;;;;;;;-1:-1:-1;95243:414:0;;;;;:::i;:::-;;:::i;79586:1015::-;;;;;;;;;;-1:-1:-1;79586:1015:0;;;;;:::i;:::-;;:::i;85996:266::-;;;;;;;;;;-1:-1:-1;85996:266:0;;;;;:::i;:::-;;:::i;82763:324::-;;;;;;;;;;-1:-1:-1;82763:324:0;;;;;:::i;:::-;;:::i;28841:177::-;;;;;;;;;;-1:-1:-1;28841:177:0;;;;;:::i;:::-;;:::i;61820:268::-;;;;;;;;;;-1:-1:-1;61820:268:0;;;;;:::i;:::-;;:::i;74424:115::-;;;;;;;;;;-1:-1:-1;74424:115:0;;;;;:::i;:::-;;:::i;58507:36::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;64556:192::-;;;;;;;;;;-1:-1:-1;64556:192:0;;;;;:::i;:::-;;:::i;91048:331::-;;;;;;;;;;-1:-1:-1;91048:331:0;;;;;:::i;:::-;;:::i;81314:363::-;;;;;;;;;;-1:-1:-1;81314:363:0;;;;;:::i;:::-;;:::i;52288:120::-;;;;;;;;;;-1:-1:-1;52288:120:0;;;;;:::i;:::-;;:::i;59742:118::-;;;;;;;;;;-1:-1:-1;59742:118:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;63520:351::-;;;;;;;;;;;;;:::i;72536:168::-;;;;;;;;;;-1:-1:-1;72536:168:0;;;;;:::i;:::-;;:::i;27781:95::-;;;;;;;;;;;;;:::i;73422:994::-;;;;;;;;;;-1:-1:-1;73422:994:0;;;;;:::i;:::-;;:::i;72870:189::-;;;;;;;;;;-1:-1:-1;72870:189:0;;;;;:::i;:::-;;:::i;60109:247::-;;;;;;;;;;-1:-1:-1;60109:247:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;32216:400::-;;;;;;;;;;-1:-1:-1;32216:400:0;;;;;:::i;:::-;;:::i;76385:337::-;;;;;;;;;;-1:-1:-1;76385:337:0;;;;;:::i;:::-;;:::i;66012:197::-;;;;;;;;;;-1:-1:-1;66012:197:0;;;;;:::i;:::-;;:::i;85353:36::-;;;;;;;;;;;;;:::i;60532:417::-;;;;;;;;;;-1:-1:-1;60532:417:0;;;;;:::i;:::-;;:::i;61218:274::-;;;;;;;;;;-1:-1:-1;61218:274:0;;;;;:::i;:::-;;:::i;58552:41::-;;;;;;;;;;;;;:::i;62938:245::-;;;;;;;;;;-1:-1:-1;62938:245:0;;;;;:::i;:::-;;:::i;90097:604::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;51287:935::-;;;;;;;;;;-1:-1:-1;51287:935:0;;;;;:::i;:::-;;:::i;52963:349::-;;;;;;;;;;-1:-1:-1;52963:349:0;;;;;:::i;:::-;;:::i;85475:54::-;;;;;;;;;;;;;:::i;86530:325::-;;;;;;;;;;-1:-1:-1;86530:325:0;;;;;:::i;:::-;;:::i;63927:316::-;;;;;;;;;;;;;:::i;29510:201::-;;;;;;;;;;-1:-1:-1;29510:201:0;;;;;:::i;:::-;;:::i;88507:181::-;;;;;;;;;;;;;:::i;95779:113::-;;;;;;;;;;-1:-1:-1;95779:113:0;;;;;:::i;:::-;;:::i;79022:195::-;;;;;;;;;;-1:-1:-1;79022:195:0;;;;;:::i;:::-;;:::i;85430:38::-;;;;;;;;;;;;;:::i;82065:348::-;;;;;;;;;;-1:-1:-1;82065:348:0;;;;;:::i;:::-;;:::i;64851:252::-;;;;;;;;;;-1:-1:-1;64851:252:0;;;;;:::i;:::-;;:::i;65154:439::-;;;;;;;;;;;;;:::i;27571:91::-;27649:5;27642:12;;;;;;;;-1:-1:-1;;27642:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27616:13;;27642:12;;27649:5;;27642:12;;27649:5;27642:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27571:91;;:::o;65711:244::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;;;;;;;;;56428:1;57167:7;:18;65781:17:::1;65792:5:::0;65781:10:::1;:17::i;:::-;65814:38;65823:12;:10;:12::i;:::-;65845:5;65814:38;;;;;;;:::i;:::-;;;;;;;;65903:44;65927:12;:10;:12::i;:::-;65941:5;65903:23;:44::i;:::-;-1:-1:-1::0;56384:1:0;57346:7;:22;65711:244::o;29858:210::-;29977:4;29999:39;30008:12;:10;:12::i;:::-;30022:7;30031:6;29999:8;:39::i;:::-;-1:-1:-1;30056:4:0;29858:210;;;;;:::o;78680:173::-;-1:-1:-1;;;;;78819:18:0;;;78787:7;78819:18;;;:11;:18;;;;;;;;:26;;;;;;;;;;;;;78680:173::o;63293:157::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;63357:48:::1;63371:5:::0;63378:12:::1;:10;:12::i;:::-;63392;:10;:12::i;:::-;63357:13;:48::i;:::-;63429:12;:10;:12::i;:::-;63421:21;::::0;-1:-1:-1;;;;;63421:21:0;;;::::1;::::0;::::1;::::0;;;::::1;-1:-1:-1::0;56384:1:0;57346:7;:22;63293:157::o;64346:105::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;64412:31:::1;64423:5:::0;64430:12:::1;:10;:12::i;:::-;64412:10;:31::i;28670:108::-:0;28758:12;;28670:108;:::o;80929:214::-;-1:-1:-1;;;;;78348:18:0;;;;;;:11;:18;;;;;;;78303:148;;78348:18;78367:12;:10;:12::i;:::-;-1:-1:-1;;;;;78348:32:0;;;;;;;;;;;;;;;-1:-1:-1;78348:32:0;;78303:148;;;;;;;;;;-1:-1:-1;;;78303:148:0;;;;;;;;;;;;;;;-1:-1:-1;;;78303:148:0;;;;;;;78329:15;:51;;;78303:148;:11;:148::i;:::-;56428:1:::1;57034:7;;:19;;57026:63;;;::::0;-1:-1:-1;;;57026:63:0;;::::1;::::0;::::1;;;:::i;:::-;56428:1;57167:7;:18:::0;81076:30:::2;81090:5:::0;81097:4;81103:2;81076:13:::2;:30::i;:::-;81122:13;::::0;-1:-1:-1;;;;;81122:13:0;::::2;::::0;::::2;::::0;;;::::2;-1:-1:-1::0;;56384:1:0::1;57346:7;:22:::0;-1:-1:-1;;80929:214:0:o;66270:222::-;66415:4;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;66439:45:::1;66458:6:::0;66466:9;66477:6;66439:18:::1;:45::i;:::-;56384:1:::0;57346:7;:22;66432:52;66270:222;-1:-1:-1;;;;66270:222:0:o;74994:246::-;-1:-1:-1;;;;;72211:17:0;;;;;;:11;:17;;;;;;;72166:144;;72211:17;72229:12;:10;:12::i;:::-;-1:-1:-1;;;;;72211:31:0;;;;;;;;;;;;;;;-1:-1:-1;72211:31:0;;72166:144;;;;;;;;;;-1:-1:-1;;;72166:144:0;;;;;;;;;;;;;;;-1:-1:-1;;;72166:144:0;;;;;;;72192:15;:50;;;72166:144;:11;:144::i;:::-;56428:1:::1;57034:7;;:19;;57026:63;;;::::0;-1:-1:-1;;;57026:63:0;;::::1;::::0;::::1;;;:::i;:::-;56428:1;57167:7;:18:::0;75140:9:::2;75135:98;75159:6;:13;75155:1;:17;75135:98;;;75194:27;75205:6;75212:1;75205:9;;;;;;;;;;;;;;75216:4;75194:10;:27::i;:::-;75174:3;;75135:98;;;-1:-1:-1::0;;56384:1:0::1;57346:7;:22:::0;-1:-1:-1;;74994:246:0:o;62356:249::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;62423:15:::1;62441:31;62451:6:::0;62459:12:::1;:10;:12::i;:::-;62441:9;:31::i;:::-;62423:49;;62508:28;62514:12;:10;:12::i;:::-;62528:7;62508:5;:28::i;:::-;62584:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;62552:45:0::1;62561:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;62552:45:0::1;;62575:7;62552:45;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;56384:1:0;57346:7;:22;62356:249::o;28514:91::-;28588:9;;;;28514:91;:::o;52538:115::-;52598:7;52625:20;:18;:20::i;:::-;52618:27;;52538:115;:::o;31413:300::-;31528:4;31550:133;31573:12;:10;:12::i;:::-;31600:7;31622:50;31661:10;31622:11;:25;31634:12;:10;:12::i;:::-;-1:-1:-1;;;;;31622:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;31622:25:0;;;:34;;;;;;;;;;;:38;:50::i;:::-;31550:8;:133::i;74684:161::-;-1:-1:-1;;;;;72211:17:0;;;;;;:11;:17;;;;;;;72166:144;;72211:17;72229:12;:10;:12::i;72166:144::-;56428:1:::1;57034:7;;:19;;57026:63;;;::::0;-1:-1:-1;;;57026:63:0;;::::1;::::0;::::1;;;:::i;:::-;56428:1;57167:7;:18:::0;74814:23:::2;74825:5:::0;74832:4;74814:10:::2;:23::i;:::-;-1:-1:-1::0;;56384:1:0::1;57346:7;:22:::0;-1:-1:-1;74684:161:0:o;85396:27::-;;;;:::o;75648:322::-;75866:60;75877:4;75883:12;:10;:12::i;:::-;75897:9;75908:8;75918:1;75921;75924;75866:10;:60::i;:::-;75937:25;75950:5;75957:4;75937:12;:25::i;:::-;75648:322;;;;;;;:::o;80609:120::-;-1:-1:-1;;;;;80697:14:0;;80670:7;80697:14;;;:7;:14;;;;;:24;;:22;:24::i;:::-;80690:31;;80609:120;;;;:::o;87195:1304::-;87403:38;;-1:-1:-1;;;87403:38:0;;87368:4;;;;-1:-1:-1;;;;;87403:23:0;;;-1:-1:-1;;87403:38:0;;87435:4;;87403:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87385:56;;87452:11;87466:23;87475:5;87482:6;87466:8;:23::i;:::-;87452:37;-1:-1:-1;87535:52:0;-1:-1:-1;;;;;87535:12:0;:25;87569:8;87580:6;87535:25;:52::i;:::-;87620:58;;-1:-1:-1;;;87620:58:0;;85586:45;;-1:-1:-1;;;;;87620:20:0;;;-1:-1:-1;;87620:58:0;;87641:10;;87653:5;;87660:6;;87668:3;;87673:4;;;;87620:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:92;87598:162;;;;-1:-1:-1;;;87598:162:0;;;;;;;:::i;:::-;87811:56;;-1:-1:-1;;;87811:56:0;;87771:24;;-1:-1:-1;;;;;87811:12:0;:22;;;;:56;;87842:8;;87861:4;;87811:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87771:96;-1:-1:-1;87878:17:0;87898:15;:6;87909:3;87898:10;:15::i;:::-;87878:35;;87966:9;87946:16;:29;;87924:110;;;;-1:-1:-1;;;87924:110:0;;;;;;;:::i;:::-;88081:124;-1:-1:-1;;;;;88081:12:0;:29;88133:8;88165:4;88185:9;88081:29;:124::i;:::-;88216:17;88236:23;:21;:23::i;:::-;88216:43;-1:-1:-1;;;;;;88274:23:0;;;88270:70;;88299:41;-1:-1:-1;;;;;88299:12:0;:25;88325:9;88336:3;88299:25;:41::i;:::-;88373:38;;-1:-1:-1;;;88373:38:0;;88415:7;;-1:-1:-1;;;;;88373:23:0;;;-1:-1:-1;;88373:38:0;;88405:4;;88373:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:49;;88351:116;;;;-1:-1:-1;;;88351:116:0;;;;;;;:::i;:::-;-1:-1:-1;88487:4:0;;87195:1304;-1:-1:-1;;;;;;;;;;87195:1304:0:o;95243:414::-;95349:7;94479:131;94521:7;-1:-1:-1;;;;;94521:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;94505:35:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;94505:35:0;;94479:131;;;;;;;;;;;;;-1:-1:-1;;;94479:131:0;;;;;;;;;;;;;;;;-1:-1:-1;;;94479:131:0;;;:11;:131::i;:::-;95374:14:::1;95412:12;-1:-1:-1::0;;;;;95403:21:0;;::::1;::::0;;::::1;;95399:184;;;95450:49;95485:13;:11;:13::i;:::-;95450:30;::::0;-1:-1:-1;;;95450:30:0;;-1:-1:-1;;;;;95450:15:0;::::1;::::0;-1:-1:-1;;95450:30:0::1;::::0;95474:4:::1;::::0;95450:30:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:34:::0;::::1;:49::i;:::-;95441:58;;95399:184;;;95541:30;::::0;-1:-1:-1;;;95541:30:0;;-1:-1:-1;;;;;95541:15:0;::::1;::::0;-1:-1:-1;;95541:30:0::1;::::0;95565:4:::1;::::0;95541:30:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95532:39;;95399:184;95593:30;-1:-1:-1::0;;;;;95593:18:0;::::1;95612:2:::0;95616:6;95593:18:::1;:30::i;:::-;95643:6:::0;95243:414;-1:-1:-1;;;95243:414:0:o;79586:1015::-;79851:127;79896:8;79877:15;:27;;79851:127;;;;;;;;;;;;;-1:-1:-1;;;79851:127:0;;;;;;;;;;;;;;;;-1:-1:-1;;;79851:127:0;;;:11;:127::i;:::-;-1:-1:-1;;;;;80222:14:0;;79991:18;80222:14;;;:7;:14;;;;;77763:129;;80222:14;;80161:6;;80190:9;;80222:24;;:22;:24::i;:::-;80269:8;80053:243;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;80025:286;;;;;;79991:320;;80324:12;80339:28;80356:10;80339:16;:28::i;:::-;80324:43;;80380:14;80397:28;80411:4;80417:1;80420;80423;80397:13;:28::i;:::-;80436:66;;;;;;;;;;;-1:-1:-1;;;80436:66:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;80436:66:0;;;;80380:45;;-1:-1:-1;80436:66:0;;-1:-1:-1;;;;;80448:15:0;;;;;;;;80436:11;:66::i;:::-;-1:-1:-1;;;;;80515:14:0;;;;;;:7;:14;;;;;:26;;:24;:26::i;:::-;80552:41;80568:5;80575:6;80583:9;80552:15;:41::i;:::-;79586:1015;;;;;;;;;;:::o;85996:266::-;86101:7;86163:12;-1:-1:-1;;;;;86146:30:0;;;;;;;:108;;86253:1;86146:108;;;86196:37;;-1:-1:-1;;;86196:37:0;;-1:-1:-1;;;;;86196:12:0;:22;;-1:-1:-1;;86196:37:0;;86227:4;;86196:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;82763:324::-;82981:63;82995:4;83001:12;:10;:12::i;:::-;83015:9;83026:8;83036:1;83039;83042;82981:13;:63::i;:::-;83055:24;83070:4;83076:2;83055:14;:24::i;28841:177::-;-1:-1:-1;;;;;28992:18:0;28960:7;28992:18;;;;;;;;;;;;28841:177::o;61820:268::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;61940:15:::1;61958:16;61967:6:::0;61958:8:::1;:16::i;:::-;61940:34;;62010:18;62016:2;62020:7;62010:5;:18::i;:::-;-1:-1:-1::0;;;;;62046:34:0;::::1;62054:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;62046:34:0::1;;62068:7;62046:34;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;56384:1:0;57346:7;:22;-1:-1:-1;61820:268:0:o;74424:115::-;-1:-1:-1;;;;;74508:13:0;;74481:7;74508:13;;;:7;:13;;;;;:23;;:21;:23::i;58507:36::-;;;:::o;64556:192::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;64640:9:::1;64635:106;64655:17:::0;;::::1;64635:106;;;64694:35;64705:6;;64712:1;64705:9;;;;;;;;;;;;;;;;;;;;:::i;:::-;64716:12;:10;:12::i;64694:35::-;64674:3;;64635:106;;91048:331:::0;91322:49;;-1:-1:-1;;;91322:49:0;;-1:-1:-1;;;;;91322:12:0;;;-1:-1:-1;;91322:49:0;;91335:4;;91341:2;;91345:6;;91353:8;;91363:1;;91366;;91369;;91322:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91048:331;;;;;;;;:::o;81314:363::-;-1:-1:-1;;;;;78348:18:0;;;;;;:11;:18;;;;;;;78303:148;;78348:18;78367:12;:10;:12::i;78303:148::-;56428:1:::1;57034:7;;:19;;57026:63;;;::::0;-1:-1:-1;;;57026:63:0;;::::1;::::0;::::1;;;:::i;:::-;56428:1;57167:7;:18:::0;81448:22:::2;81473:17;81485:4:::0;81473:11:::2;:17::i;:::-;81448:42;;81506:9;81501:140;81525:6;:13;81521:1;:17;81501:140;;;81560:12;81575:6;81582:1;81575:9;;;;;;;;;;;;;;81560:24;;81599:30;81613:5;81620:4;81626:2;81599:13;:30::i;:::-;-1:-1:-1::0;81540:3:0::2;;81501:140;;;-1:-1:-1::0;81656:13:0::2;::::0;-1:-1:-1;;;;;81656:13:0;::::2;::::0;::::2;::::0;;;::::2;-1:-1:-1::0;;56384:1:0::1;57346:7;:22:::0;-1:-1:-1;;81314:363:0:o;52288:120::-;-1:-1:-1;;;;;52376:14:0;;52349:7;52376:14;;;:7;:14;;;;;:24;;:22;:24::i;59742:118::-;-1:-1:-1;;;;;59833:19:0;;;;;;:13;:19;;;;;;;;;59826:26;;;;;;;;;;;;;;;;;59798:15;;59826:26;;;59833:19;59826:26;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59826:26:0;;;-1:-1:-1;59826:26:0;;;;;;;;;;;;;;;;;;;59742:118;;;:::o;63520:351::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;63605:23:::1;63631:13;63605:23:::0;63645:12:::1;:10;:12::i;:::-;-1:-1:-1::0;;;;;63631:27:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;63631:27:0;;;;-1:-1:-1;63669:158:0::1;63693:13:::0;;63689:17;::::1;63669:158;;;63728:12;63743:6;63750:1;63743:9;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;63743:9:0::1;::::0;-1:-1:-1;63767:48:0::1;63743:9:::0;63788:12:::1;:10;:12::i;63767:48::-;-1:-1:-1::0;63708:3:0::1;;63669:158;;;;63850:12;:10;:12::i;72536:168::-:0;-1:-1:-1;;;;;72671:17:0;;;72639:7;72671:17;;;:11;:17;;;;;;;;:25;;;;;;;;;;;;;72536:168::o;27781:95::-;27861:7;27854:14;;;;;;;;-1:-1:-1;;27854:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27828:13;;27854:14;;27861:7;;27854:14;;27861:7;27854:14;;;;;;;;;;;;;;;;;;;;;;;;73422:994;73683:124;73728:8;73709:15;:27;;73683:124;;;;;;;;;;;;;-1:-1:-1;;;73683:124:0;;;;;;;;;;;;;;;;-1:-1:-1;;;73683:124:0;;;:11;:124::i;:::-;-1:-1:-1;;;;;74047:13:0;;73820:18;74047:13;;;:7;:13;;;;;71640:125;;74047:13;;73986:6;;74015:9;;74047:23;;:21;:23::i;:::-;74093:8;73882:238;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;73854:281;;;;;;73820:315;;74148:12;74163:28;74180:10;74163:16;:28::i;:::-;74148:43;;74204:14;74221:28;74235:4;74241:1;74244;74247;74221:13;:28::i;:::-;74260:62;;;;;;;;;;;-1:-1:-1;;;74260:62:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;74260:62:0;;;;74204:45;;-1:-1:-1;74260:62:0;;-1:-1:-1;;;;;74272:14:0;;;;;;;;74260:11;:62::i;:::-;-1:-1:-1;;;;;74335:13:0;;;;;;:7;:13;;;;;:25;;:23;:25::i;:::-;74371:37;74384:4;74390:6;74398:9;74371:12;:37::i;72870:189::-;72962:4;72984:45;72997:12;:10;:12::i;:::-;73011:6;73019:9;72984:12;:45::i;60109:247::-;-1:-1:-1;;;;;60219:18:0;;60165:7;60219:18;;;:11;:18;;;;;;;;60260:10;;60248:53;;;;;;;;;;-1:-1:-1;;;60248:53:0;;;;;;;;;;;;;;;-1:-1:-1;;;60248:53:0;;;;;;;60165:7;;60219:18;;60248:53;;60260:10;;;;;60248:53;:11;:53::i;:::-;60320:4;:8;;;60330:4;:17;;;60312:36;;;;;60109:247;;;:::o;32216:400::-;32336:4;32358:228;32381:12;:10;:12::i;:::-;32408:7;32430:145;32487:15;32430:145;;;;;;;;;;;;;;;;;:11;:25;32442:12;:10;:12::i;:::-;-1:-1:-1;;;;;32430:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;32430:25:0;;;:34;;;;;;;;;;;;:38;:145::i;76385:337::-;76616:60;76627:4;76633:12;:10;:12::i;76616:60::-;76687:27;76701:6;;76687:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76709:4:0;;-1:-1:-1;76687:13:0;;-1:-1:-1;;76687:27:0:i;:::-;76385:337;;;;;;;;:::o;66012:197::-;66139:4;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;66168:33:::1;66183:9:::0;66194:6;66168:14:::1;:33::i;:::-;56384:1:::0;57346:7;:22;66161:40;66012:197;-1:-1:-1;;;66012:197:0:o;85353:36::-;;;:::o;60532:417::-;60584:12;60606;:10;:12::i;:::-;-1:-1:-1;;;;;60655:18:0;;60630:22;60655:18;;;:11;:18;;;;;;;;;60697:10;;60684:53;;;;;;;;;;-1:-1:-1;;;60684:53:0;;;;;;;;;;;;;;;-1:-1:-1;;;60684:53:0;;;;;;;60655:18;;-1:-1:-1;60684:53:0;;60697:10;;;;60696:11;;60684:53;:11;:53::i;:::-;60774:18;;-1:-1:-1;;;60774:18:0;;60748:140;;-1:-1:-1;;;;;60804:12:0;60774:43;;;:13;;;;-1:-1:-1;;60774:18:0;;60788:3;;60774:18;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;60774:43:0;;60748:140;;;;;;;;;;;;;-1:-1:-1;;;60748:140:0;;;;;;;;;;;;;;;;-1:-1:-1;;;60748:140:0;;;:11;:140::i;:::-;60899:17;;-1:-1:-1;;60899:17:0;60912:4;60899:17;;;;;60927:8;:14;;;;-1:-1:-1;60532:417:0:o;61218:274::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;61324:15:::1;61342:16;61351:6:::0;61342:8:::1;:16::i;:::-;61324:34;;61394:28;61400:12;:10;:12::i;:::-;61414:7;61394:5;:28::i;:::-;61471:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;61440:44:0::1;61448:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;61440:44:0::1;;61462:7;61440:44;;;;;;:::i;58552:41::-:0;;;:::o;62938:245::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;63019:15:::1;63037:21;63047:6:::0;63055:2;63037:9:::1;:21::i;:::-;63019:39;;63094:28;63100:12;:10;:12::i;63094:28::-;-1:-1:-1::0;;;;;63140:35:0;::::1;63149:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;63140:35:0::1;;63163:7;63140:35;;;;;;:::i;90097:604::-:0;90208:23;;90321:5;90310:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90310:24:0;-1:-1:-1;90298:36:0;-1:-1:-1;90367:5:0;90355:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90345:35;;90396:9;90391:303;90411:16;;;90391:303;;;90450:12;90464:19;90512:4;90531:5;;90537:1;90531:8;;;;;;;;;;;;;;;;;;:::i;:::-;90504:36;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90449:91;;;;90563:7;:24;;;;90575:12;90574:13;90563:24;90589:21;90603:6;90589:13;:21::i;:::-;90555:56;;;;;-1:-1:-1;;;90555:56:0;;;;;;;;:::i;:::-;;90641:7;90626:9;90636:1;90626:12;;;;;;;;;;;;;:22;;;;;;;;;;;90676:6;90663:7;90671:1;90663:10;;;;;;;;;;;;;;;;;:19;-1:-1:-1;;90429:3:0;;90391:303;;;;90097:604;;;;;;:::o;51287:935::-;51586:8;51567:15;:27;;51559:69;;;;-1:-1:-1;;;51559:69:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;51861:14:0;;51641:18;51861:14;;;:7;:14;;;;;51736:16;;51861:14;;51803:7;;51833:5;;51861:24;;:22;:24::i;:::-;51908:8;51703:232;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;51675:275;;;;;;51641:309;;51963:12;51978:28;51995:10;51978:16;:28::i;:::-;51963:43;;52019:14;52036:28;52050:4;52056:1;52059;52062;52036:13;:28::i;:::-;52019:45;-1:-1:-1;;;;;;52083:15:0;;;;;;;52075:58;;;;-1:-1:-1;;;52075:58:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;52146:14:0;;;;;;:7;:14;;;;;:26;;:24;:26::i;:::-;52183:31;52192:5;52199:7;52208:5;52183:8;:31::i;52963:349::-;53181:4;53198:51;53205:5;53212:10;53224:5;53231:8;53241:1;53244;53247;53198:6;:51::i;:::-;53267:37;53280:5;53287:9;53298:5;53267:12;:37::i;:::-;53260:44;52963:349;-1:-1:-1;;;;;;;;52963:349:0:o;85475:54::-;85517:12;85475:54;:::o;86530:325::-;86645:7;86695:12;-1:-1:-1;;;;;86678:30:0;;;;;;;86670:54;;;;-1:-1:-1;;;86670:54:0;;;;;;;:::i;:::-;86786:61;85465:3;86787:45;85528:1;85465:3;85517:12;86787:24;86798:12;;86787:6;:10;;:24;;;;:::i;:::-;:28;;:45::i;:::-;86786:51;;:61::i;63927:316::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;63989:14:::1;64006:23;64016:12;:10;:12::i;64006:23::-;63989:40;;64040:15;64058:31;64068:6;64076:12;:10;:12::i;64058:31::-;64040:49;;64125:38;64131:12;:10;:12::i;:::-;-1:-1:-1::0;;64125:5:0::1;:38::i;:::-;64222:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;64181:54:0::1;64199:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;64181:54:0::1;;64213:7;64181:54;;;;;;:::i;29510:201::-:0;-1:-1:-1;;;;;29676:18:0;;;29644:7;29676:18;;;-1:-1:-1;29676:18:0;;;;;;;;:27;;;;;;;;;;;;;29510:201::o;88507:181::-;88623:7;88507:181;:::o;95779:113::-;94479:131;94521:7;-1:-1:-1;;;;;94521:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94479:131;95858:26:::1;95880:3;95858:21;:26::i;:::-;95779:113:::0;:::o;79022:195::-;79117:4;79139:48;79155:12;:10;:12::i;:::-;79169:6;79177:9;79139:15;:48::i;85430:38::-;85465:3;85430:38;:::o;82065:348::-;82303:63;82317:4;82323:12;:10;:12::i;82303:63::-;82377:28;82389:5;82396:4;82402:2;82377:11;:28::i;64851:252::-;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;64917:17:::1;64928:5:::0;64917:10:::1;:17::i;:::-;64950:34;64955:12;:10;:12::i;:::-;64977:5;64950:34;;;;;;;:::i;:::-;;;;;;;;65035:60;65050:12;:10;:12::i;:::-;65064:5;65071:23;65081:12;:10;:12::i;65071:23::-;65035:14;:60::i;65154:439::-:0;56428:1;57034:7;;:19;;57026:63;;;;-1:-1:-1;;;57026:63:0;;;;;;;:::i;:::-;56428:1;57167:7;:18;65211:23:::1;65237:13;65211:23:::0;65251:12:::1;:10;:12::i;:::-;-1:-1:-1::0;;;;;65237:27:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;65237:27:0;;;;-1:-1:-1;65275:266:0::1;65299:13:::0;;65295:17;::::1;65275:266;;;65334:12;65349:6;65356:1;65349:9;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;65349:9:0::1;::::0;-1:-1:-1;65378:34:0::1;65383:12;:10;:12::i;:::-;65405:5;65378:34;;;;;;;:::i;:::-;;;;;;;;65469:60;65484:12;:10;:12::i;65469:60::-;-1:-1:-1::0;65314:3:0::1;;65275:266;;;;65558:13;:27;65572:12;:10;:12::i;:::-;-1:-1:-1::0;;;;;65558:27:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;65558:27:0;;;65551:34:::1;::::0;::::1;:::i;70612:569::-:0;70666:23;70692:13;:27;70706:12;:10;:12::i;:::-;-1:-1:-1;;;;;70692:27:0;;;;;;;;;;;;;;-1:-1:-1;70692:27:0;70744:13;;70692:27;;-1:-1:-1;70744:13:0;70772:24;;70692:27;-1:-1:-1;;70779:7:0;;70772:15;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;70772:15:0;:24;70768:330;;;70813:6;:12;;;;;;;;;;;;;;;;-1:-1:-1;;70813:12:0;;;;;-1:-1:-1;;;;;;70813:12:0;;;;;;70768:330;;;70863:9;70858:229;70888:1;70882:3;:7;70878:1;:11;70858:229;;;70919:9;;-1:-1:-1;;;;;70919:18:0;;;:9;;70926:1;;70919:9;;;;;;;;;;;;;;;;-1:-1:-1;;;;;70919:9:0;:18;70915:157;;;70974:6;70987:1;70981:3;:7;70974:15;;;;;;;;;;;;;;;;;;70962:9;;-1:-1:-1;;;;;70974:15:0;;;;70962:9;;70969:1;;70962:9;;;;;;;;;;;;;;;:27;;-1:-1:-1;;;;;;70962:27:0;-1:-1:-1;;;;;70962:27:0;;;;;;;;;;71012:12;;;;;;;;;;;;;;;;;;-1:-1:-1;;71012:12:0;;;;;-1:-1:-1;;;;;;71012:12:0;;;;;;71047:5;;70915:157;70891:3;;70858:229;;;;70768:330;71120:13;;71108:65;;;;;;;;;;;-1:-1:-1;;;71108:65:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;71108:65:0;;;;;;71120:20;;;;71108:11;:65::i;:::-;70612:569;;;:::o;710:106::-;798:10;710:106;:::o;69806:360::-;-1:-1:-1;;;;;69912:18:0;;69887:22;69912:18;;;:11;:18;;;;;;;;;69953:10;;69941:64;;;;;;;;;;-1:-1:-1;;;69941:64:0;;;;;;;;;;;;;;;-1:-1:-1;;;69941:64:0;;;;;;;69912:18;;69941:64;;69953:10;;;;;69941:64;:11;:64::i;:::-;70016:14;70033:15;70043:4;70033:9;:15::i;:::-;70083:8;;;;70059:39;;-1:-1:-1;;;70059:39:0;;70016:32;;-1:-1:-1;;;;;;70059:23:0;;;;;:39;;70093:4;;70059:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;70129:17:0;;;;:29;;-1:-1:-1;70151:6:0;70129:21;:29::i;:::-;70109:4;:17;;:49;;;;69806:360;;;;:::o;35741:380::-;-1:-1:-1;;;;;35877:19:0;;35869:68;;;;-1:-1:-1;;;35869:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;35956:21:0;;35948:68;;;;-1:-1:-1;;;35948:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;36029:18:0;;;;;;;-1:-1:-1;36029:18:0;;;;;;;;:27;;;;;;;;;;;;;;:36;;;36081:32;;;;;36029:36;;36081:32;:::i;:::-;;;;;;;;35741:380;;;:::o;69513:285::-;-1:-1:-1;;;;;69655:18:0;;69630:22;69655:18;;;:11;:18;;;;;;;;;69696:10;;69684:62;;;;;;;;;;-1:-1:-1;;;69684:62:0;;;;;;;;;;;;;;;-1:-1:-1;;;69684:62:0;;;;;;;69655:18;;69684:62;;69696:10;;;;;69684:62;:11;:62::i;:::-;69771:8;;;;69757:33;;-1:-1:-1;;;69757:33:0;;-1:-1:-1;;;;;69757:13:0;;;-1:-1:-1;;69757:33:0;;69771:8;69781:4;;69787:2;;69757:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70174:430;-1:-1:-1;;;;;70268:19:0;;70242:23;70268:19;;;:13;:19;;;;;;70298:132;70322:13;;70318:17;;70298:132;;;70357:61;70382:5;-1:-1:-1;;;;;70369:18:0;:6;70376:1;70369:9;;;;;;;;;;;;;;;;;;;70357:61;;;;;;;;;;;-1:-1:-1;;;70357:61:0;;;;;;;;;;;;;;;-1:-1:-1;;;70357:61:0;;;;;;;-1:-1:-1;;;;;70369:9:0;;;:18;;;;;;70357:11;:61::i;:::-;70337:3;;70298:132;;;-1:-1:-1;70440:18:0;;;;;;;-1:-1:-1;70440:18:0;;;;;;;;;-1:-1:-1;;;;;;70440:18:0;-1:-1:-1;;;;;70440:18:0;;;;;70476:26;;;;;;70481:4;;70440:18;;70476:26;:::i;:::-;;;;;;;;70553:43;70567:4;70573:5;70580:15;70590:4;70580:9;:15::i;:::-;70553:13;:43::i;57491:202::-;57642:9;57637:48;;57653:32;57664:12;57678:6;57653:10;:32::i;30550:454::-;30690:4;30707:36;30717:6;30725:9;30736:6;30707:9;:36::i;:::-;30754:220;30777:6;30798:12;:10;:12::i;:::-;30825:138;30881:6;30825:138;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;30825:19:0;;;;;;-1:-1:-1;30825:19:0;;;;;;30845:12;:10;:12::i;:::-;-1:-1:-1;;;;;30825:33:0;;;;;;;;;;;;-1:-1:-1;30825:33:0;;;;:37;:138::i;30754:220::-;-1:-1:-1;30992:4:0;30550:454;;;;;:::o;68251:407::-;68316:7;-1:-1:-1;;68406:27:0;;:62;;68462:6;68406:62;;;68436:23;68446:12;:10;:12::i;68436:23::-;68497:37;;-1:-1:-1;;;68497:37:0;;68397:71;;-1:-1:-1;68479:15:0;;68497:12;-1:-1:-1;;;;;68497:22:0;;-1:-1:-1;;68497:37:0;;68528:4;;68497:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68479:55;-1:-1:-1;68545:37:0;-1:-1:-1;;;;;68545:12:0;:25;68571:2;68575:6;68545:25;:37::i;:::-;68612;;-1:-1:-1;;;68612:37:0;;68600:50;;-1:-1:-1;;;;;68612:12:0;:22;;-1:-1:-1;;68612:37:0;;68643:4;;68612:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68600:7;;:11;:50::i;:::-;68593:57;68251:407;-1:-1:-1;;;;68251:407:0:o;34709:594::-;-1:-1:-1;;;;;34793:21:0;;34785:67;;;;-1:-1:-1;;;34785:67:0;;;;;;;:::i;:::-;34865:49;34886:7;34903:1;34907:6;34865:20;:49::i;:::-;-1:-1:-1;;34997:27:0;;34993:60;;;-1:-1:-1;;;;;;35035:18:0;;:9;:18;;;;;;;;;;;34993:60;35087:105;35124:6;35087:105;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;35087:18:0;;:9;:18;;;;;;;;;;;;;:22;:105::i;:::-;-1:-1:-1;;;;;35066:18:0;;:9;:18;;;;;;;;;;:126;35218:12;;:24;;35235:6;35218:16;:24::i;:::-;35203:12;:39;35258:37;;35284:1;;-1:-1:-1;;;;;35258:37:0;;;;;;;35288:6;;35258:37;:::i;:::-;;;;;;;;34709:594;;:::o;40331:289::-;40392:7;40433:16;40416:13;:11;:13::i;:::-;:33;40412:201;;;-1:-1:-1;40473:24:0;40466:31;;40412:201;40537:64;40559:10;40571:12;40585:15;40537:21;:64::i;:::-;40530:71;;;;11896:179;11954:7;11986:5;;;12010:6;;;;12002:46;;;;-1:-1:-1;;;12002:46:0;;;;;;;:::i;43258:114::-;43350:14;;43258:114::o;20040:177::-;20123:86;20143:5;20173:23;;;20198:2;20202:5;20150:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;20150:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;20150:58:0;-1:-1:-1;;;;;;20150:58:0;;;;;;;;;;;20123:19;:86::i;20225:205::-;20326:96;20346:5;20376:27;;;20405:4;20411:2;20415:5;20353:68;;;;;;;;;;:::i;20326:96::-;20225:205;;;;:::o;12358:158::-;12416:7;12449:1;12444;:6;;12436:49;;;;-1:-1:-1;;;12436:49:0;;;;;;;:::i;:::-;-1:-1:-1;12503:5:0;;;12358:158::o;41607:185::-;41684:7;41750:20;:18;:20::i;:::-;41772:10;41721:62;;;;;;;;;:::i;:::-;;;;;;;;;;;;;41711:73;;;;;;41704:80;;41607:185;;;:::o;45726:1432::-;45811:7;46736:66;46722:80;;;46714:127;;;;-1:-1:-1;;;46714:127:0;;;;;;;:::i;:::-;46860:1;:7;;46865:2;46860:7;:18;;;;46871:1;:7;;46876:2;46871:7;46860:18;46852:65;;;;-1:-1:-1;;;46852:65:0;;;;;;;:::i;:::-;47015:14;47032:24;47042:4;47048:1;47051;47054;47032:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;47032:24:0;;-1:-1:-1;;47032:24:0;;;-1:-1:-1;;;;;;;47075:20:0;;47067:57;;;;-1:-1:-1;;;47067:57:0;;;;;;;:::i;:::-;47144:6;45726:1432;-1:-1:-1;;;;;45726:1432:0:o;43380:181::-;43534:19;;43552:1;43534:19;;;43380:181::o;83095:523::-;83224:134;;;;;;;;;;;-1:-1:-1;;;83224:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;83250:19:0;;;;;83224:134;:11;:134::i;:::-;83369:133;;;;;;;;;;;-1:-1:-1;;;83369:133:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;83395:20:0;;;;;83369:133;:11;:133::i;:::-;-1:-1:-1;;;;;83515:18:0;;;;;;;:11;:18;;;;;;;;:26;;;;;;;;;;;;;;:38;;;83569:41;;;;;83515:38;;83569:41;:::i;67815:280::-;67905:37;;-1:-1:-1;;;67905:37:0;;67867:7;;;;67905:12;-1:-1:-1;;;;;67905:22:0;;-1:-1:-1;;67905:37:0;;67936:4;;67905:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67887:55;;67953:66;67983:12;:10;:12::i;:::-;-1:-1:-1;;;;;67953:12:0;:29;;68005:4;68012:6;67953:29;:66::i;:::-;68037:37;;-1:-1:-1;;;68037:37:0;;:50;;68079:7;;68037:12;-1:-1:-1;;;;;68037:22:0;;-1:-1:-1;;68037:37:0;;68068:4;;68037:37;;;:::i;33998:378::-;-1:-1:-1;;;;;34082:21:0;;34074:65;;;;-1:-1:-1;;;34074:65:0;;;;;;;:::i;:::-;34152:49;34181:1;34185:7;34194:6;34152:20;:49::i;:::-;34229:12;;:24;;34246:6;34229:16;:24::i;:::-;34214:12;:39;-1:-1:-1;;;;;34285:18:0;;:9;:18;;;;;;;;;;;:30;;34308:6;34285:22;:30::i;:::-;-1:-1:-1;;;;;34264:18:0;;:9;:18;;;;;;;;;;;:51;;;;34331:37;;34264:18;;:9;34331:37;;;;34361:6;;34331:37;:::i;76730:565::-;76855:130;;;;;;;;;;;-1:-1:-1;;;76855:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;76881:18:0;;;;;76855:130;:11;:130::i;:::-;76996;;;;;;;;;;;-1:-1:-1;;;76996:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77022:20:0;;;;;76996:130;:11;:130::i;:::-;77143:9;77156:1;77143:14;77139:47;;;-1:-1:-1;77171:15:0;77139:47;-1:-1:-1;;;;;77197:17:0;;;;;;;:11;:17;;;;;;;;:25;;;;;;;;;;;;;;:37;;;77250;;;;;77197;;77250;:::i;14723:166::-;14809:7;14845:12;14837:6;;;;14829:29;;;;-1:-1:-1;;;14829:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;14876:5:0;;;14723:166::o;29231:216::-;29353:4;29375:42;29385:12;:10;:12::i;:::-;29399:9;29410:6;29375:9;:42::i;89117:528::-;89216:13;89384:2;89363:11;:18;:23;89359:67;;;-1:-1:-1;89388:38:0;;;;;;;;;;;;;;;;;;;89359:67;89530:4;89517:11;89513:22;89498:37;;89574:11;89563:33;;;;;;;;;;;;:::i;12775:220::-;12833:7;12857:6;12853:20;;-1:-1:-1;12872:1:0;12865:8;;12853:20;12896:5;;;12900:1;12896;:5;:1;12920:5;;;;;:10;12912:56;;;;-1:-1:-1;;;12912:56:0;;;;;;;:::i;13473:153::-;13531:7;13563:1;13559;:5;13551:44;;;;-1:-1:-1;;;13551:44:0;;;;;;;:::i;:::-;13617:1;13613;:5;;;;;;;13473:153;-1:-1:-1;;;13473:153:0:o;88696:155::-;85465:3;88777;:15;;88769:45;;;;-1:-1:-1;;;88769:45:0;;;;;;;:::i;:::-;88825:12;:18;88696:155::o;69149:356::-;-1:-1:-1;;;;;69296:18:0;;69271:22;69296:18;;;:11;:18;;;;;;;;;69337:10;;69325:63;;;;;;;;;;-1:-1:-1;;;69325:63:0;;;;;;;;;;;;;;;-1:-1:-1;;;69325:63:0;;;;;;;69296:18;;69325:63;;69337:10;;;;;69325:63;:11;:63::i;:::-;69414:8;;;;69399:38;;-1:-1:-1;;;69399:38:0;;-1:-1:-1;;;;;69399:14:0;;;-1:-1:-1;;69399:38:0;;69414:8;69424:6;;69432:4;;69399:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;69468:17:0;;;;:29;;-1:-1:-1;69490:6:0;69468:21;:29::i;:::-;69448:17;;;;:49;-1:-1:-1;;;69149:356:0:o;68788:353::-;-1:-1:-1;;;;;68934:18:0;;68909:22;68934:18;;;:11;:18;;;;;;;;;68975:10;;68963:62;;;;;;;;;;-1:-1:-1;;;68963:62:0;;;;;;;;;;;;;;;-1:-1:-1;;;68963:62:0;;;;;;;68934:18;;68963:62;;68975:10;;;;;68963:62;:11;:62::i;:::-;69050:8;;;;69036:37;;-1:-1:-1;;;69036:37:0;;-1:-1:-1;;;;;69036:13:0;;;-1:-1:-1;;69036:37:0;;69050:8;69060:6;;69068:4;;69036:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;69104:17:0;;;;:29;;-1:-1:-1;69126:6:0;69104:21;:29::i;57870:186::-;58019:12;58039:6;58002:44;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;58002:44:0;;;;;;;;;;-1:-1:-1;;;57988:60:0;;;;;;;:::i;33106:610::-;-1:-1:-1;;;;;33246:20:0;;33238:70;;;;-1:-1:-1;;;33238:70:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;33327:23:0;;33319:71;;;;-1:-1:-1;;;33319:71:0;;;;;;;:::i;:::-;33403:47;33424:6;33432:9;33443:6;33403:20;:47::i;:::-;33483:108;33519:6;33483:108;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;33483:17:0;;:9;:17;;;;;;;;;;;;;:21;:108::i;:::-;-1:-1:-1;;;;;33463:17:0;;;:9;:17;;;;;;;;;;;:128;;;;33625:20;;;;;;;:32;;33650:6;33625:24;:32::i;:::-;-1:-1:-1;;;;;33602:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;33673:35;;;;;;;;;;33701:6;;33673:35;:::i;66694:967::-;-1:-1:-1;;;;;66833:18:0;;;66829:555;;-1:-1:-1;;;;;66894:19:0;;66868:23;66894:19;;;:13;:19;;;;;-1:-1:-1;;66932:26:0;;66928:445;;;66984:9;66979:169;67003:13;;66999:17;;66979:169;;;67046:12;67061:6;67068:1;67061:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;67061:9:0;;-1:-1:-1;67093:35:0;67108:4;67061:9;67121:6;67093:14;:35::i;:::-;-1:-1:-1;67018:3:0;;66979:169;;;;66928:445;;;67193:9;67188:170;67212:13;;67208:17;;67188:170;;;67255:12;67270:6;67277:1;67270:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;67270:9:0;;-1:-1:-1;67302:36:0;67326:4;67270:9;67302:23;:36::i;:::-;-1:-1:-1;67227:3:0;;67188:170;;;;66928:445;66829:555;;-1:-1:-1;;;;;67398:16:0;;;67394:260;;-1:-1:-1;;;;;67457:17:0;;67431:23;67457:17;;;:13;:17;;;;;;67489:154;67513:13;;67509:17;;67489:154;;;67552:12;67567:6;67574:1;67567:9;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;67567:9:0;;-1:-1:-1;67595:32:0;67609:2;67567:9;67620:6;67595:13;:32::i;:::-;-1:-1:-1;67528:3:0;;67489:154;;;;67394:260;66694:967;;;:::o;41800:326::-;42099:9;;42073:46::o;40628:337::-;40730:7;40810:8;40837:4;40860:7;40886:13;:11;:13::i;:::-;40926:4;40781:165;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;40757:200;;;;;;40750:207;;40628:337;;;;;:::o;22345:761::-;22795:69;;;;;;;;;;;;;;;;;;22769:23;;22795:69;;-1:-1:-1;;;;;22795:27:0;;;22823:4;;22795:27;:69::i;:::-;22879:17;;22769:95;;-1:-1:-1;22879:21:0;22875:224;;23021:10;23010:30;;;;;;;;;;;;:::i;:::-;23002:85;;;;-1:-1:-1;;;23002:85:0;;;;;;;:::i;4758:195::-;4861:12;4893:52;4915:6;4923:4;4929:1;4932:12;4861;6062:18;6073:6;6062:10;:18::i;:::-;6054:60;;;;-1:-1:-1;;;6054:60:0;;;;;;;:::i;:::-;6188:12;6202:23;6229:6;-1:-1:-1;;;;;6229:11:0;6249:5;6257:4;6229:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6187:75;;;;6280:52;6298:7;6307:10;6319:12;6280:17;:52::i;:::-;6273:59;5810:530;-1:-1:-1;;;;;;;5810:530:0:o;1840:422::-;2207:20;2246:8;;;1840:422::o;8350:742::-;8465:12;8494:7;8490:595;;;-1:-1:-1;8525:10:0;8518:17;;8490:595;8639:17;;:21;8635:439;;8902:10;8896:17;8963:15;8950:10;8946:2;8942:19;8935:44;8850:148;9038:20;;-1:-1:-1;;;9038:20:0;;;;9045:12;;9038:20;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130::-;72:20;;97:33;72:20;97:33;:::i;299:363::-;;;440:3;433:4;425:6;421:17;417:27;407:2;;-1:-1;;448:12;407:2;-1:-1;478:20;;518:18;507:30;;504:2;;;-1:-1;;540:12;504:2;584:4;576:6;572:17;560:29;;635:3;584:4;;619:6;615:17;576:6;601:32;;598:41;595:2;;;652:1;;642:12;595:2;400:262;;;;;:::o;4198:126::-;4263:20;;60540:4;60529:16;;63647:33;;63637:2;;63694:1;;63684:12;4331:241;;4435:2;4423:9;4414:7;4410:23;4406:32;4403:2;;;-1:-1;;4441:12;4403:2;85:6;72:20;97:33;124:5;97:33;:::i;4579:263::-;;4694:2;4682:9;4673:7;4669:23;4665:32;4662:2;;;-1:-1;;4700:12;4662:2;226:6;220:13;238:33;265:5;238:33;:::i;4849:366::-;;;4970:2;4958:9;4949:7;4945:23;4941:32;4938:2;;;-1:-1;;4976:12;4938:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5028:63;-1:-1;5128:2;5167:22;;72:20;97:33;72:20;97:33;:::i;:::-;5136:63;;;;4932:283;;;;;:::o;5222:491::-;;;;5360:2;5348:9;5339:7;5335:23;5331:32;5328:2;;;-1:-1;;5366:12;5328:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5418:63;-1:-1;5518:2;5557:22;;72:20;97:33;72:20;97:33;:::i;:::-;5322:391;;5526:63;;-1:-1;;;5626:2;5665:22;;;;3987:20;;5322:391::o;5720:991::-;;;;;;;;5924:3;5912:9;5903:7;5899:23;5895:33;5892:2;;;-1:-1;;5931:12;5892:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;5983:63;-1:-1;6083:2;6122:22;;72:20;97:33;72:20;97:33;:::i;:::-;6091:63;-1:-1;6191:2;6230:22;;3987:20;;-1:-1;6299:2;6338:22;;3987:20;;-1:-1;6426:51;6469:7;6407:3;6445:22;;6426:51;:::i;:::-;6416:61;;6514:3;6558:9;6554:22;2190:20;6523:63;;6623:3;6667:9;6663:22;2190:20;6632:63;;5886:825;;;;;;;;;;:::o;6718:366::-;;;6839:2;6827:9;6818:7;6814:23;6810:32;6807:2;;;-1:-1;;6845:12;6807:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;6897:63;6997:2;7036:22;;;;3987:20;;-1:-1;;;6801:283::o;7091:538::-;;;;7255:2;7243:9;7234:7;7230:23;7226:32;7223:2;;;-1:-1;;7261:12;7223:2;7319:17;7306:31;7357:18;7349:6;7346:30;7343:2;;;-1:-1;;7379:12;7343:2;7417:91;7500:7;7491:6;7480:9;7476:22;7417:91;:::i;:::-;7399:109;;-1:-1;7399:109;-1:-1;;7545:2;7581:22;;1921:20;1946:30;1921:20;1946:30;:::i;:::-;7553:60;;;;7217:412;;;;;:::o;7636:427::-;;;7790:2;7778:9;7769:7;7765:23;7761:32;7758:2;;;-1:-1;;7796:12;7758:2;7854:17;7841:31;7892:18;7884:6;7881:30;7878:2;;;-1:-1;;7914:12;7878:2;7952:95;8039:7;8030:6;8019:9;8015:22;7952:95;:::i;:::-;7934:113;;;;-1:-1;7752:311;-1:-1;;;;7752:311::o;8070:1177::-;;;;;;;;;8324:3;8312:9;8303:7;8299:23;8295:33;8292:2;;;-1:-1;;8331:12;8292:2;8389:17;8376:31;8427:18;8419:6;8416:30;8413:2;;;-1:-1;;8449:12;8413:2;8487:95;8574:7;8565:6;8554:9;8550:22;8487:95;:::i;:::-;8469:113;;-1:-1;8469:113;-1:-1;;8619:2;8658:22;;72:20;97:33;72:20;97:33;:::i;:::-;8627:63;-1:-1;8727:2;8766:22;;3987:20;;-1:-1;8835:2;8874:22;;3987:20;;-1:-1;8962:51;9005:7;8943:3;8981:22;;8962:51;:::i;:::-;8952:61;;9050:3;9094:9;9090:22;2190:20;9059:63;;9159:3;9203:9;9199:22;2190:20;9168:63;;8286:961;;;;;;;;;;;:::o;9254:532::-;;;9415:2;9403:9;9394:7;9390:23;9386:32;9383:2;;;-1:-1;;9421:12;9383:2;9479:17;9466:31;9517:18;9509:6;9506:30;9503:2;;;-1:-1;;9539:12;9503:2;9630:22;;1222:4;1210:17;;1206:27;-1:-1;1196:2;;-1:-1;;1237:12;1196:2;1284:6;1271:20;1306:95;1321:79;1393:6;1321:79;:::i;:::-;1306:95;:::i;:::-;1407:16;1443:6;1436:5;1429:21;1473:4;;1490:3;1486:14;1479:21;;1473:4;1465:6;1461:17;1595:3;1473:4;;1579:6;1575:17;1465:6;1566:27;;1563:36;1560:2;;;-1:-1;;1602:12;1560:2;-1:-1;1628:10;;1622:221;1647:6;1644:1;1641:13;1622:221;;;1727:52;1775:3;1763:10;1727:52;:::i;:::-;1715:65;;1669:1;1662:9;;;;;1794:14;;;;1822;;1622:221;;;1626:14;9559:103;;;9717:53;9762:7;1473:4;9742:9;9738:22;9717:53;:::i;:::-;9707:63;;;;;;;9377:409;;;;;:::o;9793:257::-;;9905:2;9893:9;9884:7;9880:23;9876:32;9873:2;;;-1:-1;;9911:12;9873:2;2069:6;2063:13;2081:30;2105:5;2081:30;:::i;10057:263::-;;10172:2;10160:9;10151:7;10147:23;10143:32;10140:2;;;-1:-1;;10178:12;10140:2;-1:-1;2338:13;;10134:186;-1:-1;10134:186::o;10605:396::-;;;10741:2;10729:9;10720:7;10716:23;10712:32;10709:2;;;-1:-1;;10747:12;11008:521;;;;11161:2;11149:9;11140:7;11136:23;11132:32;11129:2;;;-1:-1;;11167:12;11129:2;2854:6;2841:20;2866:48;2908:5;2866:48;:::i;:::-;11219:78;-1:-1;11334:2;11373:22;;72:20;97:33;72:20;97:33;:::i;:::-;11342:63;-1:-1;11442:2;11481:22;;72:20;97:33;72:20;97:33;:::i;11536:1147::-;;;;;;;;;11772:3;11760:9;11751:7;11747:23;11743:33;11740:2;;;-1:-1;;11779:12;11740:2;2854:6;2841:20;2866:48;2908:5;2866:48;:::i;:::-;11831:78;-1:-1;11946:2;11985:22;;72:20;97:33;72:20;97:33;:::i;:::-;11954:63;-1:-1;12054:2;12093:22;;72:20;97:33;72:20;97:33;:::i;:::-;12062:63;-1:-1;12162:2;12201:22;;3987:20;;-1:-1;12270:3;12310:22;;3987:20;;-1:-1;12398:51;12441:7;12379:3;12417:22;;12398:51;:::i;:::-;12388:61;;12486:3;12530:9;12526:22;2190:20;12495:63;;12595:3;12639:9;12635:22;2190:20;12604:63;;11734:949;;;;;;;;;;;:::o;12690:1021::-;;;;;;;;12909:3;12897:9;12888:7;12884:23;12880:33;12877:2;;;-1:-1;;12916:12;12877:2;2854:6;2841:20;2866:48;2908:5;2866:48;:::i;:::-;12968:78;-1:-1;13083:2;13122:22;;72:20;97:33;72:20;97:33;:::i;:::-;13091:63;-1:-1;13191:2;13230:22;;3987:20;;-1:-1;13299:2;13338:22;;3987:20;;-1:-1;13407:3;13445:22;;4263:20;60540:4;60529:16;;63647:33;;63637:2;;-1:-1;;63684:12;63637:2;12871:840;;;;-1:-1;12871:840;;;;13416:61;13514:3;13554:22;;2190:20;;-1:-1;13623:3;13663:22;;;2190:20;;12871:840;-1:-1;;12871:840::o;15285:801::-;;;;;;15489:3;15477:9;15468:7;15464:23;15460:33;15457:2;;;-1:-1;;15496:12;15457:2;3380:6;3367:20;3392:63;3449:5;3392:63;:::i;:::-;15548:93;-1:-1;15678:2;15717:22;;72:20;97:33;72:20;97:33;:::i;:::-;15686:63;-1:-1;15786:2;15825:22;;3987:20;;-1:-1;15922:2;15907:18;;15894:32;15946:18;15935:30;;;15932:2;;;-1:-1;;15968:12;15932:2;16053:6;16042:9;16038:22;;;2529:3;2522:4;2514:6;2510:17;2506:27;2496:2;;-1:-1;;2537:12;2496:2;2580:6;2567:20;15946:18;2599:6;2596:30;2593:2;;;-1:-1;;2629:12;2593:2;2724:3;15678:2;2704:17;2665:6;2690:32;;2687:41;2684:2;;;-1:-1;;2731:12;2684:2;15451:635;;;;-1:-1;15451:635;;-1:-1;15678:2;2661:17;;15988:82;15451:635;-1:-1;;;15451:635::o;16093:362::-;;16218:2;16206:9;16197:7;16193:23;16189:32;16186:2;;;-1:-1;;16224:12;16186:2;16275:17;16269:24;16313:18;;16305:6;16302:30;16299:2;;;-1:-1;;16335:12;16299:2;16422:6;16411:9;16407:22;;;3581:3;3574:4;3566:6;3562:17;3558:27;3548:2;;-1:-1;;3589:12;3548:2;3629:6;3623:13;16313:18;56379:6;56376:30;56373:2;;;-1:-1;;56409:12;56373:2;3651:65;-1:-1;56463:17;;-1:-1;;56459:33;16218:2;56540:15;3651:65;:::i;:::-;3642:74;;3736:6;3729:5;3722:21;3840:3;16218:2;3831:6;3764;3822:16;;3819:25;3816:2;;;-1:-1;;3847:12;3816:2;3867:39;3899:6;16218:2;3798:5;3794:16;16218:2;3764:6;3760:17;3867:39;:::i;:::-;-1:-1;16355:84;16180:275;-1:-1;;;;16180:275::o;16462:241::-;;16566:2;16554:9;16545:7;16541:23;16537:32;16534:2;;;-1:-1;;16572:12;16534:2;-1:-1;3987:20;;16528:175;-1:-1;16528:175::o;16980:366::-;;;17101:2;17089:9;17080:7;17076:23;17072:32;17069:2;;;-1:-1;;17107:12;17069:2;4000:6;3987:20;17159:63;;17259:2;17302:9;17298:22;72:20;97:33;124:5;97:33;:::i;21828:323::-;;21960:5;57167:12;58274:6;58269:3;58262:19;22043:52;22088:6;58311:4;58306:3;58302:14;58311:4;22069:5;22065:16;22043:52;:::i;:::-;56482:9;62407:14;-1:-1;;62403:28;22107:39;;;;58311:4;22107:39;;21908:243;-1:-1;;21908:243::o;33220:291::-;;61909:6;61904:3;61899;61886:30;61947:16;;61940:27;;;61947:16;33364:147;-1:-1;33364:147::o;33518:271::-;;22318:5;57167:12;22429:52;22474:6;22469:3;22462:4;22455:5;22451:16;22429:52;:::i;:::-;22493:16;;;;;33652:137;-1:-1;;33652:137::o;33796:703::-;;22318:5;57167:12;22429:52;22474:6;22469:3;22462:4;22455:5;22451:16;22429:52;:::i;:::-;-1:-1;;;22493:16;;;32237:25;;;57167:12;;22429:52;57167:12;32222:1;32281:11;;22462:4;22451:16;;22429:52;:::i;:::-;22493:16;32222:1;22493:16;;34081:418;-1:-1;;;;34081:418::o;34506:659::-;-1:-1;;;25438:87;;25423:1;25544:11;;20951:37;;;;35017:12;;;20951:37;35128:12;;;34751:414::o;35172:222::-;-1:-1;;;;;60324:54;;;;18153:37;;35299:2;35284:18;;35270:124::o;35401:349::-;-1:-1;;;;;60324:54;;;18012:58;;60324:54;;35736:2;35721:18;;18153:37;35564:2;35549:18;;35535:215::o;35757:788::-;-1:-1;;;;;60324:54;;;18012:58;;60324:54;;36205:2;36190:18;;18153:37;36288:2;36273:18;;20951:37;;;36371:2;36356:18;;20951:37;;;-1:-1;36408:3;36393:19;;36386:49;;;36017:19;;58262;;;-1:-1;58262:19;61904:3;58302:14;;;61886:30;61947:16;;;58302:14;61947:16;;;61940:27;;;;56482:9;62407:14;;;-1:-1;;62403:28;21434:39;;;36003:542;-1:-1;;;;;36003:542::o;36892:444::-;-1:-1;;;;;60324:54;;;18153:37;;60324:54;;;;37239:2;37224:18;;18153:37;37322:2;37307:18;;20951:37;;;;37075:2;37060:18;;37046:290::o;37343:884::-;-1:-1;;;;;60324:54;;;18153:37;;60324:54;;;;37799:2;37784:18;;18153:37;37882:2;37867:18;;20951:37;;;;37965:2;37950:18;;20951:37;;;;60540:4;60529:16;38044:3;38029:19;;33173:35;-1:-1;38113:19;;20951:37;38212:3;38197:19;;20951:37;;;;37634:3;37619:19;;37605:622::o;38234:333::-;-1:-1;;;;;60324:54;;;;18153:37;;38553:2;38538:18;;20951:37;38389:2;38374:18;;38360:207::o;38574:653::-;38841:2;38855:47;;;57167:12;;38826:18;;;58262:19;;;38574:653;;58311:4;;58302:14;;;;56684;;;38574:653;18620:251;18645:6;18642:1;18639:13;18620:251;;;18706:13;;59685;59678:21;20723:34;;17495:14;;;;57863;;;;18667:1;18660:9;18620:251;;;18624:14;;;39066:9;39060:4;39056:20;58311:4;39040:9;39036:18;39029:48;39091:126;19148:5;57167:12;19167:95;19255:6;19250:3;19167:95;:::i;:::-;19160:102;;;;;58311:4;19319:6;19315:17;19310:3;19306:27;58311:4;19413:5;56684:14;-1:-1;19452:357;19477:6;19474:1;19471:13;19452:357;;;19539:9;19533:4;19529:20;19524:3;19517:33;17643:64;17703:3;19584:6;19578:13;17643:64;:::i;:::-;19788:14;;;;19598:90;-1:-1;57863:14;;;;18667:1;19492:9;19452:357;;;-1:-1;39083:134;;38812:415;-1:-1;;;;;;;;;38812:415::o;39234:400::-;39426:2;39440:47;;;57167:12;;39411:18;;;58262:19;;;39234:400;;39426:2;56684:14;;;;58302;;;;39234:400;20348:290;20373:6;20370:1;20367:13;20348:290;;;20434:13;;-1:-1;;;;;60324:54;22597:65;;57863:14;;;;17905;;;;-1:-1;20388:9;20348:290;;;-1:-1;39493:131;;39397:237;-1:-1;;;;;;39397:237::o;39641:210::-;59685:13;;59678:21;20723:34;;39762:2;39747:18;;39733:118::o;39858:222::-;20951:37;;;39985:2;39970:18;;39956:124::o;40087:780::-;20951:37;;;-1:-1;;;;;60324:54;;;40519:2;40504:18;;18153:37;60324:54;;;;40602:2;40587:18;;18153:37;40685:2;40670:18;;20951:37;40768:3;40753:19;;20951:37;;;;-1:-1;40837:19;;20951:37;40354:3;40339:19;;40325:542::o;40874:668::-;20951:37;;;41278:2;41263:18;;20951:37;;;;41361:2;41346:18;;20951:37;;;;41444:2;41429:18;;20951:37;-1:-1;;;;;60324:54;41527:3;41512:19;;18153:37;-1:-1;41098:19;;41084:458::o;41549:548::-;20951:37;;;60540:4;60529:16;;;;41917:2;41902:18;;33173:35;42000:2;41985:18;;20951:37;42083:2;42068:18;;20951:37;41756:3;41741:19;;41727:370::o;42640:310::-;;42787:2;42808:17;42801:47;42862:78;42787:2;42776:9;42772:18;42926:6;42862:78;:::i;42957:416::-;43157:2;43171:47;;;23964:2;43142:18;;;58262:19;24000:26;58302:14;;;23980:47;24046:12;;;43128:245::o;43380:416::-;43580:2;43594:47;;;24297:2;43565:18;;;58262:19;24333:34;58302:14;;;24313:55;-1:-1;;;24388:12;;;24381:27;24427:12;;;43551:245::o;43803:416::-;44003:2;44017:47;;;24678:2;43988:18;;;58262:19;-1:-1;;;58302:14;;;24694:43;-1:-1;24756:12;;43974:245::o;44226:416::-;44426:2;44440:47;;;25007:2;44411:18;;;58262:19;25043:34;58302:14;;;25023:55;-1:-1;;;25098:12;;;25091:26;25136:12;;;44397:245::o;44649:416::-;44849:2;44863:47;;;25794:2;44834:18;;;58262:19;25830:29;58302:14;;;25810:50;25879:12;;;44820:245::o;45072:416::-;45272:2;45286:47;;;26130:2;45257:18;;;58262:19;26166:31;58302:14;;;26146:52;26217:12;;;45243:245::o;45495:416::-;45695:2;45709:47;;;26468:2;45680:18;;;58262:19;26504:32;58302:14;;;26484:53;26556:12;;;45666:245::o;45918:416::-;46118:2;46132:47;;;26807:2;46103:18;;;58262:19;26843:34;58302:14;;;26823:55;-1:-1;;;26898:12;;;26891:26;26936:12;;;46089:245::o;46764:416::-;46964:2;46978:47;;;27571:2;46949:18;;;58262:19;27607:28;58302:14;;;27587:49;27655:12;;;46935:245::o;47187:416::-;47387:2;47401:47;;;27906:2;47372:18;;;58262:19;-1:-1;;;58302:14;;;27922:34;27975:12;;;47358:245::o;47610:416::-;47810:2;47824:47;;;28226:2;47795:18;;;58262:19;28262:34;58302:14;;;28242:55;-1:-1;;;28317:12;;;28310:26;28355:12;;;47781:245::o;48033:416::-;48233:2;48247:47;;;28606:2;48218:18;;;58262:19;28642:34;58302:14;;;28622:55;-1:-1;;;28697:12;;;28690:25;28734:12;;;48204:245::o;48456:416::-;48656:2;48670:47;;;28985:2;48641:18;;;58262:19;29021:32;58302:14;;;29001:53;29073:12;;;48627:245::o;48879:416::-;49079:2;49093:47;;;29324:2;49064:18;;;58262:19;29360:33;58302:14;;;29340:54;29413:12;;;49050:245::o;49302:416::-;49502:2;49516:47;;;29664:2;49487:18;;;58262:19;-1:-1;;;58302:14;;;29680:40;29739:12;;;49473:245::o;49725:416::-;49925:2;49939:47;;;29990:2;49910:18;;;58262:19;30026:34;58302:14;;;30006:55;-1:-1;;;30081:12;;;30074:25;30118:12;;;49896:245::o;50148:416::-;50348:2;50362:47;;;30369:2;50333:18;;;58262:19;30405:34;58302:14;;;30385:55;-1:-1;;;30460:12;;;30453:29;30501:12;;;50319:245::o;50571:416::-;50771:2;50785:47;;;30752:2;50756:18;;;58262:19;-1:-1;;;58302:14;;;30768:40;30827:12;;;50742:245::o;50994:416::-;51194:2;51208:47;;;31078:2;51179:18;;;58262:19;31114:34;58302:14;;;31094:55;-1:-1;;;31169:12;;;31162:28;31209:12;;;51165:245::o;51417:416::-;51617:2;51631:47;;;31460:2;51602:18;;;58262:19;31496:31;58302:14;;;31476:52;31547:12;;;51588:245::o;51840:416::-;52040:2;52054:47;;;31798:2;52025:18;;;58262:19;31834:34;58302:14;;;31814:55;-1:-1;;;31889:12;;;31882:34;31935:12;;;52011:245::o;52263:416::-;52463:2;52477:47;;;32531:2;52448:18;;;58262:19;32567:33;58302:14;;;32547:54;32620:12;;;52434:245::o;52686:416::-;52886:2;52900:47;;;32871:2;52871:18;;;58262:19;32907:33;58302:14;;;32887:54;32960:12;;;52857:245::o;53338:333::-;20951:37;;;-1:-1;;;;;60324:54;53657:2;53642:18;;18153:37;53493:2;53478:18;;53464:207::o;53678:444::-;20951:37;;;-1:-1;;;;;60324:54;;;54025:2;54010:18;;18153:37;60324:54;54108:2;54093:18;;18153:37;53861:2;53846:18;;53832:290::o;54129:333::-;20951:37;;;54448:2;54433:18;;20951:37;54284:2;54269:18;;54255:207::o;54469:444::-;20951:37;;;54816:2;54801:18;;20951:37;;;;-1:-1;;;;;60324:54;54899:2;54884:18;;18153:37;54652:2;54637:18;;54623:290::o;54920:214::-;60540:4;60529:16;;;;33173:35;;55043:2;55028:18;;55014:120::o;55141:506::-;;;55276:11;55263:25;55327:48;;55351:8;55335:14;55331:29;55327:48;55307:18;55303:73;55293:2;;-1:-1;;55380:12;55293:2;55407:33;;55461:18;;;-1:-1;55499:18;55488:30;;55485:2;;;-1:-1;;55521:12;55485:2;55366:4;55549:13;;-1:-1;55335:14;55581:38;;;55571:49;;55568:2;;;55633:1;;55623:12;55654:256;55716:2;55710:9;55742:17;;;55817:18;55802:34;;55838:22;;;55799:62;55796:2;;;55874:1;;55864:12;55796:2;55716;55883:22;55694:216;;-1:-1;55694:216::o;55917:319::-;;56091:18;56083:6;56080:30;56077:2;;;-1:-1;;56113:12;56077:2;-1:-1;56158:4;56146:17;;;56211:15;;56014:222::o;61982:268::-;62047:1;62054:101;62068:6;62065:1;62062:13;62054:101;;;62135:11;;;62129:18;62116:11;;;62109:39;62090:2;62083:10;62054:101;;;62170:6;62167:1;62164:13;62161:2;;;-1:-1;;62047:1;62217:16;;62210:27;62031:219::o;62444:117::-;-1:-1;;;;;60324:54;;62503:35;;62493:2;;62552:1;;62542:12;62568:111;62649:5;59685:13;59678:21;62627:5;62624:32;62614:2;;62670:1;;62660:12
Swarm Source
ipfs://e52166055dbdd56e20c3788a72557bae7907d6c913fc2f2ef4c9335b008b8972
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.