Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 10970937 | 1369 days ago | IN | Create: xSNX | 0 ETH | 0.46617381 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
xSNX
Compiler Version
v0.5.15+commit.6a57276f
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-10-01 */ // File: @openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/upgrades/contracts/Initializable.sol pragma solidity >=0.4.24 <0.7.0; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; } // File: @openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context is Initializable { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be aplied to your functions to restrict their use to * the owner. */ contract Ownable is Initializable, Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function initialize(address sender) public initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * > Note: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; } // File: @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.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 {ERC20Mintable}. * * 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 Initializable, Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view 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 returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public 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 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 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 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 { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _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 { require(account != address(0), "ERC20: mint to the zero address"); _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 { require(account != address(0), "ERC20: burn from the zero address"); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal { 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 Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } uint256[50] private ______gap; } // File: @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20Detailed.sol pragma solidity ^0.5.0; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is Initializable, IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ function initialize(string memory name, string memory symbol, uint8 decimals) public initializer { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } uint256[50] private ______gap; } // File: synthetix/contracts/interfaces/ISynth.sol pragma solidity >=0.4.24; interface ISynth { // Views function currencyKey() external view returns (bytes32); function transferableSynths(address account) external view returns (uint); // Mutative functions function transferAndSettle(address to, uint value) external returns (bool); function transferFromAndSettle( address from, address to, uint value ) external returns (bool); // Restricted: used internally to Synthetix function burn(address account, uint amount) external; function issue(address account, uint amount) external; } // File: synthetix/contracts/interfaces/ISynthetix.sol pragma solidity >=0.4.24; interface ISynthetix { // Views function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid); function availableCurrencyKeys() external view returns (bytes32[] memory); function availableSynthCount() external view returns (uint); function availableSynths(uint index) external view returns (ISynth); function collateral(address account) external view returns (uint); function collateralisationRatio(address issuer) external view returns (uint); function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint); function isWaitingPeriod(bytes32 currencyKey) external view returns (bool); function maxIssuableSynths(address issuer) external view returns (uint maxIssuable); function remainingIssuableSynths(address issuer) external view returns ( uint maxIssuable, uint alreadyIssued, uint totalSystemDebt ); function synths(bytes32 currencyKey) external view returns (ISynth); function synthsByAddress(address synthAddress) external view returns (bytes32); function totalIssuedSynths(bytes32 currencyKey) external view returns (uint); function totalIssuedSynthsExcludeEtherCollateral(bytes32 currencyKey) external view returns (uint); function transferableSynthetix(address account) external view returns (uint transferable); // Mutative Functions function burnSynths(uint amount) external; function burnSynthsOnBehalf(address burnForAddress, uint amount) external; function burnSynthsToTarget() external; function burnSynthsToTargetOnBehalf(address burnForAddress) external; function exchange( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external returns (uint amountReceived); function exchangeOnBehalf( address exchangeForAddress, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external returns (uint amountReceived); function exchangeWithTracking( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address originator, bytes32 trackingCode ) external returns (uint amountReceived); function exchangeOnBehalfWithTracking( address exchangeForAddress, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address originator, bytes32 trackingCode ) external returns (uint amountReceived); function issueMaxSynths() external; function issueMaxSynthsOnBehalf(address issueForAddress) external; function issueSynths(uint amount) external; function issueSynthsOnBehalf(address issueForAddress, uint amount) external; function mint() external returns (bool); function settle(bytes32 currencyKey) external returns ( uint reclaimed, uint refunded, uint numEntries ); function liquidateDelinquentAccount(address account, uint susdAmount) external returns (bool); } // File: synthetix/contracts/interfaces/IRewardEscrow.sol pragma solidity >=0.4.24; interface IRewardEscrow { // Views function balanceOf(address account) external view returns (uint); function numVestingEntries(address account) external view returns (uint); function totalEscrowedAccountBalance(address account) external view returns (uint); function totalVestedAccountBalance(address account) external view returns (uint); // Mutative functions function appendVestingEntry(address account, uint quantity) external; function vest() external; } // File: synthetix/contracts/interfaces/IExchangeRates.sol pragma solidity >=0.4.24; // https://docs.synthetix.io/contracts/source/interfaces/IExchangeRates interface IExchangeRates { // Structs struct RateAndUpdatedTime { uint216 rate; uint40 time; } struct InversePricing { uint entryPoint; uint upperLimit; uint lowerLimit; bool frozenAtUpperLimit; bool frozenAtLowerLimit; } // Views function aggregators(bytes32 currencyKey) external view returns (address); function aggregatorWarningFlags() external view returns (address); function anyRateIsInvalid(bytes32[] calldata currencyKeys) external view returns (bool); function canFreezeRate(bytes32 currencyKey) external view returns (bool); function currentRoundForRate(bytes32 currencyKey) external view returns (uint); function currenciesUsingAggregator(address aggregator) external view returns (bytes32[] memory); function effectiveValue( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external view returns (uint value); function effectiveValueAndRates( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external view returns ( uint value, uint sourceRate, uint destinationRate ); function effectiveValueAtRound( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, uint roundIdForSrc, uint roundIdForDest ) external view returns (uint value); function getCurrentRoundId(bytes32 currencyKey) external view returns (uint); function getLastRoundIdBeforeElapsedSecs( bytes32 currencyKey, uint startingRoundId, uint startingTimestamp, uint timediff ) external view returns (uint); function inversePricing(bytes32 currencyKey) external view returns ( uint entryPoint, uint upperLimit, uint lowerLimit, bool frozenAtUpperLimit, bool frozenAtLowerLimit ); function lastRateUpdateTimes(bytes32 currencyKey) external view returns (uint256); function oracle() external view returns (address); function rateAndTimestampAtRound(bytes32 currencyKey, uint roundId) external view returns (uint rate, uint time); function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time); function rateForCurrency(bytes32 currencyKey) external view returns (uint); function rateIsFlagged(bytes32 currencyKey) external view returns (bool); function rateIsFrozen(bytes32 currencyKey) external view returns (bool); function rateIsInvalid(bytes32 currencyKey) external view returns (bool); function rateIsStale(bytes32 currencyKey) external view returns (bool); function rateStalePeriod() external view returns (uint); function ratesAndUpdatedTimeForCurrencyLastNRounds(bytes32 currencyKey, uint numRounds) external view returns (uint[] memory rates, uint[] memory times); function ratesAndInvalidForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory rates, bool anyRateInvalid); function ratesForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory); // Mutative functions function freezeRate(bytes32 currencyKey) external; } // File: synthetix/contracts/interfaces/ISynthetixState.sol pragma solidity >=0.4.24; interface ISynthetixState { // Views function debtLedger(uint index) external view returns (uint); function issuanceData(address account) external view returns (uint initialDebtOwnership, uint debtEntryIndex); function debtLedgerLength() external view returns (uint); function hasIssued(address account) external view returns (bool); function lastDebtLedgerEntry() external view returns (uint); // Mutative functions function incrementTotalIssuerCount() external; function decrementTotalIssuerCount() external; function setCurrentIssuanceData(address account, uint initialDebtOwnership) external; function appendDebtLedgerValue(uint value) external; function clearIssuanceData(address account) external; } // File: synthetix/contracts/interfaces/IAddressResolver.sol pragma solidity >=0.4.24; interface IAddressResolver { function getAddress(bytes32 name) external view returns (address); function getSynth(bytes32 key) external view returns (address); function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address); } // File: contracts/interface/ISystemSettings.sol pragma solidity 0.5.15; interface ISystemSettings { function issuanceRatio() external view returns(uint); } // File: contracts/interface/ICurveFi.sol pragma solidity 0.5.15; interface ICurveFi { function exchange( int128 i, int128 j, uint256 dx, uint256 min_dy ) external; function exchange_underlying( int128 i, int128 j, uint256 dx, uint256 min_dy ) external; function get_dx_underlying( int128 i, int128 j, uint256 dy ) external view returns (uint256); function get_dy_underlying( int128 i, int128 j, uint256 dx ) external view returns (uint256); function get_dx( int128 i, int128 j, uint256 dy ) external view returns (uint256); function get_dy( int128 i, int128 j, uint256 dx ) external view returns (uint256); function get_virtual_price() external view returns (uint256); } // File: contracts/interface/ISetToken.sol pragma solidity 0.5.15; interface ISetToken { function unitShares() external view returns(uint); function naturalUnit() external view returns(uint); function currentSet() external view returns(address); // function getUnits() external view returns (uint256[] memory); } // File: contracts/interface/IKyberNetworkProxy.sol pragma solidity 0.5.15; contract IKyberNetworkProxy { function getExpectedRate(ERC20 src, ERC20 dest, uint srcQty) external view returns (uint expectedRate, uint slippageRate); function swapEtherToToken(ERC20 token, uint minConversionRate) external payable returns(uint); function swapTokenToEther(ERC20 token, uint tokenQty, uint minRate) external payable returns(uint); function swapTokenToToken(ERC20 src, uint srcAmount, ERC20 dest, uint minConversionRate) public returns(uint); } // File: contracts/interface/ISetAssetBaseCollateral.sol pragma solidity 0.5.15; interface ISetAssetBaseCollateral { function getComponents() external view returns(address[] memory); function naturalUnit() external view returns(uint); function getUnits() external view returns (uint256[] memory); } // File: contracts/TradeAccounting.sol pragma solidity 0.5.15; /* xSNX Target Allocation (assuming 800% C-RATIO) ---------------------- Allocation | NAV | % NAV -------------------------------------- 800 SNX @ $1/token | $800 | 100% 100 sUSD Debt | ($100) | (12.5%) 75 USD equiv Set | $75 | 9.375% 25 USD equiv ETH | $25 | 3.125% -------------------------------------- Total $800 | 100% */ /* Conditions for `isRebalanceTowardsHedgeRequired` to return true Assuming 5% rebalance threshold Allocation | NAV | % NAV -------------------------------------- 800 SNX @ $1/token | $800 | 100.63% 105 sUSD Debt | ($105) | (13.21%) 75 USD equiv Set | $75 | 9.43% 25 USD equiv ETH | $25 | 3.14% -------------------------------------- Total $795 | 100% Debt value | $105 Hedge Assets | $100 ------------------------- Debt/hedge ratio | 105% */ /* Conditions for `isRebalanceTowardsSnxRequired` to return true Assuming 5% rebalance threshold Allocation | NAV | % NAV -------------------------------------- 800 SNX @ $1/token | $800 | 99.37% 100 sUSD Debt | ($100) | (12.42%) 75 USD equiv Set | $75 | 9.31% 30 USD equiv ETH | $30 | 3.72% -------------------------------------- Total $805 | 100% Hedge Assets | $105 Debt value | $100 ------------------------- Hedge/debt ratio | 105% */ contract TradeAccounting is Ownable { using SafeMath for uint256; uint256 private constant TEN = 10; uint256 private constant DEC_18 = 1e18; uint256 private constant PERCENT = 100; uint256 private constant ETH_TARGET = 4; // targets 1/4th of hedge portfolio uint256 private constant SLIPPAGE_RATE = 99; uint256 private constant MAX_UINT = 2**256 - 1; uint256 private constant RATE_STALE_TIME = 28800; // 8 hours uint256 private constant REBALANCE_THRESHOLD = 105; // 5% uint256 private constant INITIAL_SUPPLY_MULTIPLIER = 10; int128 usdcIndex; int128 susdIndex; ICurveFi private curveFi; ISynthetixState private synthetixState; IAddressResolver private addressResolver; IKyberNetworkProxy private kyberNetworkProxy; address private xSNXAdminInstance; address private addressValidator; address private setAddress; address private susdAddress; address private usdcAddress; address private nextCurveAddress; bytes32 constant snx = "SNX"; bytes32 constant susd = "sUSD"; bytes32 constant seth = "sETH"; bytes32[2] synthSymbols; address[2] setComponentAddresses; bytes32 constant rewardEscrowName = "RewardEscrow"; bytes32 constant exchangeRatesName = "ExchangeRates"; bytes32 constant synthetixName = "Synthetix"; bytes32 constant systemSettingsName = "SystemSettings"; function initialize( address _setAddress, address _kyberProxyAddress, address _addressResolver, address _susdAddress, address _usdcAddress, address _addressValidator, bytes32[2] memory _synthSymbols, address[2] memory _setComponentAddresses, address _ownerAddress ) public initializer { Ownable.initialize(_ownerAddress); setAddress = _setAddress; kyberNetworkProxy = IKyberNetworkProxy(_kyberProxyAddress); addressResolver = IAddressResolver(_addressResolver); susdAddress = _susdAddress; usdcAddress = _usdcAddress; addressValidator = _addressValidator; synthSymbols = _synthSymbols; setComponentAddresses = _setComponentAddresses; } modifier onlyXSNXAdmin { require( msg.sender == xSNXAdminInstance, "Only xSNXAdmin contract can call" ); _; } /* ========================================================================================= */ /* Kyber/Curve */ /* ========================================================================================= */ /* * @dev Function that processes all token to token exchanges, * sometimes via Kyber and sometimes via a combination of Kyber & Curve * @dev Only callable by xSNXAdmin contract */ function swapTokenToToken( address fromToken, uint256 amount, address toToken, uint256 minKyberRate, uint256 minCurveReturn ) public onlyXSNXAdmin { if (fromToken == susdAddress) { _exchangeUnderlying(susdIndex, usdcIndex, amount, minCurveReturn); if (toToken != usdcAddress) { uint256 usdcBal = getUsdcBalance(); _swapTokenToToken(usdcAddress, usdcBal, toToken, minKyberRate); } } else if (toToken == susdAddress) { if (fromToken != usdcAddress) { _swapTokenToToken(fromToken, amount, usdcAddress, minKyberRate); } uint256 usdcBal = getUsdcBalance(); _exchangeUnderlying(usdcIndex, susdIndex, usdcBal, minCurveReturn); } else { _swapTokenToToken(fromToken, amount, toToken, minKyberRate); } IERC20(toToken).transfer( xSNXAdminInstance, IERC20(toToken).balanceOf(address(this)) ); } function _swapTokenToToken( address _fromToken, uint256 _amount, address _toToken, uint256 _minKyberRate ) private { kyberNetworkProxy.swapTokenToToken( ERC20(_fromToken), _amount, ERC20(_toToken), _minKyberRate ); } /* * @dev Function that processes all token to ETH exchanges, * sometimes via Kyber and sometimes via a combination of Kyber & Curve * @dev Only callable by xSNXAdmin contract */ function swapTokenToEther( address fromToken, uint256 amount, uint256 minKyberRate, uint256 minCurveReturn ) public onlyXSNXAdmin { if (fromToken == susdAddress) { _exchangeUnderlying(susdIndex, usdcIndex, amount, minCurveReturn); uint256 usdcBal = getUsdcBalance(); _swapTokenToEther(usdcAddress, usdcBal, minKyberRate); } else { _swapTokenToEther(fromToken, amount, minKyberRate); } uint256 ethBal = address(this).balance; (bool success, ) = msg.sender.call.value(ethBal)(""); require(success, "Transfer failed"); } function _swapTokenToEther( address _fromToken, uint256 _amount, uint256 _minKyberRate ) private { kyberNetworkProxy.swapTokenToEther( ERC20(_fromToken), _amount, _minKyberRate ); } function _exchangeUnderlying( int128 _inputIndex, int128 _outputIndex, uint256 _amount, uint256 _minReturn ) private { curveFi.exchange_underlying( _inputIndex, _outputIndex, _amount, _minReturn ); } function getUsdcBalance() internal view returns (uint256) { return IERC20(usdcAddress).balanceOf(address(this)); } /* ========================================================================================= */ /* NAV */ /* ========================================================================================= */ function getEthBalance() public view returns (uint256) { return address(xSNXAdminInstance).balance; } /* * @dev Helper function for `xSNX.burn` that outputs NAV * redemption value in ETH terms * @param totalSupply: xSNX.totalSupply() * @param tokensToRedeem: xSNX to burn */ function calculateRedemptionValue( uint256 totalSupply, uint256 tokensToRedeem ) public view returns (uint256 valueToRedeem) { uint256 snxBalanceOwned = getSnxBalanceOwned(); uint256 contractDebtValue = getContractDebtValue(); uint256 pricePerToken = calculateRedeemTokenPrice( totalSupply, snxBalanceOwned, contractDebtValue ); valueToRedeem = pricePerToken.mul(tokensToRedeem).div(DEC_18); } /* * @dev Helper function for `xSNX.mint` that * 1) determines whether ETH contribution should be maintained in ETH or exchanged for SNX and * 2) outputs the `nonSnxAssetValue` value to be used in NAV calculation * @param totalSupply: xSNX.totalSupply() */ function getMintWithEthUtils(uint256 totalSupply) public view returns (bool allocateToEth, uint256 nonSnxAssetValue) { uint256 setHoldingsInWei = getSetHoldingsValueInWei(); // called before eth transferred from xSNX to xSNXAdmin uint256 ethBalBefore = getEthBalance(); allocateToEth = shouldAllocateEthToEthReserve( setHoldingsInWei, ethBalBefore, totalSupply ); nonSnxAssetValue = setHoldingsInWei.add(ethBalBefore); } /* * @notice xSNX system targets 25% of hedge portfolio to be maintained in ETH * @dev Function produces binary yes allocate/no allocate decision point * determining whether ETH sent on xSNX.mint() is held or exchanged * @param setHoldingsInWei: value of Set portfolio in ETH terms * @param ethBalBefore: value of ETH reserve prior to tx * @param totalSupply: xSNX.totalSupply() */ function shouldAllocateEthToEthReserve( uint256 setHoldingsInWei, uint256 ethBalBefore, uint256 totalSupply ) public pure returns (bool allocateToEth) { if (totalSupply == 0) return false; if (ethBalBefore.mul(ETH_TARGET) < ethBalBefore.add(setHoldingsInWei)) { // ETH reserve is under target return true; } return false; } /* * @dev Helper function for calculateIssueTokenPrice * @dev Called indirectly by `xSNX.mint` and `xSNX.mintWithSnx` * @dev Calculates NAV of the fund, including value of escrowed SNX, in ETH terms * @param weiPerOneSnx: SNX price in ETH terms * @param snxBalanceBefore: SNX balance pre-mint * @param nonSnxAssetValue: NAV of non-SNX slice of fund */ function calculateNetAssetValueOnMint( uint256 weiPerOneSnx, uint256 snxBalanceBefore, uint256 nonSnxAssetValue ) internal view returns (uint256) { uint256 snxTokenValueInWei = snxBalanceBefore.mul(weiPerOneSnx).div( DEC_18 ); uint256 contractDebtValue = getContractDebtValue(); uint256 contractDebtValueInWei = calculateDebtValueInWei( contractDebtValue ); return snxTokenValueInWei.add(nonSnxAssetValue).sub( contractDebtValueInWei ); } /* * @dev Helper function for calculateRedeemTokenPrice * @dev Called indirectly by `xSNX.burn` * @dev Calculates NAV of the fund, excluding value of escrowed SNX, in ETH terms * @param weiPerOneSnx: SNX price in ETH terms * @param snxBalanceOwned: non-escrowed SNX balance * @param contractDebtValueInWei: sUSD debt balance of fund in ETH terms */ function calculateNetAssetValueOnRedeem( uint256 weiPerOneSnx, uint256 snxBalanceOwned, uint256 contractDebtValueInWei ) internal view returns (uint256) { uint256 snxTokenValueInWei = snxBalanceOwned.mul(weiPerOneSnx).div( DEC_18 ); uint256 nonSnxAssetValue = calculateNonSnxAssetValue(); return snxTokenValueInWei.add(nonSnxAssetValue).sub( contractDebtValueInWei ); } /* * @dev NAV value of non-SNX assets, computed in ETH terms */ function calculateNonSnxAssetValue() internal view returns (uint256) { return getSetHoldingsValueInWei().add(getEthBalance()); } /* * @dev SNX price in ETH terms, calculated for purposes of redemption NAV * @notice Return value discounted slightly to better represent liquidation price */ function getWeiPerOneSnxOnRedeem() internal view returns (uint256 weiPerOneSnx) { uint256 snxUsdPrice = getSnxPrice(); uint256 ethUsdPrice = getSynthPrice(seth); weiPerOneSnx = snxUsdPrice .mul(DEC_18) .div(ethUsdPrice) .mul(SLIPPAGE_RATE) // used to better represent liquidation price as volume scales .div(PERCENT); } /* * @dev Returns Synthetix synth symbol for asset currently held in TokenSet (e.g., sETH for WETH) * @notice xSNX contract complex only compatible with Sets that hold a single asset at a time */ function getActiveAssetSynthSymbol() internal view returns (bytes32 synthSymbol) { synthSymbol = getAssetCurrentlyActiveInSet() == setComponentAddresses[0] ? (synthSymbols[0]) : (synthSymbols[1]); } /* * @dev Returns SNX price in ETH terms, calculated for purposes of issuance NAV (when allocateToEth) */ function getWeiPerOneSnxOnMint() internal view returns (uint256) { uint256 snxUsd = getSynthPrice(snx); uint256 ethUsd = getSynthPrice(seth); return snxUsd.mul(DEC_18).div(ethUsd); } /* * @dev Single use function to define initial xSNX issuance */ function getInitialSupply() internal view returns (uint256) { return IERC20(addressResolver.getAddress(synthetixName)) .balanceOf(xSNXAdminInstance) .mul(INITIAL_SUPPLY_MULTIPLIER); } /* * @dev Helper function for `xSNX.mint` that calculates token issuance * @param snxBalanceBefore: SNX balance pre-mint * @param ethContributed: ETH payable on mint, less fees * @param nonSnxAssetValue: NAV of non-SNX slice of fund * @param totalSupply: xSNX.totalSupply() * @param allocateToEth: bool determining whether ETH payable is reserved in ETH or exchanged */ function calculateTokensToMintWithEth( uint256 snxBalanceBefore, uint256 ethContributed, uint256 nonSnxAssetValue, uint256 totalSupply, bool allocateToEth ) public view returns (uint256) { if (totalSupply == 0) { return getInitialSupply(); } uint256 weiPerOneSnx; if (allocateToEth) { weiPerOneSnx = getWeiPerOneSnxOnMint(); } else { uint256 snxBalanceAfter = getSnxBalance(); uint256 snxContributed = snxBalanceAfter.sub(snxBalanceBefore); weiPerOneSnx = ethContributed.mul(DEC_18).div(snxContributed); } uint256 pricePerToken = calculateIssueTokenPrice( weiPerOneSnx, snxBalanceBefore, nonSnxAssetValue, totalSupply ); return ethContributed.mul(DEC_18).div(pricePerToken); } /* * @dev Helper function for `xSNX.mintWithSnx` that calculates token issuance * @param snxBalanceBefore: SNX balance pre-mint * @param snxAddedToBalance: SNX contributed by mint * @param totalSupply: xSNX.totalSupply() */ function calculateTokensToMintWithSnx( uint256 snxBalanceBefore, uint256 snxAddedToBalance, uint256 totalSupply ) public view returns (uint256) { if (totalSupply == 0) { return getInitialSupply(); } uint256 weiPerOneSnx = getWeiPerOneSnxOnMint(); // need to derive snx contribution in eth terms for NAV calc uint256 proxyEthContribution = weiPerOneSnx.mul(snxAddedToBalance).div( DEC_18 ); uint256 nonSnxAssetValue = calculateNonSnxAssetValue(); uint256 pricePerToken = calculateIssueTokenPrice( weiPerOneSnx, snxBalanceBefore, nonSnxAssetValue, totalSupply ); return proxyEthContribution.mul(DEC_18).div(pricePerToken); } /* * @dev Called indirectly by `xSNX.mint` and `xSNX.mintWithSnx` * @dev Calculates token price on issuance, including value of escrowed SNX * @param weiPerOneSnx: SNX price in ETH terms * @param snxBalanceBefore: SNX balance pre-mint * @param nonSnxAssetValue: Non-SNX slice of fund * @param totalSupply: xSNX.totalSupply() */ function calculateIssueTokenPrice( uint256 weiPerOneSnx, uint256 snxBalanceBefore, uint256 nonSnxAssetValue, uint256 totalSupply ) public view returns (uint256 pricePerToken) { pricePerToken = calculateNetAssetValueOnMint( weiPerOneSnx, snxBalanceBefore, nonSnxAssetValue ) .mul(DEC_18) .div(totalSupply); } /* * @dev Called indirectly by `xSNX.burn` * @dev Calculates token price on redemption, excluding value of escrowed SNX * @param totalSupply: xSNX.totalSupply() * @param snxBalanceOwned: non-escrowed SNX balance * @param contractDebtValue: sUSD debt in USD terms */ function calculateRedeemTokenPrice( uint256 totalSupply, uint256 snxBalanceOwned, uint256 contractDebtValue ) public view returns (uint256 pricePerToken) { // SNX won't actually be sold (burns are only distributed in available ETH) but // this is a proxy for the return value of SNX that would be sold uint256 weiPerOneSnx = getWeiPerOneSnxOnRedeem(); uint256 debtValueInWei = calculateDebtValueInWei(contractDebtValue); pricePerToken = calculateNetAssetValueOnRedeem( weiPerOneSnx, snxBalanceOwned, debtValueInWei ) .mul(DEC_18) .div(totalSupply); } /* ========================================================================================= */ /* Set */ /* ========================================================================================= */ /* * @dev Balance of underlying asset "active" in Set (e.g., WETH or USDC) */ function getActiveSetAssetBalance() public view returns (uint256) { return IERC20(getAssetCurrentlyActiveInSet()).balanceOf(xSNXAdminInstance); } /* * @dev Calculates quantity of Set Token equivalent to quantity of underlying asset token * @notice rebalancingSetQuantity return value is reduced slightly to ensure successful execution * @param componentQuantity: balance of underlying Set asset, e.g., WETH */ function calculateSetQuantity(uint256 componentQuantity) public view returns (uint256 rebalancingSetQuantity) { uint256 baseSetNaturalUnit = getBaseSetNaturalUnit(); uint256 baseSetComponentUnits = getBaseSetComponentUnits(); uint256 baseSetIssuable = componentQuantity.mul(baseSetNaturalUnit).div( baseSetComponentUnits ); uint256 rebalancingSetNaturalUnit = getSetNaturalUnit(); uint256 unitShares = getSetUnitShares(); rebalancingSetQuantity = baseSetIssuable .mul(rebalancingSetNaturalUnit) .div(unitShares) .mul(99) // ensure sufficient balance in underlying asset .div(100) .div(rebalancingSetNaturalUnit) .mul(rebalancingSetNaturalUnit); } /* * @dev Calculates mintable quantity of Set Token given asset holdings */ function calculateSetIssuanceQuantity() public view returns (uint256 rebalancingSetIssuable) { uint256 componentQuantity = getActiveSetAssetBalance(); rebalancingSetIssuable = calculateSetQuantity(componentQuantity); } /* * @dev Calculates Set token to sell given sUSD burn requirements * @param totalSusdToBurn: sUSD to burn to fix ratio or unlock staked SNX */ function calculateSetRedemptionQuantity(uint256 totalSusdToBurn) public view returns (uint256 rebalancingSetRedeemable) { address currentSetAsset = getAssetCurrentlyActiveInSet(); bytes32 activeAssetSynthSymbol = getActiveAssetSynthSymbol(); uint256 synthUsd = getSynthPrice(activeAssetSynthSymbol); // expectedSetAssetRate = amount of current set asset needed to redeem for 1 sUSD uint256 expectedSetAssetRate = DEC_18.mul(DEC_18).div(synthUsd); uint256 setAssetCollateralToSell = expectedSetAssetRate .mul(totalSusdToBurn) .div(DEC_18) .mul(103) // err on the high side .div(PERCENT); uint256 decimals = (TEN**ERC20Detailed(currentSetAsset).decimals()); setAssetCollateralToSell = setAssetCollateralToSell.mul(decimals).div( DEC_18 ); rebalancingSetRedeemable = calculateSetQuantity( setAssetCollateralToSell ); } /* * @dev Calculates value of a single 1e18 Set unit in ETH terms */ function calculateEthValueOfOneSetUnit() internal view returns (uint256 ethValue) { uint256 unitShares = getSetUnitShares(); uint256 rebalancingSetNaturalUnit = getSetNaturalUnit(); uint256 baseSetRequired = DEC_18.mul(unitShares).div( rebalancingSetNaturalUnit ); uint256 unitsOfUnderlying = getBaseSetComponentUnits(); uint256 baseSetNaturalUnit = getBaseSetNaturalUnit(); uint256 componentRequired = baseSetRequired.mul(unitsOfUnderlying).div( baseSetNaturalUnit ); address currentSetAsset = getAssetCurrentlyActiveInSet(); uint256 decimals = (TEN**ERC20Detailed(currentSetAsset).decimals()); componentRequired = componentRequired.mul(DEC_18).div(decimals); bytes32 activeAssetSynthSymbol = getActiveAssetSynthSymbol(); uint256 synthUsd = getSynthPrice(activeAssetSynthSymbol); uint256 ethUsd = getSynthPrice(seth); ethValue = componentRequired.mul(synthUsd).div(ethUsd); } /* * @dev Calculates value of Set Holdings in ETH terms */ function getSetHoldingsValueInWei() public view returns (uint256 setValInWei) { uint256 setCollateralTokens = getSetCollateralTokens(); bytes32 synthSymbol = getActiveAssetSynthSymbol(); address currentSetAsset = getAssetCurrentlyActiveInSet(); uint256 synthUsd = getSynthPrice(synthSymbol); uint256 ethUsd = getSynthPrice(seth); uint256 decimals = (TEN**ERC20Detailed(currentSetAsset).decimals()); setCollateralTokens = setCollateralTokens.mul(DEC_18).div(decimals); setValInWei = setCollateralTokens.mul(synthUsd).div(ethUsd); } function getBaseSetNaturalUnit() internal view returns (uint256) { return getCurrentCollateralSet().naturalUnit(); } /* * @dev Outputs current active Set asset * @notice xSNX contracts complex only compatible with Sets that hold a single asset at a time */ function getAssetCurrentlyActiveInSet() public view returns (address) { address[] memory currentAllocation = getCurrentCollateralSet() .getComponents(); return currentAllocation[0]; } function getCurrentCollateralSet() internal view returns (ISetAssetBaseCollateral) { return ISetAssetBaseCollateral(getCurrentSet()); } function getCurrentSet() internal view returns (address) { return ISetToken(setAddress).currentSet(); } /* * @dev Returns the number of underlying tokens in the current Set asset * e.g., the contract's Set holdings are collateralized by 10.4 WETH */ function getSetCollateralTokens() internal view returns (uint256) { return getSetBalanceCollateral().mul(getBaseSetComponentUnits()).div( getBaseSetNaturalUnit() ); } function getSetBalanceCollateral() internal view returns (uint256) { uint256 unitShares = getSetUnitShares(); uint256 naturalUnit = getSetNaturalUnit(); return getContractSetBalance().mul(unitShares).div(naturalUnit); } function getSetUnitShares() internal view returns (uint256) { return ISetToken(setAddress).unitShares(); } function getSetNaturalUnit() internal view returns (uint256) { return ISetToken(setAddress).naturalUnit(); } function getContractSetBalance() internal view returns (uint256) { return IERC20(setAddress).balanceOf(xSNXAdminInstance); } function getBaseSetComponentUnits() internal view returns (uint256) { return ISetAssetBaseCollateral(getCurrentSet()).getUnits()[0]; } /* ========================================================================================= */ /* Synthetix */ /* ========================================================================================= */ function getSusdBalance() public view returns (uint256) { return IERC20(susdAddress).balanceOf(xSNXAdminInstance); } function getSnxBalance() public view returns (uint256) { return getSnxBalanceOwned().add(getSnxBalanceEscrowed()); } function getSnxBalanceOwned() internal view returns (uint256) { return IERC20(addressResolver.getAddress(synthetixName)).balanceOf( xSNXAdminInstance ); } function getSnxBalanceEscrowed() internal view returns (uint256) { return IRewardEscrow(addressResolver.getAddress(rewardEscrowName)) .balanceOf(xSNXAdminInstance); } function getContractEscrowedSnxValue() internal view returns (uint256) { return getSnxBalanceEscrowed().mul(getSnxPrice()).div(DEC_18); } function getContractOwnedSnxValue() internal view returns (uint256) { return getSnxBalanceOwned().mul(getSnxPrice()).div(DEC_18); } function getSnxPrice() internal view returns (uint256) { (uint256 rate, uint256 time) = IExchangeRates( addressResolver.getAddress(exchangeRatesName) ) .rateAndUpdatedTime(snx); require(time.add(RATE_STALE_TIME) > block.timestamp, "Rate stale"); return rate; } function getSynthPrice(bytes32 synth) internal view returns (uint256) { (uint256 rate, uint256 time) = IExchangeRates( addressResolver.getAddress(exchangeRatesName) ) .rateAndUpdatedTime(synth); if (synth != susd) { require(time.add(RATE_STALE_TIME) > block.timestamp, "Rate stale"); } return rate; } /* * @dev Converts sUSD debt value into ETH terms * @param debtValue: sUSD-denominated debt value */ function calculateDebtValueInWei(uint256 debtValue) internal view returns (uint256 debtBalanceInWei) { uint256 ethUsd = getSynthPrice(seth); debtBalanceInWei = debtValue.mul(DEC_18).div(ethUsd); } function getContractDebtValue() internal view returns (uint256) { return ISynthetix(addressResolver.getAddress(synthetixName)).debtBalanceOf( xSNXAdminInstance, susd ); } /* * @notice Returns inverse of target C-RATIO */ function getIssuanceRatio() internal view returns (uint256) { return ISystemSettings(addressResolver.getAddress(systemSettingsName)) .issuanceRatio(); } /* * @notice Returns NAV contribution of SNX holdings in USD terms */ function getContractSnxValue() internal view returns (uint256) { return getSnxBalance().mul(getSnxPrice()).div(DEC_18); } /* ========================================================================================= */ /* Burning sUSD */ /* ========================================================================================= */ /* * @dev Calculates sUSD to burn to restore C-RATIO * @param snxValueHeld: USD value of SNX * @param contractDebtValue: USD value of sUSD debt * @param issuanceRatio: Synthetix C-RATIO requirement */ function calculateSusdToBurnToFixRatio( uint256 snxValueHeld, uint256 contractDebtValue, uint256 issuanceRatio ) internal pure returns (uint256) { uint256 subtractor = issuanceRatio.mul(snxValueHeld).div(DEC_18); if (subtractor > contractDebtValue) return 0; return contractDebtValue.sub(subtractor); } /* * @dev Calculates sUSD to burn to restore C-RATIO */ function calculateSusdToBurnToFixRatioExternal() public view returns (uint256) { uint256 snxValueHeld = getContractSnxValue(); uint256 debtValue = getContractDebtValue(); uint256 issuanceRatio = getIssuanceRatio(); return calculateSusdToBurnToFixRatio( snxValueHeld, debtValue, issuanceRatio ); } /* * @dev Calculates sUSD to burn to eclipse value of escrowed SNX * @notice Synthetix system requires escrowed SNX to be "unlocked" first * @param issuanceRatio: Synthetix C-RATIO requirement */ function calculateSusdToBurnToEclipseEscrowed(uint256 issuanceRatio) public view returns (uint256) { uint256 escrowedSnxValue = getContractEscrowedSnxValue(); if (escrowedSnxValue == 0) return 0; return escrowedSnxValue.mul(issuanceRatio).div(DEC_18); } /* * @dev Helper function to calculate sUSD burn required for a potential redemption * @param tokensToRedeem: potential tokens to burn * @param totalSupply: xSNX.totalSupply() * @param contractDebtValue: sUSD debt value * @param issuanceRatio: Synthetix C-RATIO requirement */ function calculateSusdToBurnForRedemption( uint256 tokensToRedeem, uint256 totalSupply, uint256 contractDebtValue, uint256 issuanceRatio ) public view returns (uint256 susdToBurn) { uint256 nonEscrowedSnxValue = getContractOwnedSnxValue(); uint256 lockedSnxValue = contractDebtValue.mul(DEC_18).div( issuanceRatio ); uint256 valueOfSnxToSell = nonEscrowedSnxValue.mul(tokensToRedeem).div( totalSupply ); susdToBurn = ( lockedSnxValue.add(valueOfSnxToSell).sub(nonEscrowedSnxValue) ) .mul(issuanceRatio) .div(DEC_18); } /* ========================================================================================= */ /* Rebalances */ /* ========================================================================================= */ /* * @dev Helper function to facilitate xSNXAdmin.rebalanceTowardsHedge() */ function calculateAssetChangesForRebalanceToHedge() internal view returns (uint256 totalSusdToBurn, uint256 snxToSell) { uint256 snxValueHeld = getContractSnxValue(); uint256 debtValueInUsd = getContractDebtValue(); uint256 issuanceRatio = getIssuanceRatio(); uint256 susdToBurnToFixRatio = calculateSusdToBurnToFixRatio( snxValueHeld, debtValueInUsd, issuanceRatio ); uint256 susdToBurnToEclipseEscrowed = calculateSusdToBurnToEclipseEscrowed(issuanceRatio); uint256 hedgeAssetsValueInUsd = calculateHedgeAssetsValueInUsd(); uint256 valueToUnlockInUsd = debtValueInUsd.sub(hedgeAssetsValueInUsd); uint256 susdToBurnToUnlockTransfer = valueToUnlockInUsd .mul(issuanceRatio) .div(DEC_18); totalSusdToBurn = ( susdToBurnToFixRatio.add(susdToBurnToEclipseEscrowed).add( susdToBurnToUnlockTransfer ) ); snxToSell = valueToUnlockInUsd.mul(DEC_18).div(getSnxPrice()); } /* * @dev Helper function to facilitate xSNXAdmin.rebalanceTowardsSnx() */ function calculateAssetChangesForRebalanceToSnx() public view returns (uint256 setToSell) { ( uint256 debtValueInWei, uint256 hedgeAssetsBalance ) = getRebalanceUtils(); uint256 setValueToSell = hedgeAssetsBalance.sub(debtValueInWei); uint256 ethValueOfOneSet = calculateEthValueOfOneSetUnit(); setToSell = setValueToSell.mul(DEC_18).div(ethValueOfOneSet); // Set quantity must be multiple of natural unit uint256 naturalUnit = getSetNaturalUnit(); setToSell = setToSell.div(naturalUnit).mul(naturalUnit); } /* * @dev Helper function to facilitate xSNXAdmin.rebalanceTowardsSnx() */ function getRebalanceTowardsSnxUtils() public view returns (uint256 setToSell, address activeAsset) { setToSell = calculateAssetChangesForRebalanceToSnx(); activeAsset = getAssetCurrentlyActiveInSet(); } /* * @dev Helper function to facilitate xSNXAdmin.rebalanceTowardsSnx(), xSNXAdmin.rebalanceTowardsHedge() * @dev Denominated in ETH terms */ function getRebalanceUtils() public view returns (uint256 debtValueInWei, uint256 hedgeAssetsBalance) { uint256 setHoldingsInWei = getSetHoldingsValueInWei(); uint256 ethBalance = getEthBalance(); uint256 debtValue = getContractDebtValue(); debtValueInWei = calculateDebtValueInWei(debtValue); hedgeAssetsBalance = setHoldingsInWei.add(ethBalance); } /* * @dev Helper function to facilitate xSNXAdmin.rebalanceTowardsHedge() * @dev Denominated in USD terms */ function calculateHedgeAssetsValueInUsd() internal view returns (uint256 hedgeAssetsValueInUsd) { address currentSetAsset = getAssetCurrentlyActiveInSet(); uint256 decimals = (TEN**ERC20Detailed(currentSetAsset).decimals()); uint256 setCollateralTokens = getSetCollateralTokens(); setCollateralTokens = setCollateralTokens.mul(DEC_18).div(decimals); bytes32 activeAssetSynthSymbol = getActiveAssetSynthSymbol(); uint256 synthUsd = getSynthPrice(activeAssetSynthSymbol); uint256 setValueUsd = setCollateralTokens.mul(synthUsd).div(DEC_18); uint256 ethBalance = getEthBalance(); uint256 ethUsd = getSynthPrice(seth); uint256 ethValueUsd = ethBalance.mul(ethUsd).div(DEC_18); hedgeAssetsValueInUsd = setValueUsd.add(ethValueUsd); } /* * @dev Helper function to determine whether xSNXAdmin.rebalanceTowardsSnx() is required */ function isRebalanceTowardsSnxRequired() public view returns (bool) { ( uint256 debtValueInWei, uint256 hedgeAssetsBalance ) = getRebalanceUtils(); if ( debtValueInWei.mul(REBALANCE_THRESHOLD).div(PERCENT) < hedgeAssetsBalance ) { return true; } return false; } /* * @dev Helper function to determine whether xSNXAdmin.rebalanceTowardsHedge() is required */ function isRebalanceTowardsHedgeRequired() public view returns (bool) { ( uint256 debtValueInWei, uint256 hedgeAssetsBalance ) = getRebalanceUtils(); if ( hedgeAssetsBalance.mul(REBALANCE_THRESHOLD).div(PERCENT) < debtValueInWei ) { return true; } return false; } /* * @dev Helper function to facilitate xSNXAdmin.rebalanceTowardsHedge() * @notice Will fail if !isRebalanceTowardsHedgeRequired() */ function getRebalanceTowardsHedgeUtils() public view returns ( uint256, uint256, address ) { ( uint256 totalSusdToBurn, uint256 snxToSell ) = calculateAssetChangesForRebalanceToHedge(); address activeAsset = getAssetCurrentlyActiveInSet(); return (totalSusdToBurn, snxToSell, activeAsset); } /* * @dev Helper for `hedge` function * @dev Determines share of sUSD to allocate to ETH * @dev Implicitly determines Set allocation as well * @param susdBal: sUSD balance post minting */ function getEthAllocationOnHedge(uint256 susdBal) public view returns (uint256 ethAllocation) { uint256 ethUsd = getSynthPrice(seth); uint256 setHoldingsInUsd = getSetHoldingsValueInWei().mul(ethUsd).div( DEC_18 ); uint256 ethBalInUsd = getEthBalance().mul(ethUsd).div(DEC_18); uint256 hedgeAssets = setHoldingsInUsd.add(ethBalInUsd); if (ethBalInUsd.mul(ETH_TARGET) >= hedgeAssets.add(susdBal)) { // full bal directed toward Set // eth allocation is 0 } else if ((ethBalInUsd.add(susdBal)).mul(ETH_TARGET) < hedgeAssets) { // full bal directed toward Eth ethAllocation = susdBal; } else { // fractionate allocation ethAllocation = ((hedgeAssets.add(susdBal)).div(ETH_TARGET)).sub( ethBalInUsd ); } } /* * @dev Helper function to facilitate xSNXAdmin.rebalanceSetToEth() */ function calculateSetToSellForRebalanceSetToEth() public view returns (uint256 setQuantityToSell) { uint256 setHoldingsInWei = getSetHoldingsValueInWei(); uint256 ethBal = getEthBalance(); uint256 hedgeAssets = setHoldingsInWei.add(ethBal); require( ethBal.mul(ETH_TARGET) < hedgeAssets, "Rebalance not necessary" ); uint256 ethToAdd = ((hedgeAssets.div(ETH_TARGET)).sub(ethBal)); setQuantityToSell = getContractSetBalance().mul(ethToAdd).div( setHoldingsInWei ); uint256 naturalUnit = getSetNaturalUnit(); setQuantityToSell = setQuantityToSell.div(naturalUnit).mul(naturalUnit); } /* ========================================================================================= */ /* Address Setters */ /* ========================================================================================= */ function setAdminInstanceAddress(address _xSNXAdminInstance) public onlyOwner { if (xSNXAdminInstance == address(0)) { xSNXAdminInstance = _xSNXAdminInstance; } } function setCurve( address curvePoolAddress, int128 _usdcIndex, int128 _susdIndex ) public onlyOwner { if (address(curveFi) == address(0)) { // if initial set on deployment, immediately activate Curve address curveFi = ICurveFi(curvePoolAddress); nextCurveAddress = curvePoolAddress; } else { // if updating Curve address (i.e., not initial setting of address on deployment), // store nextCurveAddress but don't activate until addressValidator has confirmed nextCurveAddress = curvePoolAddress; } usdcIndex = _usdcIndex; susdIndex = _susdIndex; } /* ========================================================================================= */ /* Utils */ /* ========================================================================================= */ // admin on deployment approve [snx, susd, setComponentA, setComponentB] function approveKyber(address tokenAddress) public onlyOwner { IERC20(tokenAddress).approve(address(kyberNetworkProxy), MAX_UINT); } // admin on deployment approve [susd, usdc] function approveCurve(address tokenAddress) public onlyOwner { IERC20(tokenAddress).approve(address(curveFi), MAX_UINT); } function confirmCurveAddress(address _nextCurveAddress) public { require(msg.sender == addressValidator, "Incorrect caller"); require(nextCurveAddress == _nextCurveAddress, "Addresses don't match"); curveFi = ICurveFi(nextCurveAddress); } function() external payable {} } // File: contracts/helpers/Pausable.sol pragma solidity ^0.5.15; /* Adapted from OpenZeppelin */ contract Pausable is Initializable { /** * @dev Emitted when the pause is triggered by a pauser. */ event Paused(); /** * @dev Emitted when the pause is lifted by a pauser. */ event Unpaused(); bool private _paused; address public pauser; /** * @dev Initializes the contract in unpaused state. Assigns the Pauser role * to the deployer. */ constructor () internal { _paused = false; pauser = msg.sender; } /** * @dev Initializes the contract in unpaused state. Assigns the Pauser role * to the deployer. This function is called when the contract is used in a upgradeable context. */ function initialize(address sender) public initializer { _paused = false; pauser = sender; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "Pausable: not paused"); _; } /** * @dev Called by a pauser to pause, triggers stopped state. */ function pause() public onlyPauser whenNotPaused { _paused = true; emit Paused(); } /** * @dev Called by a pauser to unpause, returns to normal state. */ function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(); } modifier onlyPauser { require(msg.sender == pauser, "Don't have rights"); _; } } // File: contracts/interface/IxSNXAdmin.sol pragma solidity 0.5.15; contract IxSNXAdmin { function sendEthOnRedemption(uint valueToRedeem) external; } // File: contracts/xSNX.sol pragma solidity 0.5.15; contract xSNX is ERC20, ERC20Detailed, Pausable, Ownable { TradeAccounting private tradeAccounting; IKyberNetworkProxy private kyberNetworkProxy; address xsnxAdmin; address snxAddress; address susdAddress; uint256 public withdrawableEthFees; function initialize( address payable _tradeAccountingAddress, address _kyberProxyAddress, address _snxAddress, address _susdAddress, address _xsnxAdmin, address _ownerAddress, uint256 _mintFeeDivisor, uint256 _burnFeeDivisor, uint256 _claimFeeDivisor ) public initializer { Ownable.initialize(_ownerAddress); ERC20Detailed.initialize("xSNX", "xSNXa", 18); Pausable.initialize(_ownerAddress); tradeAccounting = TradeAccounting(_tradeAccountingAddress); kyberNetworkProxy = IKyberNetworkProxy(_kyberProxyAddress); snxAddress = _snxAddress; susdAddress = _susdAddress; xsnxAdmin = _xsnxAdmin; _setFeeDivisors(_mintFeeDivisor, _burnFeeDivisor, _claimFeeDivisor); } event Mint( address indexed user, uint256 timestamp, uint256 valueSent, uint256 mintAmount, bool mintWithEth ); event Burn( address indexed user, uint256 timestamp, uint256 burnAmount, uint256 valueToSend ); event WithdrawFees( uint256 ethAmount, uint256 susdAmount, uint256 snxAmount ); struct FeeDivisors { uint256 mintFee; uint256 burnFee; uint256 claimFee; } FeeDivisors public feeDivisors; /* * @notice Mint new xSNX tokens from the contract by sending ETH * @dev Exchanges ETH for SNX * @dev Min rate ETH/SNX sourced from Kyber in JS * @dev: Calculates overall fund NAV in ETH terms, using ETH/SNX implicit conversion rate * or ETH/SNX price (via SNX oracle) in case of allocateToEth * @dev: Mints/distributes new xSNX tokens based on contribution to NAV * @param: minRate: kyberProxy.getExpectedRate eth=>snx */ function mint(uint256 minRate) external payable whenNotPaused { require(msg.value > 0, "Must send ETH"); uint256 fee = calculateFee(msg.value, feeDivisors.mintFee); uint256 ethContribution = msg.value.sub(fee); uint256 snxBalanceBefore = tradeAccounting.getSnxBalance(); uint256 totalSupply = totalSupply(); (bool allocateToEth, uint256 nonSnxAssetValue) = tradeAccounting .getMintWithEthUtils(totalSupply); if (!allocateToEth) { uint256 snxAcquired = kyberNetworkProxy.swapEtherToToken.value( ethContribution )(ERC20(snxAddress), minRate); require( IERC20(snxAddress).transfer(xsnxAdmin, snxAcquired), "Transfer failed" ); } else { (bool success, ) = xsnxAdmin.call.value(ethContribution)(""); require(success, "Transfer failed"); } uint256 mintAmount = tradeAccounting.calculateTokensToMintWithEth( snxBalanceBefore, ethContribution, nonSnxAssetValue, totalSupply, allocateToEth ); emit Mint(msg.sender, block.timestamp, msg.value, mintAmount, true); return super._mint(msg.sender, mintAmount); } /* * @notice Mint new xSNX tokens from the contract by sending SNX * @notice Won't run without ERC20 approval * @dev: Calculates overall fund NAV in ETH terms, using ETH/SNX price (via SNX oracle) * @dev: Mints/distributes new xSNX tokens based on contribution to NAV * @param: snxAmount: SNX to contribute */ function mintWithSnx(uint256 snxAmount) external whenNotPaused { require(snxAmount > 0, "Must send SNX"); uint256 snxBalanceBefore = tradeAccounting.getSnxBalance(); uint256 fee = calculateFee(snxAmount, feeDivisors.mintFee); uint256 snxContribution = snxAmount.sub(fee); require( IERC20(snxAddress).transferFrom(msg.sender, address(this), fee), "Transfer failed" ); require( IERC20(snxAddress).transferFrom( msg.sender, xsnxAdmin, snxContribution ), "Transfer failed" ); uint256 mintAmount = tradeAccounting.calculateTokensToMintWithSnx( snxBalanceBefore, snxContribution, totalSupply() ); emit Mint( msg.sender, block.timestamp, snxContribution, mintAmount, false ); return super._mint(msg.sender, mintAmount); } /* * @notice Redeems and burns xSNX tokens and sends ETH to user * @dev Checks if ETH reserve is sufficient to settle redeem obligation * @dev Will only redeem if ETH reserve is sufficient * @param tokensToRedeem */ function burn(uint256 tokensToRedeem) external { require(tokensToRedeem > 0, "Must burn tokens"); uint256 valueToRedeem = tradeAccounting.calculateRedemptionValue( totalSupply(), tokensToRedeem ); require( tradeAccounting.getEthBalance() >= valueToRedeem, "Redeem amount exceeds available liquidity" ); IxSNXAdmin(xsnxAdmin).sendEthOnRedemption(valueToRedeem); uint256 valueToSend = valueToRedeem.sub( calculateFee(valueToRedeem, feeDivisors.burnFee) ); super._burn(msg.sender, tokensToRedeem); emit Burn(msg.sender, block.timestamp, tokensToRedeem, valueToSend); (bool success, ) = msg.sender.call.value(valueToSend)(""); require(success, "Burn transfer failed"); } function calculateFee(uint256 _value, uint256 _feeDivisor) internal pure returns (uint256 fee) { if (_feeDivisor > 0) { fee = _value.div(_feeDivisor); } } /* * @notice Inverse of fee i.e., a fee divisor of 100 == 1% * @notice Three fee types * @dev Mint fee 0 or <= 2% * @dev Burn fee 0 or <= 1% * @dev Claim fee 0 <= 4% */ function setFeeDivisors( uint256 mintFeeDivisor, uint256 burnFeeDivisor, uint256 claimFeeDivisor ) public onlyOwner { _setFeeDivisors(mintFeeDivisor, burnFeeDivisor, claimFeeDivisor); } function _setFeeDivisors( uint256 _mintFeeDivisor, uint256 _burnFeeDivisor, uint256 _claimFeeDivisor ) private { require(_mintFeeDivisor == 0 || _mintFeeDivisor >= 50, "Invalid fee"); require(_burnFeeDivisor == 0 || _burnFeeDivisor >= 100, "Invalid fee"); require(_claimFeeDivisor >= 25, "Invalid fee"); feeDivisors.mintFee = _mintFeeDivisor; feeDivisors.burnFee = _burnFeeDivisor; feeDivisors.claimFee = _claimFeeDivisor; } /* * @notice Withdraws ETH, sUSD and SNX fees to owner address */ function withdrawFees() public onlyOwner { uint256 ethFeesToWithdraw = address(this).balance; uint256 susdFeesToWithdraw = IERC20(susdAddress).balanceOf( address(this) ); uint256 snxFeesToWithdraw = IERC20(snxAddress).balanceOf(address(this)); (bool success, ) = msg.sender.call.value(ethFeesToWithdraw)(""); require(success, "Transfer failed"); IERC20(susdAddress).transfer(msg.sender, susdFeesToWithdraw); IERC20(snxAddress).transfer(msg.sender, snxFeesToWithdraw); emit WithdrawFees( ethFeesToWithdraw, susdFeesToWithdraw, snxFeesToWithdraw ); } /* * @notice Emergency function in case of errant transfer of * xSNX token directly to contract */ function withdrawNativeToken() public onlyOwner { uint256 tokenBal = balanceOf(address(this)); if (tokenBal > 0) { IERC20(address(this)).transfer(msg.sender, tokenBal); } } /* * @dev Helper function for xSNXAdmin to calculate and * transfer claim fees */ function getClaimFeeDivisor() public view returns (uint256) { return feeDivisors.claimFee; } function() external payable { require(msg.sender == xsnxAdmin, "Invalid send"); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"valueToSend","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"valueSent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"mintWithEth","type":"bool"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","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":[],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"susdAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"snxAmount","type":"uint256"}],"name":"WithdrawFees","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"tokensToRedeem","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"feeDivisors","outputs":[{"internalType":"uint256","name":"mintFee","type":"uint256"},{"internalType":"uint256","name":"burnFee","type":"uint256"},{"internalType":"uint256","name":"claimFee","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getClaimFeeDivisor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"_tradeAccountingAddress","type":"address"},{"internalType":"address","name":"_kyberProxyAddress","type":"address"},{"internalType":"address","name":"_snxAddress","type":"address"},{"internalType":"address","name":"_susdAddress","type":"address"},{"internalType":"address","name":"_xsnxAdmin","type":"address"},{"internalType":"address","name":"_ownerAddress","type":"address"},{"internalType":"uint256","name":"_mintFeeDivisor","type":"uint256"},{"internalType":"uint256","name":"_burnFeeDivisor","type":"uint256"},{"internalType":"uint256","name":"_claimFeeDivisor","type":"uint256"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"minRate","type":"uint256"}],"name":"mint","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"snxAmount","type":"uint256"}],"name":"mintWithSnx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pauser","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"mintFeeDivisor","type":"uint256"},{"internalType":"uint256","name":"burnFeeDivisor","type":"uint256"},{"internalType":"uint256","name":"claimFeeDivisor","type":"uint256"}],"name":"setFeeDivisors","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"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"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawNativeToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawableEthFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040526000609d60006101000a81548160ff02191690831515021790555033609d60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506148e68061006f6000396000f3fe6080604052600436106101d85760003560e01c8063715018a611610102578063a9059cbb11610095578063e7654b3c11610064578063e7654b3c14610c7b578063f007033314610cca578063f09ddae714610d05578063f2fde38b14610d30576101d8565b8063a9059cbb14610a22578063c4d66de814610a95578063dd62ed3e14610ae6578063df5377fe14610b6b576101d8565b806395d89b41116100d157806395d89b411461089a5780639fd0506d1461092a578063a0712d6814610981578063a457c2d7146109af576101d8565b8063715018a6146107e65780638456cb59146107fd5780638da5cb5b146108145780638f32d59b1461086b576101d8565b8063395093511161017a5780635a18664c116101495780635a18664c146107025780635c975abb14610719578063629c577e1461074857806370a0823114610781576101d8565b806339509351146106265780633f4ba83a1461069957806342966c68146106b0578063476343ee146106eb576101d8565b806318160ddd116101b657806318160ddd1461050c5780631838d85c1461053757806323b872dd14610562578063313ce567146105f5576101d8565b806306fdde031461029d578063095ea7b31461032d5780631624f6c6146103a0575b60d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f496e76616c69642073656e64000000000000000000000000000000000000000081525060200191505060405180910390fd5b005b3480156102a957600080fd5b506102b2610d81565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102f25780820151818401526020810190506102d7565b50505050905090810190601f16801561031f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561033957600080fd5b506103866004803603604081101561035057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e23565b604051808215151515815260200191505060405180910390f35b3480156103ac57600080fd5b5061050a600480360360608110156103c357600080fd5b81019080803590602001906401000000008111156103e057600080fd5b8201836020820111156103f257600080fd5b8035906020019184600183028401116401000000008311171561041457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561047757600080fd5b82018360208201111561048957600080fd5b803590602001918460018302840111640100000000831117156104ab57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff169060200190929190505050610e41565b005b34801561051857600080fd5b50610521610f8c565b6040518082815260200191505060405180910390f35b34801561054357600080fd5b5061054c610f96565b6040518082815260200191505060405180910390f35b34801561056e57600080fd5b506105db6004803603606081101561058557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f9c565b604051808215151515815260200191505060405180910390f35b34801561060157600080fd5b5061060a611075565b604051808260ff1660ff16815260200191505060405180910390f35b34801561063257600080fd5b5061067f6004803603604081101561064957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061108c565b604051808215151515815260200191505060405180910390f35b3480156106a557600080fd5b506106ae61113f565b005b3480156106bc57600080fd5b506106e9600480360360208110156106d357600080fd5b81019080803590602001909291905050506112cd565b005b3480156106f757600080fd5b506107006116fb565b005b34801561070e57600080fd5b50610717611c29565b005b34801561072557600080fd5b5061072e611d80565b604051808215151515815260200191505060405180910390f35b34801561075457600080fd5b5061075d611d97565b60405180848152602001838152602001828152602001935050505060405180910390f35b34801561078d57600080fd5b506107d0600480360360208110156107a457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611daf565b6040518082815260200191505060405180910390f35b3480156107f257600080fd5b506107fb611df8565b005b34801561080957600080fd5b50610812611f33565b005b34801561082057600080fd5b506108296120c2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561087757600080fd5b506108806120ec565b604051808215151515815260200191505060405180910390f35b3480156108a657600080fd5b506108af61214b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ef5780820151818401526020810190506108d4565b50505050905090810190601f16801561091c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561093657600080fd5b5061093f6121ed565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109ad6004803603602081101561099757600080fd5b8101908080359060200190929190505050612213565b005b3480156109bb57600080fd5b50610a08600480360360408110156109d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061298a565b604051808215151515815260200191505060405180910390f35b348015610a2e57600080fd5b50610a7b60048036036040811015610a4557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612a57565b604051808215151515815260200191505060405180910390f35b348015610aa157600080fd5b50610ae460048036036020811015610ab857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a75565b005b348015610af257600080fd5b50610b5560048036036040811015610b0957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612c33565b6040518082815260200191505060405180910390f35b348015610b7757600080fd5b50610c796004803603610120811015610b8f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050612cba565b005b348015610c8757600080fd5b50610cc860048036036060811015610c9e57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050612f9a565b005b348015610cd657600080fd5b50610d0360048036036020811015610ced57600080fd5b8101908080359060200190929190505050613024565b005b348015610d1157600080fd5b50610d1a613669565b6040518082815260200191505060405180910390f35b348015610d3c57600080fd5b50610d7f60048036036020811015610d5357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613676565b005b606060688054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e195780601f10610dee57610100808354040283529160200191610e19565b820191906000526020600020905b815481529060010190602001808311610dfc57829003601f168201915b5050505050905090565b6000610e37610e306136fc565b8484613704565b6001905092915050565b600060019054906101000a900460ff1680610e605750610e5f6138fb565b5b80610e7757506000809054906101000a900460ff16155b610ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806147cc602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015610f1c576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b8360689080519060200190610f3292919061464b565b508260699080519060200190610f4992919061464b565b5081606a60006101000a81548160ff021916908360ff1602179055508015610f865760008060016101000a81548160ff0219169083151502179055505b50505050565b6000603554905090565b60d65481565b6000610fa9848484613912565b61106a84610fb56136fc565b611065856040518060600160405280602881526020016147a460289139603460008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061101b6136fc565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613bcc9092919063ffffffff16565b613704565b600190509392505050565b6000606a60009054906101000a900460ff16905090565b60006111356110996136fc565b8461113085603460006110aa6136fc565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613c8c90919063ffffffff16565b613704565b6001905092915050565b609d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611202576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f446f6e277420686176652072696768747300000000000000000000000000000081525060200191505060405180910390fd5b609d60009054906101000a900460ff16611284576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5061757361626c653a206e6f742070617573656400000000000000000000000081525060200191505060405180910390fd5b6000609d60006101000a81548160ff0219169083151502179055507fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693360405160405180910390a1565b60008111611343576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f4d757374206275726e20746f6b656e730000000000000000000000000000000081525060200191505060405180910390fd5b600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318d814ba61138b610f8c565b846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156113c757600080fd5b505afa1580156113db573d6000803e3d6000fd5b505050506040513d60208110156113f157600080fd5b810190808051906020019092919050505090508060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370ed0ada6040518163ffffffff1660e01b815260040160206040518083038186803b15801561146d57600080fd5b505afa158015611481573d6000803e3d6000fd5b505050506040513d602081101561149757600080fd5b810190808051906020019092919050505010156114ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806148646029913960400191505060405180910390fd5b60d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9650727826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561157457600080fd5b505af1158015611588573d6000803e3d6000fd5b5050505060006115af6115a08360d760010154613d14565b83613d3a90919063ffffffff16565b90506115bb3384613d84565b3373ffffffffffffffffffffffffffffffffffffffff167f743033787f4738ff4d6a7225ce2bd0977ee5f86b91a902a58f5e4d0b297b464442858460405180848152602001838152602001828152602001935050505060405180910390a260003373ffffffffffffffffffffffffffffffffffffffff168260405180600001905060006040518083038185875af1925050503d8060008114611679576040519150601f19603f3d011682016040523d82523d6000602084013e61167e565b606091505b50509050806116f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4275726e207472616e73666572206661696c656400000000000000000000000081525060200191505060405180910390fd5b50505050565b6117036120ec565b611775576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000479050600060d560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561181b57600080fd5b505afa15801561182f573d6000803e3d6000fd5b505050506040513d602081101561184557600080fd5b81019080805190602001909291905050509050600060d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156118f957600080fd5b505afa15801561190d573d6000803e3d6000fd5b505050506040513d602081101561192357600080fd5b8101908080519060200190929190505050905060003373ffffffffffffffffffffffffffffffffffffffff168460405180600001905060006040518083038185875af1925050503d8060008114611996576040519150601f19603f3d011682016040523d82523d6000602084013e61199b565b606091505b5050905080611a12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b60d560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611abb57600080fd5b505af1158015611acf573d6000803e3d6000fd5b505050506040513d6020811015611ae557600080fd5b81019080805190602001909291905050505060d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611ba057600080fd5b505af1158015611bb4573d6000803e3d6000fd5b505050506040513d6020811015611bca57600080fd5b8101908080519060200190929190505050507fa80975b2ffacb3d3f1fcfd13863288991d27ae8e617c147e7c83d240b82bd1f684848460405180848152602001838152602001828152602001935050505060405180910390a150505050565b611c316120ec565b611ca3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000611cae30611daf565b90506000811115611d7d573073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611d4057600080fd5b505af1158015611d54573d6000803e3d6000fd5b505050506040513d6020811015611d6a57600080fd5b8101908080519060200190929190505050505b50565b6000609d60009054906101000a900460ff16905090565b60d78060000154908060010154908060020154905083565b6000603360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611e006120ec565b611e72576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000609e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b609d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611ff6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f446f6e277420686176652072696768747300000000000000000000000000000081525060200191505060405180910390fd5b609d60009054906101000a900460ff1615612079576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6001609d60006101000a81548160ff0219169083151502179055507f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75260405160405180910390a1565b6000609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661212f6136fc565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b606060698054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156121e35780601f106121b8576101008083540402835291602001916121e3565b820191906000526020600020905b8154815290600101906020018083116121c657829003601f168201915b5050505050905090565b609d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b609d60009054906101000a900460ff1615612296576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6000341161230c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742073656e64204554480000000000000000000000000000000000000081525060200191505060405180910390fd5b600061231d3460d760000154613d14565b905060006123348234613d3a90919063ffffffff16565b9050600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166389afb5b76040518163ffffffff1660e01b815260040160206040518083038186803b1580156123a057600080fd5b505afa1580156123b4573d6000803e3d6000fd5b505050506040513d60208110156123ca57600080fd5b8101908080519060200190929190505050905060006123e7610f8c565b905060008060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639d765ea6846040518263ffffffff1660e01b815260040180828152602001915050604080518083038186803b15801561245e57600080fd5b505afa158015612472573d6000803e3d6000fd5b505050506040513d604081101561248857600080fd5b810190808051906020019092919080519060200190929190505050915091508161273557600060d260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637a2a04568760d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b6040518463ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506020604051808303818588803b15801561257957600080fd5b505af115801561258d573d6000803e3d6000fd5b50505050506040513d60208110156125a457600080fd5b8101908080519060200190929190505050905060d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561268257600080fd5b505af1158015612696573d6000803e3d6000fd5b505050506040513d60208110156126ac57600080fd5b810190808051906020019092919050505061272f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b50612835565b600060d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168660405180600001905060006040518083038185875af1925050503d80600081146127b7576040519150601f19603f3d011682016040523d82523d6000602084013e6127bc565b606091505b5050905080612833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b505b600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166347029e4b86888588886040518663ffffffff1660e01b815260040180868152602001858152602001848152602001838152602001821515151581526020019550505050505060206040518083038186803b1580156128ce57600080fd5b505afa1580156128e2573d6000803e3d6000fd5b505050506040513d60208110156128f857600080fd5b810190808051906020019092919050505090503373ffffffffffffffffffffffffffffffffffffffff167f5b5de75983fe8891c65234472ee1805018163815d4c146f10bf176b736093c094234846001604051808581526020018481526020018381526020018215151515815260200194505050505060405180910390a26129803382613f3e565b5050505050505050565b6000612a4d6129976136fc565b84612a488560405180606001604052806025815260200161488d60259139603460006129c16136fc565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613bcc9092919063ffffffff16565b613704565b6001905092915050565b6000612a6b612a646136fc565b8484613912565b6001905092915050565b600060019054906101000a900460ff1680612a945750612a936138fb565b5b80612aab57506000809054906101000a900460ff16155b612b00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806147cc602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015612b50576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b81609e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a38015612c2f5760008060016101000a81548160ff0219169083151502179055505b5050565b6000603460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600060019054906101000a900460ff1680612cd95750612cd86138fb565b5b80612cf057506000809054906101000a900460ff16155b612d45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806147cc602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015612d95576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b612d9e85612a75565b612e146040518060400160405280600481526020017f78534e58000000000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f78534e58610000000000000000000000000000000000000000000000000000008152506012610e41565b612e1d856140fb565b8960d160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508860d260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508760d460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508660d560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560d360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612f6d848484614257565b8015612f8e5760008060016101000a81548160ff0219169083151502179055505b50505050505050505050565b612fa26120ec565b613014576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61301f838383614257565b505050565b609d60009054906101000a900460ff16156130a7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6000811161311d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742073656e6420534e580000000000000000000000000000000000000081525060200191505060405180910390fd5b600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166389afb5b76040518163ffffffff1660e01b815260040160206040518083038186803b15801561318757600080fd5b505afa15801561319b573d6000803e3d6000fd5b505050506040513d60208110156131b157600080fd5b8101908080519060200190929190505050905060006131d58360d760000154613d14565b905060006131ec8285613d3a90919063ffffffff16565b905060d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156132cb57600080fd5b505af11580156132df573d6000803e3d6000fd5b505050506040513d60208110156132f557600080fd5b8101908080519060200190929190505050613378576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b60d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3360d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561347757600080fd5b505af115801561348b573d6000803e3d6000fd5b505050506040513d60208110156134a157600080fd5b8101908080519060200190929190505050613524576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632bdbe219858461356e610f8c565b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156135b057600080fd5b505afa1580156135c4573d6000803e3d6000fd5b505050506040513d60208110156135da57600080fd5b810190808051906020019092919050505090503373ffffffffffffffffffffffffffffffffffffffff167f5b5de75983fe8891c65234472ee1805018163815d4c146f10bf176b736093c094284846000604051808581526020018481526020018381526020018215151515815260200194505050505060405180910390a26136623382613f3e565b5050505050565b600060d760020154905090565b61367e6120ec565b6136f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6136f9816143f5565b50565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561378a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806148406024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061475c6022913960400191505060405180910390fd5b80603460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b6000803090506000813b9050600081149250505090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613998576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061481b6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613a1e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806146f16023913960400191505060405180910390fd5b613a8a8160405180606001604052806026815260200161477e60269139603360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613bcc9092919063ffffffff16565b603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550613b1f81603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613c8c90919063ffffffff16565b603360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290613c79576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c3e578082015181840152602081019050613c23565b50505050905090810190601f168015613c6b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015613d0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600080821115613d3457613d31828461453b90919063ffffffff16565b90505b92915050565b6000613d7c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613bcc565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613e0a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806147fa6021913960400191505060405180910390fd5b613e768160405180606001604052806022815260200161471460229139603360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613bcc9092919063ffffffff16565b603360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550613ece81603554613d3a90919063ffffffff16565b603581905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613fe1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b613ff681603554613c8c90919063ffffffff16565b60358190555061404e81603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613c8c90919063ffffffff16565b603360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600060019054906101000a900460ff168061411a57506141196138fb565b5b8061413157506000809054906101000a900460ff16155b614186576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806147cc602e913960400191505060405180910390fd5b60008060019054906101000a900460ff1615905080156141d6576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6000609d60006101000a81548160ff02191690831515021790555081609d60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080156142535760008060016101000a81548160ff0219169083151502179055505b5050565b6000831480614267575060328310155b6142d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f496e76616c69642066656500000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008214806142e9575060648210155b61435b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f496e76616c69642066656500000000000000000000000000000000000000000081525060200191505060405180910390fd5b60198110156143d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f496e76616c69642066656500000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260d7600001819055508160d7600101819055508060d760020181905550505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561447b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806147366026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380609e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061457d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614585565b905092915050565b60008083118290614631576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156145f65780820151818401526020810190506145db565b50505050905090810190601f1680156146235780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161463d57fe5b049050809150509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061468c57805160ff19168380011785556146ba565b828001600101855582156146ba579182015b828111156146b957825182559160200191906001019061469e565b5b5090506146c791906146cb565b5090565b6146ed91905b808211156146e95760008160009055506001016146d1565b5090565b9056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737352656465656d20616d6f756e74206578636565647320617661696c61626c65206c697175696469747945524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a72315820940916da5f1e9262e013f08512ac5b1de7b172a0e4e66a8267f6245981a46b0a64736f6c634300050f0032
Deployed Bytecode
0x6080604052600436106101d85760003560e01c8063715018a611610102578063a9059cbb11610095578063e7654b3c11610064578063e7654b3c14610c7b578063f007033314610cca578063f09ddae714610d05578063f2fde38b14610d30576101d8565b8063a9059cbb14610a22578063c4d66de814610a95578063dd62ed3e14610ae6578063df5377fe14610b6b576101d8565b806395d89b41116100d157806395d89b411461089a5780639fd0506d1461092a578063a0712d6814610981578063a457c2d7146109af576101d8565b8063715018a6146107e65780638456cb59146107fd5780638da5cb5b146108145780638f32d59b1461086b576101d8565b8063395093511161017a5780635a18664c116101495780635a18664c146107025780635c975abb14610719578063629c577e1461074857806370a0823114610781576101d8565b806339509351146106265780633f4ba83a1461069957806342966c68146106b0578063476343ee146106eb576101d8565b806318160ddd116101b657806318160ddd1461050c5780631838d85c1461053757806323b872dd14610562578063313ce567146105f5576101d8565b806306fdde031461029d578063095ea7b31461032d5780631624f6c6146103a0575b60d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f496e76616c69642073656e64000000000000000000000000000000000000000081525060200191505060405180910390fd5b005b3480156102a957600080fd5b506102b2610d81565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102f25780820151818401526020810190506102d7565b50505050905090810190601f16801561031f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561033957600080fd5b506103866004803603604081101561035057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e23565b604051808215151515815260200191505060405180910390f35b3480156103ac57600080fd5b5061050a600480360360608110156103c357600080fd5b81019080803590602001906401000000008111156103e057600080fd5b8201836020820111156103f257600080fd5b8035906020019184600183028401116401000000008311171561041457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561047757600080fd5b82018360208201111561048957600080fd5b803590602001918460018302840111640100000000831117156104ab57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff169060200190929190505050610e41565b005b34801561051857600080fd5b50610521610f8c565b6040518082815260200191505060405180910390f35b34801561054357600080fd5b5061054c610f96565b6040518082815260200191505060405180910390f35b34801561056e57600080fd5b506105db6004803603606081101561058557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610f9c565b604051808215151515815260200191505060405180910390f35b34801561060157600080fd5b5061060a611075565b604051808260ff1660ff16815260200191505060405180910390f35b34801561063257600080fd5b5061067f6004803603604081101561064957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061108c565b604051808215151515815260200191505060405180910390f35b3480156106a557600080fd5b506106ae61113f565b005b3480156106bc57600080fd5b506106e9600480360360208110156106d357600080fd5b81019080803590602001909291905050506112cd565b005b3480156106f757600080fd5b506107006116fb565b005b34801561070e57600080fd5b50610717611c29565b005b34801561072557600080fd5b5061072e611d80565b604051808215151515815260200191505060405180910390f35b34801561075457600080fd5b5061075d611d97565b60405180848152602001838152602001828152602001935050505060405180910390f35b34801561078d57600080fd5b506107d0600480360360208110156107a457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611daf565b6040518082815260200191505060405180910390f35b3480156107f257600080fd5b506107fb611df8565b005b34801561080957600080fd5b50610812611f33565b005b34801561082057600080fd5b506108296120c2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561087757600080fd5b506108806120ec565b604051808215151515815260200191505060405180910390f35b3480156108a657600080fd5b506108af61214b565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ef5780820151818401526020810190506108d4565b50505050905090810190601f16801561091c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561093657600080fd5b5061093f6121ed565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109ad6004803603602081101561099757600080fd5b8101908080359060200190929190505050612213565b005b3480156109bb57600080fd5b50610a08600480360360408110156109d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061298a565b604051808215151515815260200191505060405180910390f35b348015610a2e57600080fd5b50610a7b60048036036040811015610a4557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612a57565b604051808215151515815260200191505060405180910390f35b348015610aa157600080fd5b50610ae460048036036020811015610ab857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a75565b005b348015610af257600080fd5b50610b5560048036036040811015610b0957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612c33565b6040518082815260200191505060405180910390f35b348015610b7757600080fd5b50610c796004803603610120811015610b8f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050612cba565b005b348015610c8757600080fd5b50610cc860048036036060811015610c9e57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050612f9a565b005b348015610cd657600080fd5b50610d0360048036036020811015610ced57600080fd5b8101908080359060200190929190505050613024565b005b348015610d1157600080fd5b50610d1a613669565b6040518082815260200191505060405180910390f35b348015610d3c57600080fd5b50610d7f60048036036020811015610d5357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613676565b005b606060688054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e195780601f10610dee57610100808354040283529160200191610e19565b820191906000526020600020905b815481529060010190602001808311610dfc57829003601f168201915b5050505050905090565b6000610e37610e306136fc565b8484613704565b6001905092915050565b600060019054906101000a900460ff1680610e605750610e5f6138fb565b5b80610e7757506000809054906101000a900460ff16155b610ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806147cc602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015610f1c576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b8360689080519060200190610f3292919061464b565b508260699080519060200190610f4992919061464b565b5081606a60006101000a81548160ff021916908360ff1602179055508015610f865760008060016101000a81548160ff0219169083151502179055505b50505050565b6000603554905090565b60d65481565b6000610fa9848484613912565b61106a84610fb56136fc565b611065856040518060600160405280602881526020016147a460289139603460008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061101b6136fc565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613bcc9092919063ffffffff16565b613704565b600190509392505050565b6000606a60009054906101000a900460ff16905090565b60006111356110996136fc565b8461113085603460006110aa6136fc565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613c8c90919063ffffffff16565b613704565b6001905092915050565b609d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611202576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f446f6e277420686176652072696768747300000000000000000000000000000081525060200191505060405180910390fd5b609d60009054906101000a900460ff16611284576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5061757361626c653a206e6f742070617573656400000000000000000000000081525060200191505060405180910390fd5b6000609d60006101000a81548160ff0219169083151502179055507fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693360405160405180910390a1565b60008111611343576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f4d757374206275726e20746f6b656e730000000000000000000000000000000081525060200191505060405180910390fd5b600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318d814ba61138b610f8c565b846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156113c757600080fd5b505afa1580156113db573d6000803e3d6000fd5b505050506040513d60208110156113f157600080fd5b810190808051906020019092919050505090508060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370ed0ada6040518163ffffffff1660e01b815260040160206040518083038186803b15801561146d57600080fd5b505afa158015611481573d6000803e3d6000fd5b505050506040513d602081101561149757600080fd5b810190808051906020019092919050505010156114ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806148646029913960400191505060405180910390fd5b60d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9650727826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561157457600080fd5b505af1158015611588573d6000803e3d6000fd5b5050505060006115af6115a08360d760010154613d14565b83613d3a90919063ffffffff16565b90506115bb3384613d84565b3373ffffffffffffffffffffffffffffffffffffffff167f743033787f4738ff4d6a7225ce2bd0977ee5f86b91a902a58f5e4d0b297b464442858460405180848152602001838152602001828152602001935050505060405180910390a260003373ffffffffffffffffffffffffffffffffffffffff168260405180600001905060006040518083038185875af1925050503d8060008114611679576040519150601f19603f3d011682016040523d82523d6000602084013e61167e565b606091505b50509050806116f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4275726e207472616e73666572206661696c656400000000000000000000000081525060200191505060405180910390fd5b50505050565b6117036120ec565b611775576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000479050600060d560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561181b57600080fd5b505afa15801561182f573d6000803e3d6000fd5b505050506040513d602081101561184557600080fd5b81019080805190602001909291905050509050600060d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156118f957600080fd5b505afa15801561190d573d6000803e3d6000fd5b505050506040513d602081101561192357600080fd5b8101908080519060200190929190505050905060003373ffffffffffffffffffffffffffffffffffffffff168460405180600001905060006040518083038185875af1925050503d8060008114611996576040519150601f19603f3d011682016040523d82523d6000602084013e61199b565b606091505b5050905080611a12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b60d560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611abb57600080fd5b505af1158015611acf573d6000803e3d6000fd5b505050506040513d6020811015611ae557600080fd5b81019080805190602001909291905050505060d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611ba057600080fd5b505af1158015611bb4573d6000803e3d6000fd5b505050506040513d6020811015611bca57600080fd5b8101908080519060200190929190505050507fa80975b2ffacb3d3f1fcfd13863288991d27ae8e617c147e7c83d240b82bd1f684848460405180848152602001838152602001828152602001935050505060405180910390a150505050565b611c316120ec565b611ca3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000611cae30611daf565b90506000811115611d7d573073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611d4057600080fd5b505af1158015611d54573d6000803e3d6000fd5b505050506040513d6020811015611d6a57600080fd5b8101908080519060200190929190505050505b50565b6000609d60009054906101000a900460ff16905090565b60d78060000154908060010154908060020154905083565b6000603360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b611e006120ec565b611e72576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000609e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b609d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611ff6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f446f6e277420686176652072696768747300000000000000000000000000000081525060200191505060405180910390fd5b609d60009054906101000a900460ff1615612079576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6001609d60006101000a81548160ff0219169083151502179055507f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75260405160405180910390a1565b6000609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661212f6136fc565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b606060698054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156121e35780601f106121b8576101008083540402835291602001916121e3565b820191906000526020600020905b8154815290600101906020018083116121c657829003601f168201915b5050505050905090565b609d60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b609d60009054906101000a900460ff1615612296576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6000341161230c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742073656e64204554480000000000000000000000000000000000000081525060200191505060405180910390fd5b600061231d3460d760000154613d14565b905060006123348234613d3a90919063ffffffff16565b9050600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166389afb5b76040518163ffffffff1660e01b815260040160206040518083038186803b1580156123a057600080fd5b505afa1580156123b4573d6000803e3d6000fd5b505050506040513d60208110156123ca57600080fd5b8101908080519060200190929190505050905060006123e7610f8c565b905060008060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639d765ea6846040518263ffffffff1660e01b815260040180828152602001915050604080518083038186803b15801561245e57600080fd5b505afa158015612472573d6000803e3d6000fd5b505050506040513d604081101561248857600080fd5b810190808051906020019092919080519060200190929190505050915091508161273557600060d260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637a2a04568760d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b6040518463ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506020604051808303818588803b15801561257957600080fd5b505af115801561258d573d6000803e3d6000fd5b50505050506040513d60208110156125a457600080fd5b8101908080519060200190929190505050905060d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561268257600080fd5b505af1158015612696573d6000803e3d6000fd5b505050506040513d60208110156126ac57600080fd5b810190808051906020019092919050505061272f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b50612835565b600060d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168660405180600001905060006040518083038185875af1925050503d80600081146127b7576040519150601f19603f3d011682016040523d82523d6000602084013e6127bc565b606091505b5050905080612833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b505b600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166347029e4b86888588886040518663ffffffff1660e01b815260040180868152602001858152602001848152602001838152602001821515151581526020019550505050505060206040518083038186803b1580156128ce57600080fd5b505afa1580156128e2573d6000803e3d6000fd5b505050506040513d60208110156128f857600080fd5b810190808051906020019092919050505090503373ffffffffffffffffffffffffffffffffffffffff167f5b5de75983fe8891c65234472ee1805018163815d4c146f10bf176b736093c094234846001604051808581526020018481526020018381526020018215151515815260200194505050505060405180910390a26129803382613f3e565b5050505050505050565b6000612a4d6129976136fc565b84612a488560405180606001604052806025815260200161488d60259139603460006129c16136fc565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613bcc9092919063ffffffff16565b613704565b6001905092915050565b6000612a6b612a646136fc565b8484613912565b6001905092915050565b600060019054906101000a900460ff1680612a945750612a936138fb565b5b80612aab57506000809054906101000a900460ff16155b612b00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806147cc602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015612b50576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b81609e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a38015612c2f5760008060016101000a81548160ff0219169083151502179055505b5050565b6000603460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600060019054906101000a900460ff1680612cd95750612cd86138fb565b5b80612cf057506000809054906101000a900460ff16155b612d45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806147cc602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015612d95576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b612d9e85612a75565b612e146040518060400160405280600481526020017f78534e58000000000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f78534e58610000000000000000000000000000000000000000000000000000008152506012610e41565b612e1d856140fb565b8960d160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508860d260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508760d460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508660d560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508560d360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612f6d848484614257565b8015612f8e5760008060016101000a81548160ff0219169083151502179055505b50505050505050505050565b612fa26120ec565b613014576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61301f838383614257565b505050565b609d60009054906101000a900460ff16156130a7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5061757361626c653a207061757365640000000000000000000000000000000081525060200191505060405180910390fd5b6000811161311d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f4d7573742073656e6420534e580000000000000000000000000000000000000081525060200191505060405180910390fd5b600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166389afb5b76040518163ffffffff1660e01b815260040160206040518083038186803b15801561318757600080fd5b505afa15801561319b573d6000803e3d6000fd5b505050506040513d60208110156131b157600080fd5b8101908080519060200190929190505050905060006131d58360d760000154613d14565b905060006131ec8285613d3a90919063ffffffff16565b905060d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156132cb57600080fd5b505af11580156132df573d6000803e3d6000fd5b505050506040513d60208110156132f557600080fd5b8101908080519060200190929190505050613378576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b60d460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3360d360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561347757600080fd5b505af115801561348b573d6000803e3d6000fd5b505050506040513d60208110156134a157600080fd5b8101908080519060200190929190505050613524576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5472616e73666572206661696c6564000000000000000000000000000000000081525060200191505060405180910390fd5b600060d160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632bdbe219858461356e610f8c565b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156135b057600080fd5b505afa1580156135c4573d6000803e3d6000fd5b505050506040513d60208110156135da57600080fd5b810190808051906020019092919050505090503373ffffffffffffffffffffffffffffffffffffffff167f5b5de75983fe8891c65234472ee1805018163815d4c146f10bf176b736093c094284846000604051808581526020018481526020018381526020018215151515815260200194505050505060405180910390a26136623382613f3e565b5050505050565b600060d760020154905090565b61367e6120ec565b6136f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6136f9816143f5565b50565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561378a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806148406024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061475c6022913960400191505060405180910390fd5b80603460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b6000803090506000813b9050600081149250505090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613998576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061481b6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613a1e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806146f16023913960400191505060405180910390fd5b613a8a8160405180606001604052806026815260200161477e60269139603360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613bcc9092919063ffffffff16565b603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550613b1f81603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613c8c90919063ffffffff16565b603360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290613c79576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c3e578082015181840152602081019050613c23565b50505050905090810190601f168015613c6b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015613d0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600080821115613d3457613d31828461453b90919063ffffffff16565b90505b92915050565b6000613d7c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613bcc565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613e0a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806147fa6021913960400191505060405180910390fd5b613e768160405180606001604052806022815260200161471460229139603360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613bcc9092919063ffffffff16565b603360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550613ece81603554613d3a90919063ffffffff16565b603581905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613fe1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b613ff681603554613c8c90919063ffffffff16565b60358190555061404e81603360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054613c8c90919063ffffffff16565b603360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b600060019054906101000a900460ff168061411a57506141196138fb565b5b8061413157506000809054906101000a900460ff16155b614186576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806147cc602e913960400191505060405180910390fd5b60008060019054906101000a900460ff1615905080156141d6576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6000609d60006101000a81548160ff02191690831515021790555081609d60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080156142535760008060016101000a81548160ff0219169083151502179055505b5050565b6000831480614267575060328310155b6142d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f496e76616c69642066656500000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008214806142e9575060648210155b61435b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f496e76616c69642066656500000000000000000000000000000000000000000081525060200191505060405180910390fd5b60198110156143d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f496e76616c69642066656500000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260d7600001819055508160d7600101819055508060d760020181905550505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561447b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806147366026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16609e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380609e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061457d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614585565b905092915050565b60008083118290614631576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156145f65780820151818401526020810190506145db565b50505050905090810190601f1680156146235780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161463d57fe5b049050809150509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061468c57805160ff19168380011785556146ba565b828001600101855582156146ba579182015b828111156146b957825182559160200191906001019061469e565b5b5090506146c791906146cb565b5090565b6146ed91905b808211156146e95760008160009055506001016146d1565b5090565b9056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737352656465656d20616d6f756e74206578636565647320617661696c61626c65206c697175696469747945524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a72315820940916da5f1e9262e013f08512ac5b1de7b172a0e4e66a8267f6245981a46b0a64736f6c634300050f0032
Deployed Bytecode Sourcemap
81035:8722:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89720:9;;;;;;;;;;;89706:23;;:10;:23;;;89698:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81035:8722;23559:83;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23559:83:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;23559:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17002:152;;8:9:-1;5:2;;;30:1;27;20:12;5:2;17002:152:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;17002:152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;23303:186;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23303:186:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;23303:186:0;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;23303:186:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;23303:186:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;23303:186:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;23303:186:0;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;23303:186:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;23303:186:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;23303:186:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;23303:186:0;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;16023:91;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16023:91:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;81275:34;;8:9:-1;5:2;;;30:1;27;20:12;5:2;81275:34:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;17626:304;;8:9:-1;5:2;;;30:1;27;20:12;5:2;17626:304:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;17626:304:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;24411:83;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24411:83:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;18339:210;;8:9:-1;5:2;;;30:1;27;20:12;5:2;18339:210:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;18339:210:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;80569:108;;8:9:-1;5:2;;;30:1;27;20:12;5:2;80569:108:0;;;:::i;:::-;;86239:852;;8:9:-1;5:2;;;30:1;27;20:12;5:2;86239:852:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;86239:852:0;;;;;;;;;;;;;;;;;:::i;:::-;;88384:701;;8:9:-1;5:2;;;30:1;27;20:12;5:2;88384:701:0;;;:::i;:::-;;89215:217;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89215:217:0;;;:::i;:::-;;79788:78;;8:9:-1;5:2;;;30:1;27;20:12;5:2;79788:78:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;82704:30;;8:9:-1;5:2;;;30:1;27;20:12;5:2;82704:30:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16177:110;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16177:110:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;16177:110:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;10717:140;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10717:140:0;;;:::i;:::-;;80368:106;;8:9:-1;5:2;;;30:1;27;20:12;5:2;80368:106:0;;;:::i;:::-;;9904:79;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9904:79:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;10270:94;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10270:94:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;23761:87;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23761:87:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;23761:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79123:21;;8:9:-1;5:2;;;30:1;27;20:12;5:2;79123:21:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;83220:1337;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;83220:1337:0;;;;;;;;;;;;;;;;;:::i;:::-;;19052:261;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19052:261:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;19052:261:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;16500:158;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16500:158:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;16500:158:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;9678:145;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9678:145:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;9678:145:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;16721:134;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16721:134:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;16721:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;81318:836;;8:9:-1;5:2;;;30:1;27;20:12;5:2;81318:836:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;81318:836:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;87539:231;;8:9:-1;5:2;;;30:1;27;20:12;5:2;87539:231:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;87539:231:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;84916:1064;;8:9:-1;5:2;;;30:1;27;20:12;5:2;84916:1064:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;84916:1064:0;;;;;;;;;;;;;;;;;:::i;:::-;;89545:106;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89545:106:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;11012:109;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11012:109:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;11012:109:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;23559:83;23596:13;23629:5;23622:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23559:83;:::o;17002:152::-;17068:4;17085:39;17094:12;:10;:12::i;:::-;17108:7;17117:6;17085:8;:39::i;:::-;17142:4;17135:11;;17002:152;;;;:::o;23303:186::-;6655:12;;;;;;;;;;;:31;;;;6671:15;:13;:15::i;:::-;6655:31;:47;;;;6691:11;;;;;;;;;;;6690:12;6655:47;6647:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6762:19;6785:12;;;;;;;;;;;6784:13;6762:35;;6808:14;6804:83;;;6848:4;6833:12;;:19;;;;;;;;;;;;;;;;;;6875:4;6861:11;;:18;;;;;;;;;;;;;;;;;;6804:83;23419:4;23411:5;:12;;;;;;;;;;;;:::i;:::-;;23444:6;23434:7;:16;;;;;;;;;;;;:::i;:::-;;23473:8;23461:9;;:20;;;;;;;;;;;;;;;;;;6909:14;6905:57;;;6949:5;6934:12;;:20;;;;;;;;;;;;;;;;;;6905:57;23303:186;;;;:::o;16023:91::-;16067:7;16094:12;;16087:19;;16023:91;:::o;81275:34::-;;;;:::o;17626:304::-;17715:4;17732:36;17742:6;17750:9;17761:6;17732:9;:36::i;:::-;17779:121;17788:6;17796:12;:10;:12::i;:::-;17810:89;17848:6;17810:89;;;;;;;;;;;;;;;;;:11;:19;17822:6;17810:19;;;;;;;;;;;;;;;:33;17830:12;:10;:12::i;:::-;17810:33;;;;;;;;;;;;;;;;:37;;:89;;;;;:::i;:::-;17779:8;:121::i;:::-;17918:4;17911:11;;17626:304;;;;;:::o;24411:83::-;24452:5;24477:9;;;;;;;;;;;24470:16;;24411:83;:::o;18339:210::-;18419:4;18436:83;18445:12;:10;:12::i;:::-;18459:7;18468:50;18507:10;18468:11;:25;18480:12;:10;:12::i;:::-;18468:25;;;;;;;;;;;;;;;:34;18494:7;18468:34;;;;;;;;;;;;;;;;:38;;:50;;;;:::i;:::-;18436:8;:83::i;:::-;18537:4;18530:11;;18339:210;;;;:::o;80569:108::-;80738:6;;;;;;;;;;;80724:20;;:10;:20;;;80716:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80224:7;;;;;;;;;;;80216:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80638:5;80628:7;;:15;;;;;;;;;;;;;;;;;;80659:10;;;;;;;;;;80569:108::o;86239:852::-;86322:1;86305:14;:18;86297:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86357:21;86381:15;;;;;;;;;;;:40;;;86436:13;:11;:13::i;:::-;86464:14;86381:108;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;86381:108:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;86381:108:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;86381:108:0;;;;;;;;;;;;;;;;86357:132;;86559:13;86524:15;;;;;;;;;;;:29;;;:31;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;86524:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;86524:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;86524:31:0;;;;;;;;;;;;;;;;:48;;86502:139;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86665:9;;;;;;;;;;;86654:41;;;86696:13;86654:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;86654:56:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;86654:56:0;;;;86721:19;86743:91;86775:48;86788:13;86803:11;:19;;;86775:12;:48::i;:::-;86743:13;:17;;:91;;;;:::i;:::-;86721:113;;86845:39;86857:10;86869:14;86845:11;:39::i;:::-;86905:10;86900:62;;;86917:15;86934:14;86950:11;86900:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86976:12;86994:10;:15;;87016:11;86994:38;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;86975:57:0;;;87051:7;87043:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86239:852;;;;:::o;88384:701::-;10116:9;:7;:9::i;:::-;10108:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88436:25;88464:21;88436:49;;88496:26;88532:11;;;;;;;;;;;88525:29;;;88577:4;88525:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;88525:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;88525:68:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;88525:68:0;;;;;;;;;;;;;;;;88496:97;;88604:25;88639:10;;;;;;;;;;;88632:28;;;88669:4;88632:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;88632:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;88632:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;88632:43:0;;;;;;;;;;;;;;;;88604:71;;88689:12;88707:10;:15;;88729:17;88707:44;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;88688:63:0;;;88770:7;88762:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88817:11;;;;;;;;;;;88810:28;;;88839:10;88851:18;88810:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;88810:60:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;88810:60:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;88810:60:0;;;;;;;;;;;;;;;;;88888:10;;;;;;;;;;;88881:27;;;88909:10;88921:17;88881:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;88881:58:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;88881:58:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;88881:58:0;;;;;;;;;;;;;;;;;88957:120;88984:17;89016:18;89049:17;88957:120;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10173:1;;;;88384:701::o;89215:217::-;10116:9;:7;:9::i;:::-;10108:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89274:16;89293:24;89311:4;89293:9;:24::i;:::-;89274:43;;89343:1;89332:8;:12;89328:97;;;89376:4;89361:30;;;89392:10;89404:8;89361:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89361:52:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;89361:52:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;89361:52:0;;;;;;;;;;;;;;;;;89328:97;10173:1;89215:217::o;79788:78::-;79827:4;79851:7;;;;;;;;;;;79844:14;;79788:78;:::o;82704:30::-;;;;;;;;;;;;;;;;;;;:::o;16177:110::-;16234:7;16261:9;:18;16271:7;16261:18;;;;;;;;;;;;;;;;16254:25;;16177:110;;;:::o;10717:140::-;10116:9;:7;:9::i;:::-;10108:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10816:1;10779:40;;10800:6;;;;;;;;;;;10779:40;;;;;;;;;;;;10847:1;10830:6;;:19;;;;;;;;;;;;;;;;;;10717:140::o;80368:106::-;80738:6;;;;;;;;;;;80724:20;;:10;:20;;;80716:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80025:7;;;;;;;;;;;80024:8;80016:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80438:4;80428:7;;:14;;;;;;;;;;;;;;;;;;80458:8;;;;;;;;;;80368:106::o;9904:79::-;9942:7;9969:6;;;;;;;;;;;9962:13;;9904:79;:::o;10270:94::-;10310:4;10350:6;;;;;;;;;;;10334:22;;:12;:10;:12::i;:::-;:22;;;10327:29;;10270:94;:::o;23761:87::-;23800:13;23833:7;23826:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23761:87;:::o;79123:21::-;;;;;;;;;;;;;:::o;83220:1337::-;80025:7;;;;;;;;;;;80024:8;80016:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83313:1;83301:9;:13;83293:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83345:11;83359:44;83372:9;83383:11;:19;;;83359:12;:44::i;:::-;83345:58;;83414:23;83440:18;83454:3;83440:9;:13;;:18;;;;:::i;:::-;83414:44;;83469:24;83496:15;;;;;;;;;;;:29;;;:31;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;83496:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83496:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;83496:31:0;;;;;;;;;;;;;;;;83469:58;;83540:19;83562:13;:11;:13::i;:::-;83540:35;;83587:18;83607:24;83635:15;;;;;;;;;;;:49;;;83685:11;83635:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;83635:62:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83635:62:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;83635:62:0;;;;;;;;;;;;;;;;;;;;;;;;;83586:111;;;;83715:13;83710:472;;83745:19;83767:17;;;;;;;;;;;:34;;;83826:15;83863:10;;;;;;;;;;;83876:7;83767:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;83767:117:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83767:117:0;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;83767:117:0;;;;;;;;;;;;;;;;83745:139;;83932:10;;;;;;;;;;;83925:27;;;83953:9;;;;;;;;;;;83964:11;83925:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;83925:51:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83925:51:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;83925:51:0;;;;;;;;;;;;;;;;83899:128;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83710:472;;;;84061:12;84079:9;;;;;;;;;;;:14;;84100:15;84079:41;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;84060:60:0;;;84143:7;84135:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83710:472;;84194:18;84215:15;;;;;;;;;;;:44;;;84274:16;84305:15;84335:16;84366:11;84392:13;84215:201;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;84215:201:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;84215:201:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;84215:201:0;;;;;;;;;;;;;;;;84194:222;;84439:10;84434:62;;;84451:15;84468:9;84479:10;84491:4;84434:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84514:35;84526:10;84538;84514:11;:35::i;:::-;84507:42;;;;;;;83220:1337;:::o;19052:261::-;19137:4;19154:129;19163:12;:10;:12::i;:::-;19177:7;19186:96;19225:15;19186:96;;;;;;;;;;;;;;;;;:11;:25;19198:12;:10;:12::i;:::-;19186:25;;;;;;;;;;;;;;;:34;19212:7;19186:34;;;;;;;;;;;;;;;;:38;;:96;;;;;:::i;:::-;19154:8;:129::i;:::-;19301:4;19294:11;;19052:261;;;;:::o;16500:158::-;16569:4;16586:42;16596:12;:10;:12::i;:::-;16610:9;16621:6;16586:9;:42::i;:::-;16646:4;16639:11;;16500:158;;;;:::o;9678:145::-;6655:12;;;;;;;;;;;:31;;;;6671:15;:13;:15::i;:::-;6655:31;:47;;;;6691:11;;;;;;;;;;;6690:12;6655:47;6647:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6762:19;6785:12;;;;;;;;;;;6784:13;6762:35;;6808:14;6804:83;;;6848:4;6833:12;;:19;;;;;;;;;;;;;;;;;;6875:4;6861:11;;:18;;;;;;;;;;;;;;;;;;6804:83;9753:6;9744;;:15;;;;;;;;;;;;;;;;;;9808:6;;;;;;;;;;;9775:40;;9804:1;9775:40;;;;;;;;;;;;6909:14;6905:57;;;6949:5;6934:12;;:20;;;;;;;;;;;;;;;;;;6905:57;9678:145;;:::o;16721:134::-;16793:7;16820:11;:18;16832:5;16820:18;;;;;;;;;;;;;;;:27;16839:7;16820:27;;;;;;;;;;;;;;;;16813:34;;16721:134;;;;:::o;81318:836::-;6655:12;;;;;;;;;;;:31;;;;6671:15;:13;:15::i;:::-;6655:31;:47;;;;6691:11;;;;;;;;;;;6690:12;6655:47;6647:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6762:19;6785:12;;;;;;;;;;;6784:13;6762:35;;6808:14;6804:83;;;6848:4;6833:12;;:19;;;;;;;;;;;;;;;;;;6875:4;6861:11;;:18;;;;;;;;;;;;;;;;;;6804:83;81687:33;81706:13;81687:18;:33::i;:::-;81731:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81773:2;81731:24;:45::i;:::-;81787:34;81807:13;81787:19;:34::i;:::-;81868:23;81834:15;;:58;;;;;;;;;;;;;;;;;;81942:18;81903:17;;:58;;;;;;;;;;;;;;;;;;81985:11;81972:10;;:24;;;;;;;;;;;;;;;;;;82021:12;82007:11;;:26;;;;;;;;;;;;;;;;;;82056:10;82044:9;;:22;;;;;;;;;;;;;;;;;;82079:67;82095:15;82112;82129:16;82079:15;:67::i;:::-;6909:14;6905:57;;;6949:5;6934:12;;:20;;;;;;;;;;;;;;;;;;6905:57;81318:836;;;;;;;;;;:::o;87539:231::-;10116:9;:7;:9::i;:::-;10108:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87698:64;87714:14;87730;87746:15;87698;:64::i;:::-;87539:231;;;:::o;84916:1064::-;80025:7;;;;;;;;;;;80024:8;80016:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85010:1;84998:9;:13;84990:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85040:24;85067:15;;;;;;;;;;;:29;;;:31;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;85067:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;85067:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;85067:31:0;;;;;;;;;;;;;;;;85040:58;;85111:11;85125:44;85138:9;85149:11;:19;;;85125:12;:44::i;:::-;85111:58;;85180:23;85206:18;85220:3;85206:9;:13;;:18;;;;:::i;:::-;85180:44;;85266:10;;;;;;;;;;;85259:31;;;85291:10;85311:4;85318:3;85259:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;85259:63:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;85259:63:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;85259:63:0;;;;;;;;;;;;;;;;85237:128;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85405:10;;;;;;;;;;;85398:31;;;85448:10;85477:9;;;;;;;;;;;85505:15;85398:137;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;85398:137:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;85398:137:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;85398:137:0;;;;;;;;;;;;;;;;85376:202;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85591:18;85612:15;;;;;;;;;;;:44;;;85671:16;85702:15;85732:13;:11;:13::i;:::-;85612:144;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;85612:144:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;85612:144:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;85612:144:0;;;;;;;;;;;;;;;;85591:165;;85793:10;85774:145;;;85818:15;85848;85878:10;85903:5;85774:145;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85937:35;85949:10;85961;85937:11;:35::i;:::-;85930:42;;;;84916:1064;:::o;89545:106::-;89596:7;89623:11;:20;;;89616:27;;89545:106;:::o;11012:109::-;10116:9;:7;:9::i;:::-;10108:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11085:28;11104:8;11085:18;:28::i;:::-;11012:109;:::o;8583:98::-;8628:15;8663:10;8656:17;;8583:98;:::o;21983:338::-;22094:1;22077:19;;:5;:19;;;;22069:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22175:1;22156:21;;:7;:21;;;;22148:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22259:6;22229:11;:18;22241:5;22229:18;;;;;;;;;;;;;;;:27;22248:7;22229:27;;;;;;;;;;;;;;;:36;;;;22297:7;22281:32;;22290:5;22281:32;;;22306:6;22281:32;;;;;;;;;;;;;;;;;;21983:338;;;:::o;7056:508::-;7103:4;7450:12;7473:4;7450:28;;7485:10;7531:4;7519:17;7513:23;;7557:1;7551:2;:7;7544:14;;;;7056:508;:::o;19803:471::-;19919:1;19901:20;;:6;:20;;;;19893:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20003:1;19982:23;;:9;:23;;;;19974:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20078;20100:6;20078:71;;;;;;;;;;;;;;;;;:9;:17;20088:6;20078:17;;;;;;;;;;;;;;;;:21;;:71;;;;;:::i;:::-;20058:9;:17;20068:6;20058:17;;;;;;;;;;;;;;;:91;;;;20183:32;20208:6;20183:9;:20;20193:9;20183:20;;;;;;;;;;;;;;;;:24;;:32;;;;:::i;:::-;20160:9;:20;20170:9;20160:20;;;;;;;;;;;;;;;:55;;;;20248:9;20231:35;;20240:6;20231:35;;;20259:6;20231:35;;;;;;;;;;;;;;;;;;19803:471;;;:::o;1869:192::-;1955:7;1988:1;1983;:6;;1991:12;1975:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1975:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2015:9;2031:1;2027;:5;2015:17;;2052:1;2045:8;;;1869:192;;;;;:::o;940:181::-;998:7;1018:9;1034:1;1030;:5;1018:17;;1059:1;1054;:6;;1046:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1112:1;1105:8;;;940:181;;;;:::o;87099:222::-;87208:11;87255:1;87241:11;:15;87237:77;;;87279:23;87290:11;87279:6;:10;;:23;;;;:::i;:::-;87273:29;;87237:77;87099:222;;;;:::o;1396:136::-;1454:7;1481:43;1485:1;1488;1481:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;1474:50;;1396:136;;;;:::o;21195:348::-;21290:1;21271:21;;:7;:21;;;;21263:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21364:68;21387:6;21364:68;;;;;;;;;;;;;;;;;:9;:18;21374:7;21364:18;;;;;;;;;;;;;;;;:22;;:68;;;;;:::i;:::-;21343:9;:18;21353:7;21343:18;;;;;;;;;;;;;;;:89;;;;21458:24;21475:6;21458:12;;:16;;:24;;;;:::i;:::-;21443:12;:39;;;;21524:1;21498:37;;21507:7;21498:37;;;21528:6;21498:37;;;;;;;;;;;;;;;;;;21195:348;;:::o;20555:308::-;20650:1;20631:21;;:7;:21;;;;20623:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20716:24;20733:6;20716:12;;:16;;:24;;;;:::i;:::-;20701:12;:39;;;;20772:30;20795:6;20772:9;:18;20782:7;20772:18;;;;;;;;;;;;;;;;:22;;:30;;;;:::i;:::-;20751:9;:18;20761:7;20751:18;;;;;;;;;;;;;;;:51;;;;20839:7;20818:37;;20835:1;20818:37;;;20848:6;20818:37;;;;;;;;;;;;;;;;;;20555:308;;:::o;79573:115::-;6655:12;;;;;;;;;;;:31;;;;6671:15;:13;:15::i;:::-;6655:31;:47;;;;6691:11;;;;;;;;;;;6690:12;6655:47;6647:106;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6762:19;6785:12;;;;;;;;;;;6784:13;6762:35;;6808:14;6804:83;;;6848:4;6833:12;;:19;;;;;;;;;;;;;;;;;;6875:4;6861:11;;:18;;;;;;;;;;;;;;;;;;6804:83;79649:5;79639:7;;:15;;;;;;;;;;;;;;;;;;79674:6;79665;;:15;;;;;;;;;;;;;;;;;;6909:14;6905:57;;;6949:5;6934:12;;:20;;;;;;;;;;;;;;;;;;6905:57;79573:115;;:::o;87778:515::-;87959:1;87940:15;:20;:45;;;;87983:2;87964:15;:21;;87940:45;87932:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88039:1;88020:15;:20;:46;;;;88063:3;88044:15;:22;;88020:46;88012:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88121:2;88101:16;:22;;88093:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88172:15;88150:11;:19;;:37;;;;88220:15;88198:11;:19;;:37;;;;88269:16;88246:11;:20;;:39;;;;87778:515;;;:::o;11227:229::-;11321:1;11301:22;;:8;:22;;;;11293:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11411:8;11382:38;;11403:6;;;;;;;;;;;11382:38;;;;;;;;;;;;11440:8;11431:6;;:17;;;;;;;;;;;;;;;;;;11227:229;:::o;3251:132::-;3309:7;3336:39;3340:1;3343;3336:39;;;;;;;;;;;;;;;;;:3;:39::i;:::-;3329:46;;3251:132;;;;:::o;3913:345::-;3999:7;4098:1;4094;:5;4101:12;4086:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;4086:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4125:9;4141:1;4137;:5;;;;;;4125:17;;4249:1;4242:8;;;3913:345;;;;;:::o;81035:8722::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
bzzr://940916da5f1e9262e013f08512ac5b1de7b172a0e4e66a8267f6245981a46b0a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.