Address Details
contract
0xb55c3DF43dB44492aF67743331d88cdC840CBE03
- Contract Name
- ETHTimeBondDepository
- Creator
- 0x087927–0e4c89 at 0x2e831d–c3a4dd
- Balance
- 0 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- 1 Transactions
- Transfers
- 0 Transfers
- Gas Used
- 250,000
- Last Balance Update
- 14998903
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- ETHTimeBondDepository
- Optimization enabled
- false
- Compiler version
- v0.7.5+commit.eb77ed08
- EVM Version
- istanbul
- Verified at
- 2022-11-16T02:27:46.711369Z
.deps/EthBondDepository.sol
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.7.5; interface IOwnable { function policy() external view returns (address); function renounceManagement() external; function pushManagement( address newOwner_ ) external; function pullManagement() external; } contract Ownable is IOwnable { address internal _owner; address internal _newOwner; event OwnershipPushed(address indexed previousOwner, address indexed newOwner); event OwnershipPulled(address indexed previousOwner, address indexed newOwner); constructor () { _owner = msg.sender; emit OwnershipPushed( address(0), _owner ); } function policy() public view override returns (address) { return _owner; } modifier onlyPolicy() { require( _owner == msg.sender, "Ownable: caller is not the owner" ); _; } function renounceManagement() public virtual override onlyPolicy() { emit OwnershipPushed( _owner, address(0) ); _owner = address(0); } function pushManagement( address newOwner_ ) public virtual override onlyPolicy() { require( newOwner_ != address(0), "Ownable: new owner is the zero address"); emit OwnershipPushed( _owner, newOwner_ ); _newOwner = newOwner_; } function pullManagement() public virtual override { require( msg.sender == _newOwner, "Ownable: must be new owner to pull"); emit OwnershipPulled( _owner, _newOwner ); _owner = _newOwner; } } library LowGasSafeMath { /// @notice Returns x + y, reverts if sum overflows uint256 /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x); } function add32(uint32 x, uint32 y) internal pure returns (uint32 z) { require((z = x + y) >= x); } /// @notice Returns x - y, reverts if underflows /// @param x The minuend /// @param y The subtrahend /// @return z The difference of x and y function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x - y) <= x); } function sub32(uint32 x, uint32 y) internal pure returns (uint32 z) { require((z = x - y) <= x); } /// @notice Returns x * y, reverts if overflows /// @param x The multiplicand /// @param y The multiplier /// @return z The product of x and y function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { require(x == 0 || (z = x * y) / x == y); } /// @notice Returns x + y, reverts if overflows or underflows /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add(int256 x, int256 y) internal pure returns (int256 z) { require((z = x + y) >= x == (y >= 0)); } /// @notice Returns x - y, reverts if overflows or underflows /// @param x The minuend /// @param y The subtrahend /// @return z The difference of x and y function sub(int256 x, int256 y) internal pure returns (int256 z) { require((z = x - y) <= x == (y >= 0)); } } library Address { function isContract(address account) internal view returns (bool) { uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } function _functionCallWithValue( address target, bytes memory data, uint256 weiValue, string memory errorMessage ) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) private pure returns(bytes memory) { if (success) { return returndata; } else { if (returndata.length > 0) { assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } function addressToString(address _address) internal pure returns(string memory) { bytes32 _bytes = bytes32(uint256(_address)); bytes memory HEX = "0123456789abcdef"; bytes memory _addr = new bytes(42); _addr[0] = '0'; _addr[1] = 'x'; for(uint256 i = 0; i < 20; i++) { _addr[2+i*2] = HEX[uint8(_bytes[i + 12] >> 4)]; _addr[3+i*2] = HEX[uint8(_bytes[i + 12] & 0x0f)]; } return string(_addr); } } interface IERC20 { function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } library SafeERC20 { using LowGasSafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) .sub(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function _callOptionalReturn(IERC20 token, bytes memory data) private { bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } library FullMath { function fullMul(uint256 x, uint256 y) private pure returns (uint256 l, uint256 h) { uint256 mm = mulmod(x, y, uint256(-1)); l = x * y; h = mm - l; if (mm < l) h -= 1; } function fullDiv( uint256 l, uint256 h, uint256 d ) private pure returns (uint256) { uint256 pow2 = d & -d; d /= pow2; l /= pow2; l += h * ((-pow2) / pow2 + 1); uint256 r = 1; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; return l * r; } function mulDiv( uint256 x, uint256 y, uint256 d ) internal pure returns (uint256) { (uint256 l, uint256 h) = fullMul(x, y); uint256 mm = mulmod(x, y, d); if (mm > l) h -= 1; l -= mm; require(h < d, 'FullMath::mulDiv: overflow'); return fullDiv(l, h, d); } } library FixedPoint { struct uq112x112 { uint224 _x; } struct uq144x112 { uint256 _x; } uint8 private constant RESOLUTION = 112; uint256 private constant Q112 = 0x10000000000000000000000000000; uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000; uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits) function decode(uq112x112 memory self) internal pure returns (uint112) { return uint112(self._x >> RESOLUTION); } function decode112with18(uq112x112 memory self) internal pure returns (uint) { return uint(self._x) / 5192296858534827; } function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) { require(denominator > 0, 'FixedPoint::fraction: division by zero'); if (numerator == 0) return FixedPoint.uq112x112(0); if (numerator <= uint144(-1)) { uint256 result = (numerator << RESOLUTION) / denominator; require(result <= uint224(-1), 'FixedPoint::fraction: overflow'); return uq112x112(uint224(result)); } else { uint256 result = FullMath.mulDiv(numerator, Q112, denominator); require(result <= uint224(-1), 'FixedPoint::fraction: overflow'); return uq112x112(uint224(result)); } } } interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } interface ITreasury { function deposit( uint _amount, address _token, uint _profit ) external returns ( bool ); function valueOf( address _token, uint _amount ) external view returns ( uint value_ ); function mintRewards( address _recipient, uint _amount ) external; } interface IStaking { function stake( uint _amount, address _recipient ) external returns ( bool ); } interface IStakingHelper { function stake( uint _amount, address _recipient ) external; } interface IWAVAX9 is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; } contract ETHTimeBondDepository is Ownable { using FixedPoint for *; using SafeERC20 for IERC20; using SafeERC20 for IWAVAX9; using LowGasSafeMath for uint; using LowGasSafeMath for uint32; /* ======== EVENTS ======== */ event BondCreated( uint deposit, uint indexed payout, uint indexed expires, uint indexed priceInUSD ); event BondRedeemed( address indexed recipient, uint payout, uint remaining ); event BondPriceChanged( uint indexed priceInUSD, uint indexed internalPrice, uint indexed debtRatio ); event ControlVariableAdjustment( uint initialBCV, uint newBCV, uint adjustment, bool addition ); /* ======== STATE VARIABLES ======== */ IERC20 public immutable Time; // token given as payment for bond IWAVAX9 public immutable principle; // token used to create bond ITreasury public immutable treasury; // mints Time when receives principle address public immutable DAO; // receives profit share from bond AggregatorV3Interface public priceFeed; IStaking public staking; // to auto-stake payout IStakingHelper public stakingHelper; // to stake and claim if no staking warmup bool public useHelper; Terms public terms; // stores terms for new bonds Adjust public adjustment; // stores adjustment to BCV data mapping( address => Bond ) public bondInfo; // stores bond information for depositors uint public totalDebt; // total value of outstanding bonds; used for pricing uint32 public lastDecay; // reference time for debt decay mapping (address => bool) public allowedZappers; /* ======== STRUCTS ======== */ // Info for creating new bonds struct Terms { uint controlVariable; // scaling variable for price uint minimumPrice; // vs principle value. 4 decimals (1500 = 0.15) uint maxPayout; // in thousandths of a %. i.e. 500 = 0.5% uint maxDebt; // 9 decimal debt ratio, max % total supply created as debt uint32 vestingTerm; // in seconds } // Info for bond holder struct Bond { uint payout; // Time remaining to be paid uint pricePaid; // In DAI, for front end viewing uint32 vesting; // Seconds left to vest uint32 lastTime; // Last interaction } // Info for incremental adjustments to control variable struct Adjust { bool add; // addition or subtraction uint rate; // increment uint target; // BCV when adjustment finished uint32 buffer; // minimum length (in seconds) between adjustments uint32 lastTime; // time when last adjustment made } /* ======== INITIALIZATION ======== */ constructor ( address _Time, address _principle, address _treasury, address _DAO, address _feed ) { require( _Time != address(0) ); Time = IERC20(_Time); require( _principle != address(0) ); principle = IWAVAX9(_principle); require( _treasury != address(0) ); treasury = ITreasury(_treasury); require( _DAO != address(0) ); DAO = _DAO; require( _feed != address(0) ); priceFeed = AggregatorV3Interface( _feed ); } /** * @notice initializes bond parameters * @param _controlVariable uint * @param _vestingTerm uint * @param _minimumPrice uint * @param _maxPayout uint * @param _maxDebt uint */ function initializeBondTerms( uint _controlVariable, uint _minimumPrice, uint _maxPayout, uint _maxDebt, uint32 _vestingTerm ) external onlyPolicy() { require( currentDebt() == 0, "Debt must be 0 for initialization" ); require( _controlVariable >= 40, "Can lock adjustment" ); require( _maxPayout <= 1000, "Payout cannot be above 1 percent" ); require( _vestingTerm >= 129600, "Vesting must be longer than 36 hours" ); terms = Terms ({ controlVariable: _controlVariable, vestingTerm: _vestingTerm, minimumPrice: _minimumPrice, maxPayout: _maxPayout, maxDebt: _maxDebt }); lastDecay = uint32(block.timestamp); } /* ======== POLICY FUNCTIONS ======== */ enum PARAMETER { VESTING, PAYOUT, DEBT, MINPRICE } /** * @notice set parameters for new bonds * @param _parameter PARAMETER * @param _input uint */ function setBondTerms ( PARAMETER _parameter, uint _input ) external onlyPolicy() { if ( _parameter == PARAMETER.VESTING ) { // 0 require( _input >= 129600, "Vesting must be longer than 36 hours" ); terms.vestingTerm = uint32(_input); } else if ( _parameter == PARAMETER.PAYOUT ) { // 1 require( _input <= 1000, "Payout cannot be above 1 percent" ); terms.maxPayout = _input; } else if ( _parameter == PARAMETER.DEBT ) { // 2 terms.maxDebt = _input; } else if ( _parameter == PARAMETER.MINPRICE ) { // 3 terms.minimumPrice = _input; } } /** * @notice set control variable adjustment * @param _addition bool * @param _increment uint * @param _target uint * @param _buffer uint */ function setAdjustment ( bool _addition, uint _increment, uint _target, uint32 _buffer ) external onlyPolicy() { require( _increment <= terms.controlVariable.mul( 25 )/ 1000, "Increment too large" ); require(_target >= 40, "Next Adjustment could be locked"); adjustment = Adjust({ add: _addition, rate: _increment, target: _target, buffer: _buffer, lastTime: uint32(block.timestamp) }); } /** * @notice set contract for auto stake * @param _staking address * @param _helper bool */ function setStaking( address _staking, bool _helper ) external onlyPolicy() { require( _staking != address(0) , "IA"); if ( _helper ) { useHelper = true; stakingHelper = IStakingHelper(_staking); } else { useHelper = false; staking = IStaking(_staking); } } function allowZapper(address zapper) external onlyPolicy { require(zapper != address(0), "ZNA"); allowedZappers[zapper] = true; } function removeZapper(address zapper) external onlyPolicy { allowedZappers[zapper] = false; } /* ======== USER FUNCTIONS ======== */ /** * @notice deposit bond * @param _amount uint * @param _maxPrice uint * @param _depositor address * @return uint */ function deposit( uint _amount, uint _maxPrice, address _depositor ) external payable returns ( uint ) { require( _depositor != address(0), "Invalid address" ); require(msg.sender == _depositor || allowedZappers[msg.sender], "LFNA"); decayDebt(); require( totalDebt <= terms.maxDebt, "Max capacity reached" ); uint priceInUSD = bondPriceInUSD(); // Stored in bond info uint nativePrice = _bondPrice(); require( _maxPrice >= nativePrice, "Slippage limit: more than max price" ); // slippage protection uint value = treasury.valueOf( address(principle), _amount ); uint payout = payoutFor( value ); // payout to bonder is computed require( payout >= 10000000, "Bond too small" ); // must be > 0.01 Time ( underflow protection ) require( payout <= maxPayout(), "Bond too large"); // size protection because there is no slippage /** asset carries risk and is not minted against asset transfered to treasury and rewards minted as payout */ if (address(this).balance >= _amount) { // pay with WETH9 require(msg.value == _amount, "UA"); principle.deposit{value: _amount}(); // wrap only what is needed to pay principle.transfer(address(treasury), _amount); } else { principle.safeTransferFrom( msg.sender, address(treasury), _amount ); } treasury.mintRewards( address(this), payout ); // total debt is increased totalDebt = totalDebt.add( value ); // depositor info is stored bondInfo[ _depositor ] = Bond({ payout: bondInfo[ _depositor ].payout.add( payout ), vesting: terms.vestingTerm, lastTime: uint32(block.timestamp), pricePaid: priceInUSD }); // indexed events are emitted emit BondCreated( _amount, payout, block.timestamp.add( terms.vestingTerm ), priceInUSD ); emit BondPriceChanged( bondPriceInUSD(), _bondPrice(), debtRatio() ); adjust(); // control variable is adjusted return payout; } /** * @notice redeem bond for user * @param _recipient address * @param _stake bool * @return uint */ function redeem( address _recipient, bool _stake ) external returns ( uint ) { require(msg.sender == _recipient, "NA"); Bond memory info = bondInfo[ _recipient ]; uint percentVested = percentVestedFor( _recipient ); // (seconds since last interaction / vesting term remaining) if ( percentVested >= 10000 ) { // if fully vested delete bondInfo[ _recipient ]; // delete user info emit BondRedeemed( _recipient, info.payout, 0 ); // emit bond data return stakeOrSend( _recipient, _stake, info.payout ); // pay user everything due } else { // if unfinished // calculate payout vested uint payout = info.payout.mul( percentVested )/ 10000; // store updated deposit info bondInfo[ _recipient ] = Bond({ payout: info.payout.sub( payout ), vesting: info.vesting.sub32( uint32( block.timestamp ).sub32( info.lastTime ) ), lastTime: uint32( block.timestamp ), pricePaid: info.pricePaid }); emit BondRedeemed( _recipient, payout, bondInfo[ _recipient ].payout ); return stakeOrSend( _recipient, _stake, payout ); } } /* ======== INTERNAL HELPER FUNCTIONS ======== */ /** * @notice allow user to stake payout automatically * @param _stake bool * @param _amount uint * @return uint */ function stakeOrSend( address _recipient, bool _stake, uint _amount ) internal returns ( uint ) { if ( !_stake ) { // if user does not want to stake Time.transfer( _recipient, _amount ); // send payout } else { // if user wants to stake if ( useHelper ) { // use if staking warmup is 0 Time.approve( address(stakingHelper), _amount ); stakingHelper.stake( _amount, _recipient ); } else { Time.approve( address(staking), _amount ); staking.stake( _amount, _recipient ); } } return _amount; } /** * @notice makes incremental adjustment to control variable */ function adjust() internal { uint timeCanAdjust = adjustment.lastTime.add32( adjustment.buffer ); if( adjustment.rate != 0 && block.timestamp >= timeCanAdjust ) { uint initial = terms.controlVariable; if ( adjustment.add ) { terms.controlVariable = terms.controlVariable.add( adjustment.rate ); if ( terms.controlVariable >= adjustment.target ) { adjustment.rate = 0; } } else { terms.controlVariable = terms.controlVariable.sub( adjustment.rate ); if ( terms.controlVariable <= adjustment.target ) { adjustment.rate = 0; } } adjustment.lastTime = uint32(block.timestamp); emit ControlVariableAdjustment( initial, terms.controlVariable, adjustment.rate, adjustment.add ); } } /** * @notice reduce total debt */ function decayDebt() internal { totalDebt = totalDebt.sub( debtDecay() ); lastDecay = uint32(block.timestamp); } /* ======== VIEW FUNCTIONS ======== */ /** * @notice determine maximum bond size * @return uint */ function maxPayout() public view returns ( uint ) { return Time.totalSupply().mul( terms.maxPayout )/ 100000; } /** * @notice calculate interest due for new bond * @param _value uint * @return uint */ function payoutFor( uint _value ) public view returns ( uint ) { return FixedPoint.fraction( _value, bondPrice() ).decode112with18()/ 1e14; } /** * @notice calculate current bond premium * @return price_ uint */ function bondPrice() public view returns ( uint price_ ) { price_ = terms.controlVariable.mul( debtRatio() )/ 1e5; if ( price_ < terms.minimumPrice ) { price_ = terms.minimumPrice; } } /** * @notice calculate current bond price and remove floor if above * @return price_ uint */ function _bondPrice() internal returns ( uint price_ ) { price_ = terms.controlVariable.mul( debtRatio() ).add( 1000000000 ) / 1e7; if ( price_ < terms.minimumPrice ) { price_ = terms.minimumPrice; } else if ( terms.minimumPrice != 0 ) { terms.minimumPrice = 0; } } /** * @notice get asset price from chainlink */ function assetPrice() public view returns (int) { ( , int price, , , ) = priceFeed.latestRoundData(); return price; } /** * @notice converts bond price to DAI value * @return price_ uint */ function bondPriceInUSD() public view returns ( uint price_ ) { price_ = bondPrice().mul( uint( assetPrice() ) ).mul( 1e6 ); } /** * @notice calculate current ratio of debt to Time supply * @return debtRatio_ uint */ function debtRatio() public view returns ( uint debtRatio_ ) { uint supply = Time.totalSupply(); debtRatio_ = FixedPoint.fraction( currentDebt().mul( 1e9 ), supply ).decode112with18()/ 1e18; } /** * @notice debt ratio in same terms as reserve bonds * @return uint */ function standardizedDebtRatio() external view returns ( uint ) { return debtRatio().mul( uint( assetPrice() ) )/ 10**priceFeed.decimals(); // ETH feed is 8 decimals } /** * @notice calculate debt factoring in decay * @return uint */ function currentDebt() public view returns ( uint ) { return totalDebt.sub( debtDecay() ); } /** * @notice amount to decay total debt by * @return decay_ uint */ function debtDecay() public view returns ( uint decay_ ) { uint32 timeSinceLast = uint32(block.timestamp).sub32( lastDecay ); decay_ = totalDebt.mul( timeSinceLast )/ terms.vestingTerm; if ( decay_ > totalDebt ) { decay_ = totalDebt; } } /** * @notice calculate how far into vesting a depositor is * @param _depositor address * @return percentVested_ uint */ function percentVestedFor( address _depositor ) public view returns ( uint percentVested_ ) { Bond memory bond = bondInfo[ _depositor ]; uint secondsSinceLast = uint32(block.timestamp).sub32( bond.lastTime ); uint vesting = bond.vesting; if ( vesting > 0 ) { percentVested_ = secondsSinceLast.mul( 10000 )/vesting; } else { percentVested_ = 0; } } /** * @notice calculate amount of Time available for claim by depositor * @param _depositor address * @return pendingPayout_ uint */ function pendingPayoutFor( address _depositor ) external view returns ( uint pendingPayout_ ) { uint percentVested = percentVestedFor( _depositor ); uint payout = bondInfo[ _depositor ].payout; if ( percentVested >= 10000 ) { pendingPayout_ = payout; } else { pendingPayout_ = payout.mul( percentVested )/ 10000; } } /* ======= AUXILLIARY ======= */ /** * @notice allow anyone to send lost tokens (excluding principle or Time) to the DAO * @return bool */ function recoverLostToken( IERC20 _token ) external returns ( bool ) { require( _token != Time, "NAT" ); require( _token != principle, "NAP" ); _token.safeTransfer( DAO, _token.balanceOf( address(this) ) ); return true; } function recoverLostETH() internal { if (address(this).balance > 0) safeTransferETH(DAO, address(this).balance); } /// @notice Transfers ETH to the recipient address /// @dev Fails with `STE` /// @param to The destination of the transfer /// @param value The value to be transferred function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'STE'); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_Time","internalType":"address"},{"type":"address","name":"_principle","internalType":"address"},{"type":"address","name":"_treasury","internalType":"address"},{"type":"address","name":"_DAO","internalType":"address"},{"type":"address","name":"_feed","internalType":"address"}]},{"type":"event","name":"BondCreated","inputs":[{"type":"uint256","name":"deposit","internalType":"uint256","indexed":false},{"type":"uint256","name":"payout","internalType":"uint256","indexed":true},{"type":"uint256","name":"expires","internalType":"uint256","indexed":true},{"type":"uint256","name":"priceInUSD","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"BondPriceChanged","inputs":[{"type":"uint256","name":"priceInUSD","internalType":"uint256","indexed":true},{"type":"uint256","name":"internalPrice","internalType":"uint256","indexed":true},{"type":"uint256","name":"debtRatio","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"BondRedeemed","inputs":[{"type":"address","name":"recipient","internalType":"address","indexed":true},{"type":"uint256","name":"payout","internalType":"uint256","indexed":false},{"type":"uint256","name":"remaining","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ControlVariableAdjustment","inputs":[{"type":"uint256","name":"initialBCV","internalType":"uint256","indexed":false},{"type":"uint256","name":"newBCV","internalType":"uint256","indexed":false},{"type":"uint256","name":"adjustment","internalType":"uint256","indexed":false},{"type":"bool","name":"addition","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipPulled","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipPushed","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"DAO","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"Time","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"add","internalType":"bool"},{"type":"uint256","name":"rate","internalType":"uint256"},{"type":"uint256","name":"target","internalType":"uint256"},{"type":"uint32","name":"buffer","internalType":"uint32"},{"type":"uint32","name":"lastTime","internalType":"uint32"}],"name":"adjustment","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"allowZapper","inputs":[{"type":"address","name":"zapper","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"allowedZappers","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"assetPrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"payout","internalType":"uint256"},{"type":"uint256","name":"pricePaid","internalType":"uint256"},{"type":"uint32","name":"vesting","internalType":"uint32"},{"type":"uint32","name":"lastTime","internalType":"uint32"}],"name":"bondInfo","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"price_","internalType":"uint256"}],"name":"bondPrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"price_","internalType":"uint256"}],"name":"bondPriceInUSD","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentDebt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"decay_","internalType":"uint256"}],"name":"debtDecay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"debtRatio_","internalType":"uint256"}],"name":"debtRatio","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deposit","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint256","name":"_maxPrice","internalType":"uint256"},{"type":"address","name":"_depositor","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initializeBondTerms","inputs":[{"type":"uint256","name":"_controlVariable","internalType":"uint256"},{"type":"uint256","name":"_minimumPrice","internalType":"uint256"},{"type":"uint256","name":"_maxPayout","internalType":"uint256"},{"type":"uint256","name":"_maxDebt","internalType":"uint256"},{"type":"uint32","name":"_vestingTerm","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"lastDecay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxPayout","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"payoutFor","inputs":[{"type":"uint256","name":"_value","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"pendingPayout_","internalType":"uint256"}],"name":"pendingPayoutFor","inputs":[{"type":"address","name":"_depositor","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"percentVested_","internalType":"uint256"}],"name":"percentVestedFor","inputs":[{"type":"address","name":"_depositor","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"policy","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract AggregatorV3Interface"}],"name":"priceFeed","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IWAVAX9"}],"name":"principle","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pullManagement","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pushManagement","inputs":[{"type":"address","name":"newOwner_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"recoverLostToken","inputs":[{"type":"address","name":"_token","internalType":"contract IERC20"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"redeem","inputs":[{"type":"address","name":"_recipient","internalType":"address"},{"type":"bool","name":"_stake","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeZapper","inputs":[{"type":"address","name":"zapper","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceManagement","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAdjustment","inputs":[{"type":"bool","name":"_addition","internalType":"bool"},{"type":"uint256","name":"_increment","internalType":"uint256"},{"type":"uint256","name":"_target","internalType":"uint256"},{"type":"uint32","name":"_buffer","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBondTerms","inputs":[{"type":"uint8","name":"_parameter","internalType":"enum ETHTimeBondDepository.PARAMETER"},{"type":"uint256","name":"_input","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setStaking","inputs":[{"type":"address","name":"_staking","internalType":"address"},{"type":"bool","name":"_helper","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IStaking"}],"name":"staking","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IStakingHelper"}],"name":"stakingHelper","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"standardizedDebtRatio","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"controlVariable","internalType":"uint256"},{"type":"uint256","name":"minimumPrice","internalType":"uint256"},{"type":"uint256","name":"maxPayout","internalType":"uint256"},{"type":"uint256","name":"maxDebt","internalType":"uint256"},{"type":"uint32","name":"vestingTerm","internalType":"uint32"}],"name":"terms","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalDebt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ITreasury"}],"name":"treasury","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"useHelper","inputs":[]}]
Contract Creation Code
0x6101006040523480156200001257600080fd5b5060405162004e7738038062004e77833981810160405260a08110156200003857600080fd5b810190808051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba60405160405180910390a3600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156200016757600080fd5b8473ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415620001d957600080fd5b8373ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156200024b57600080fd5b8273ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620002bd57600080fd5b8173ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200032f57600080fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050505060805160601c60a05160601c60c05160601c60e05160601c614a706200040760003980612c7452806130b4525080611f3f528061249052806127b8528061287252806128dc525080610c9152806124cc52806126fb528061277c52806128945280612fef525080612f2d52806131f9528061369452806137eb5280613848528061392f5280613ace5250614a706000f3fe6080604052600436106102255760003560e01c80637927ebf811610123578063d24378eb116100ab578063e0176de81161006f578063e0176de814610b9c578063e392a26214610bc7578063f5c2ab5b14610bf2578063f8e157ea14610c23578063fc7b9c1814610c6457610225565b8063d24378eb14610a35578063d4d863ce14610a60578063d502562514610abd578063d7ccfb0b14610b0a578063dc6549fb14610b3557610225565b806398fabd3a116100f257806398fabd3a1461087b578063ae9832cf146108bc578063b4abccba1461091d578063cd1234b314610984578063cea55f5714610a0a57610225565b80637927ebf81461076a578063844b5c7c146107b95780638dbdbe6d146107e4578063904b3ece1461085057610225565b8063451ee4a1116101b157806361d027b31161017557806361d027b31461062b57806363b3256b1461066c578063741bef1a146106bd578063759076e5146106fe57806377b818951461072957610225565b8063451ee4a1146104c857806346f68ee91461051d5780634cf088d91461056e578063507930ec146105af5780635a96ac0a1461061457610225565b80630ab69367116101f85780630ab69367146103285780631e321a0f146103915780631ed2d71a146103d95780631feed31f1461042a5780632f3f470a1461049b57610225565b8063016a42841461022a57806301b88ee81461026b5780630505c8c9146102d0578063089208d814610311575b600080fd5b34801561023657600080fd5b5061023f610c8f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561027757600080fd5b506102ba6004803603602081101561028e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cb3565b6040518082815260200191505060405180910390f35b3480156102dc57600080fd5b506102e5610d41565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561031d57600080fd5b50610326610d6a565b005b34801561033457600080fd5b5061038f600480360360a081101561034b57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190505050610ee9565b005b34801561039d57600080fd5b506103d7600480360360408110156103b457600080fd5b81019080803560ff16906020019092919080359060200190929190505050611204565b005b3480156103e557600080fd5b50610428600480360360208110156103fc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061146d565b005b34801561043657600080fd5b506104856004803603604081101561044d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050611589565b6040518082815260200191505060405180910390f35b3480156104a757600080fd5b506104b06119e1565b60405180821515815260200191505060405180910390f35b3480156104d457600080fd5b506104dd6119f4565b6040518086151581526020018581526020018481526020018363ffffffff1681526020018263ffffffff1681526020019550505050505060405180910390f35b34801561052957600080fd5b5061056c6004803603602081101561054057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611a45565b005b34801561057a57600080fd5b50610583611c4a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156105bb57600080fd5b506105fe600480360360208110156105d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c70565b6040518082815260200191505060405180910390f35b34801561062057600080fd5b50610629611d97565b005b34801561063757600080fd5b50610640611f3d565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561067857600080fd5b506106bb6004803603602081101561068f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f61565b005b3480156106c957600080fd5b506106d2612120565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561070a57600080fd5b50610713612146565b6040518082815260200191505060405180910390f35b34801561073557600080fd5b5061073e612169565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561077657600080fd5b506107a36004803603602081101561078d57600080fd5b810190808035906020019092919050505061218f565b6040518082815260200191505060405180910390f35b3480156107c557600080fd5b506107ce6121c0565b6040518082815260200191505060405180910390f35b61083a600480360360608110156107fa57600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506121fd565b6040518082815260200191505060405180910390f35b34801561085c57600080fd5b50610865612b99565b6040518082815260200191505060405180910390f35b34801561088757600080fd5b50610890612c72565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108c857600080fd5b5061091b600480360360808110156108df57600080fd5b810190808035151590602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190505050612c96565b005b34801561092957600080fd5b5061096c6004803603602081101561094057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612f29565b60405180821515815260200191505060405180910390f35b34801561099057600080fd5b506109d3600480360360208110156109a757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506131a4565b604051808581526020018481526020018363ffffffff1681526020018263ffffffff16815260200194505050505060405180910390f35b348015610a1657600080fd5b50610a1f6131f4565b6040518082815260200191505060405180910390f35b348015610a4157600080fd5b50610a4a6132e0565b6040518082815260200191505060405180910390f35b348015610a6c57600080fd5b50610abb60048036036040811015610a8357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035151590602001909291905050506133bb565b005b348015610ac957600080fd5b50610ad26135e7565b604051808681526020018581526020018481526020018381526020018263ffffffff1681526020019550505050505060405180910390f35b348015610b1657600080fd5b50610b1f61361b565b6040518082815260200191505060405180910390f35b348015610b4157600080fd5b50610b8460048036036020811015610b5857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613663565b60405180821515815260200191505060405180910390f35b348015610ba857600080fd5b50610bb1613683565b6040518082815260200191505060405180910390f35b348015610bd357600080fd5b50610bdc61374e565b6040518082815260200191505060405180910390f35b348015610bfe57600080fd5b50610c076137d3565b604051808263ffffffff16815260200191505060405180910390f35b348015610c2f57600080fd5b50610c386137e9565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610c7057600080fd5b50610c7961380d565b6040518082815260200191505060405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000081565b600080610cbf83611c70565b90506000600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506127108210610d1957809250610d3a565b612710610d2f838361381390919063ffffffff16565b81610d3657fe5b0492505b5050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e2b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba60405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610faa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000610fb4612146565b1461100a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806149a96021913960400191505060405180910390fd5b6028851015611081576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616e206c6f636b2061646a7573746d656e740000000000000000000000000081525060200191505060405180910390fd5b6103e88311156110f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5061796f75742063616e6e6f742062652061626f766520312070657263656e7481525060200191505060405180910390fd5b6201fa408163ffffffff16101561115b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806149ed6024913960400191505060405180910390fd5b6040518060a001604052808681526020018581526020018481526020018381526020018263ffffffff1681525060056000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548163ffffffff021916908363ffffffff16021790555090505042601060006101000a81548163ffffffff021916908363ffffffff1602179055505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146112c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600060038111156112d257fe5b8260038111156112de57fe5b1415611369576201fa40811015611340576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806149ed6024913960400191505060405180910390fd5b80600560040160006101000a81548163ffffffff021916908363ffffffff160217905550611469565b6001600381111561137657fe5b82600381111561138257fe5b141561140f576103e8811115611400576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5061796f75742063616e6e6f742062652061626f766520312070657263656e7481525060200191505060405180910390fd5b80600560020181905550611468565b6002600381111561141c57fe5b82600381111561142857fe5b141561143d5780600560030181905550611467565b60038081111561144957fe5b82600381111561145557fe5b141561146657806005600101819055505b5b5b5b5050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461152e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461162c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260028152602001807f4e4100000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6116346148d5565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681525050905060006116eb85611c70565b905061271081106117e957600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549063ffffffff02191690556002820160046101000a81549063ffffffff021916905550508473ffffffffffffffffffffffffffffffffffffffff167f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b183600001516000604051808381526020018281526020019250505060405180910390a26117e08585846000015161383f565b925050506119db565b600061271061180583856000015161381390919063ffffffff16565b8161180c57fe5b0490506040518060800160405280611831838660000151613c9690919063ffffffff16565b81526020018460200151815260200161187961186086606001514263ffffffff16613cb090919063ffffffff16565b866040015163ffffffff16613cb090919063ffffffff16565b63ffffffff1681526020014263ffffffff16815250600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548163ffffffff021916908363ffffffff16021790555060608201518160020160046101000a81548163ffffffff021916908363ffffffff1602179055509050508573ffffffffffffffffffffffffffffffffffffffff167f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b182600e60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154604051808381526020018281526020019250505060405180910390a26119d586868361383f565b93505050505b92915050565b600460149054906101000a900460ff1681565b600a8060000160009054906101000a900460ff16908060010154908060020154908060030160009054906101000a900463ffffffff16908060030160049054906101000a900463ffffffff16905085565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611b8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061493b6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba60405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000611c7a6148d5565b600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152505090506000611d4582606001514263ffffffff16613cb090919063ffffffff16565b63ffffffff1690506000826040015163ffffffff1690506000811115611d8a5780611d7b6127108461381390919063ffffffff16565b81611d8257fe5b049350611d8f565b600093505b505050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e3d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806149616022913960400191505060405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167faa151555690c956fc3ea32f106bb9f119b5237a061eaa8557cff3e51e3792c8d60405160405180910390a3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b7f000000000000000000000000000000000000000000000000000000000000000081565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612022576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156120c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260038152602001807f5a4e41000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061216461215361374e565b600f54613c9690919063ffffffff16565b905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000655af3107a40006121b16121ac846121a761361b565b613cd6565b613fb7565b816121b857fe5b049050919050565b60006121f8620f42406121ea6121d46132e0565b6121dc61361b565b61381390919063ffffffff16565b61381390919063ffffffff16565b905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156122a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f496e76616c69642061646472657373000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806123245750601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b612396576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260048152602001807f4c464e410000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61239e613ff3565b600560030154600f54111561241b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4d6178206361706163697479207265616368656400000000000000000000000081525060200191505060405180910390fd5b60006124256121c0565b90506000612431614038565b90508085101561248c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806149ca6023913960400191505060405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16631eec5a9a7f0000000000000000000000000000000000000000000000000000000000000000896040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060206040518083038186803b15801561253d57600080fd5b505afa158015612551573d6000803e3d6000fd5b505050506040513d602081101561256757600080fd5b8101908080519060200190929190505050905060006125858261218f565b905062989680811015612600576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f20736d616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b612608613683565b81111561267d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f206c6172676500000000000000000000000000000000000081525060200191505060405180910390fd5b87471061286c578734146126f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260028152602001807f554100000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0896040518263ffffffff1660e01b81526004016000604051808303818588803b15801561276157600080fd5b505af1158015612775573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb7f00000000000000000000000000000000000000000000000000000000000000008a6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561282b57600080fd5b505af115801561283f573d6000803e3d6000fd5b505050506040513d602081101561285557600080fd5b8101908080519060200190929190505050506128da565b6128d9337f00000000000000000000000000000000000000000000000000000000000000008a7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166140b4909392919063ffffffff16565b5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636a20de9230836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561296b57600080fd5b505af115801561297f573d6000803e3d6000fd5b5050505061299882600f5461417590919063ffffffff16565b600f8190555060405180608001604052806129fe83600e60008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015461417590919063ffffffff16565b8152602001858152602001600560040160009054906101000a900463ffffffff1663ffffffff1681526020014263ffffffff16815250600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548163ffffffff021916908363ffffffff16021790555060608201518160020160046101000a81548163ffffffff021916908363ffffffff16021790555090505083612b07600560040160009054906101000a900463ffffffff1663ffffffff164261417590919063ffffffff16565b827f1fec6dc81f140574bf43f6b1e420ae1dd47928b9d57db8cbd7b8611063b85ae58b6040518082815260200191505060405180910390a4612b476131f4565b612b4f614038565b612b576121c0565b7f375b221f40939bfd8f49723a17cf7bc6d576ebf72efe2cc3e991826f5b3f390a60405160405180910390a4612b8b61418f565b809450505050509392505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612c0357600080fd5b505afa158015612c17573d6000803e3d6000fd5b505050506040513d6020811015612c2d57600080fd5b810190808051906020019092919050505060ff16600a0a612c65612c4f6132e0565b612c576131f4565b61381390919063ffffffff16565b81612c6c57fe5b04905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612d57576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6103e8612d73601960056000015461381390919063ffffffff16565b81612d7a57fe5b04831115612df0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e6372656d656e7420746f6f206c617267650000000000000000000000000081525060200191505060405180910390fd5b6028821015612e67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6578742041646a7573746d656e7420636f756c64206265206c6f636b65640081525060200191505060405180910390fd5b6040518060a0016040528085151581526020018481526020018381526020018263ffffffff1681526020014263ffffffff16815250600a60008201518160000160006101000a81548160ff021916908315150217905550602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a81548163ffffffff021916908363ffffffff16021790555090505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612fed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260038152602001807f4e4154000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156130af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260038152602001807f4e4150000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61319b7f00000000000000000000000000000000000000000000000000000000000000008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561313a57600080fd5b505afa15801561314e573d6000803e3d6000fd5b505050506040513d602081101561316457600080fd5b81019080805190602001909291905050508473ffffffffffffffffffffffffffffffffffffffff1661433b9092919063ffffffff16565b60019050919050565b600e6020528060005260406000206000915090508060000154908060010154908060020160009054906101000a900463ffffffff16908060020160049054906101000a900463ffffffff16905084565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561325d57600080fd5b505afa158015613271573d6000803e3d6000fd5b505050506040513d602081101561328757600080fd5b81019080805190602001909291905050509050670de0b6b3a76400006132d26132cd6132c7633b9aca006132b9612146565b61381390919063ffffffff16565b84613cd6565b613fb7565b816132d957fe5b0491505090565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561334b57600080fd5b505afa15801561335f573d6000803e3d6000fd5b505050506040513d60a081101561337557600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291905050505050509150508091505090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461347c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561351f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260028152602001807f494100000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8015613586576001600460146101000a81548160ff02191690831515021790555081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506135e3565b6000600460146101000a81548160ff02191690831515021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5050565b60058060000154908060010154908060020154908060030154908060040160009054906101000a900463ffffffff16905085565b6000620186a061364061362c6131f4565b60056000015461381390919063ffffffff16565b8161364757fe5b0490506005600101548110156136605760056001015490505b90565b60116020528060005260406000206000915054906101000a900460ff1681565b6000620186a06137416005600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156136f857600080fd5b505afa15801561370c573d6000803e3d6000fd5b505050506040513d602081101561372257600080fd5b810190808051906020019092919050505061381390919063ffffffff16565b8161374857fe5b04905090565b60008061377c601060009054906101000a900463ffffffff164263ffffffff16613cb090919063ffffffff16565b9050600560040160009054906101000a900463ffffffff1663ffffffff166137b58263ffffffff16600f5461381390919063ffffffff16565b816137bc57fe5b049150600f548211156137cf57600f5491505b5090565b601060009054906101000a900463ffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b600f5481565b600080831480613830575081838385029250828161382d57fe5b04145b61383957600080fd5b92915050565b600082613918577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156138d757600080fd5b505af11580156138eb573d6000803e3d6000fd5b505050506040513d602081101561390157600080fd5b810190808051906020019092919050505050613c8c565b600460149054906101000a900460ff1615613acc577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156139e057600080fd5b505af11580156139f4573d6000803e3d6000fd5b505050506040513d6020811015613a0a57600080fd5b810190808051906020019092919050505050600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637acb775783866040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b158015613aaf57600080fd5b505af1158015613ac3573d6000803e3d6000fd5b50505050613c8b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015613b7f57600080fd5b505af1158015613b93573d6000803e3d6000fd5b505050506040513d6020811015613ba957600080fd5b810190808051906020019092919050505050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637acb775783866040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600087803b158015613c4e57600080fd5b505af1158015613c62573d6000803e3d6000fd5b505050506040513d6020811015613c7857600080fd5b8101908080519060200190929190505050505b5b8190509392505050565b6000828284039150811115613caa57600080fd5b92915050565b60008263ffffffff1682840391508163ffffffff161115613cd057600080fd5b92915050565b613cde614909565b60008211613d37576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806149836026913960400191505060405180910390fd5b6000831415613d7557604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509050613fb1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff71ffffffffffffffffffffffffffffffffffff168311613eae57600082607060ff1685901b81613dc257fe5b0490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16811115613e79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815250915050613fb1565b6000613eca846e010000000000000000000000000000856143dd565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16811115613f80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509150505b92915050565b60006612725dd1d243ab82600001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681613feb57fe5b049050919050565b61400f613ffe61374e565b600f54613c9690919063ffffffff16565b600f8190555042601060006101000a81548163ffffffff021916908363ffffffff160217905550565b600062989680614073633b9aca006140656140516131f4565b60056000015461381390919063ffffffff16565b61417590919063ffffffff16565b8161407a57fe5b0490506005600101548110156140975760056001015490506140b1565b6000600560010154146140b05760006005600101819055505b5b90565b61416f846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061449f565b50505050565b600082828401915081101561418957600080fd5b92915050565b60006141d4600a60030160009054906101000a900463ffffffff16600a60030160049054906101000a900463ffffffff1663ffffffff1661458e90919063ffffffff16565b63ffffffff1690506000600a60010154141580156141f25750804210155b156143385760006005600001549050600a60000160009054906101000a900460ff161561426157614236600a6001015460056000015461417590919063ffffffff16565b600560000181905550600a600201546005600001541061425c576000600a600101819055505b6142a5565b61427e600a60010154600560000154613c9690919063ffffffff16565b600560000181905550600a60020154600560000154116142a4576000600a600101819055505b5b42600a60030160046101000a81548163ffffffff021916908363ffffffff1602179055507fb923e581a0f83128e9e1d8297aa52b18d6744310476e0b54509c054cd7a93b2a81600560000154600a60010154600a60000160009054906101000a900460ff1660405180858152602001848152602001838152602001821515815260200194505050505060405180910390a1505b50565b6143d88363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061449f565b505050565b60008060006143ec86866145b4565b91509150600084806143fa57fe5b86880990508281111561440e576001820391505b8083039250848210614488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f46756c6c4d6174683a3a6d756c4469763a206f766572666c6f7700000000000081525060200191505060405180910390fd5b614493838387614607565b93505050509392505050565b6060614501826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166146a49092919063ffffffff16565b90506000815111156145895780806020019051602081101561452257600080fd5b8101908080519060200190929190505050614588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180614a11602a913960400191505060405180910390fd5b5b505050565b60008263ffffffff1682840191508163ffffffff1610156145ae57600080fd5b92915050565b60008060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff806145e157fe5b848609905083850292508281039150828110156145ff576001820391505b509250929050565b600080826000038316905080838161461b57fe5b04925080858161462757fe5b049450600181826000038161463857fe5b04018402850194506000600190508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808602925050509392505050565b60606146b384846000856146bc565b90509392505050565b60606146c7856148c2565b614739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106147895780518252602082019150602081019050602083039250614766565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146147eb576040519150601f19603f3d011682016040523d82523d6000602084013e6147f0565b606091505b509150915081156148055780925050506148ba565b6000815111156148185780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561487f578082015181840152602081019050614864565b50505050905090810190601f1680156148ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b949350505050565b600080823b905060008111915050919050565b60405180608001604052806000815260200160008152602001600063ffffffff168152602001600063ffffffff1681525090565b604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a206d757374206265206e6577206f776e657220746f2070756c6c4669786564506f696e743a3a6672616374696f6e3a206469766973696f6e206279207a65726f44656274206d757374206265203020666f7220696e697469616c697a6174696f6e536c697070616765206c696d69743a206d6f7265207468616e206d617820707269636556657374696e67206d757374206265206c6f6e676572207468616e20333620686f7572735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a26469706673582212204df0ba713b23133555d6844107438e5e66e8ad5be491f98f4909ea044653a3c864736f6c63430007050033000000000000000000000000768c665e57ee879a61a3253cb319f484489b0f9a000000000000000000000000471ece3750da237f93b8e339c536989b8978a438000000000000000000000000ce78d38e71b5a0461e1bfe945fe62aa2b88aa6d50000000000000000000000000879270f8ba78126628595bec8d10dcdad0e4c890000000000000000000000000879270f8ba78126628595bec8d10dcdad0e4c89
Deployed ByteCode
0x6080604052600436106102255760003560e01c80637927ebf811610123578063d24378eb116100ab578063e0176de81161006f578063e0176de814610b9c578063e392a26214610bc7578063f5c2ab5b14610bf2578063f8e157ea14610c23578063fc7b9c1814610c6457610225565b8063d24378eb14610a35578063d4d863ce14610a60578063d502562514610abd578063d7ccfb0b14610b0a578063dc6549fb14610b3557610225565b806398fabd3a116100f257806398fabd3a1461087b578063ae9832cf146108bc578063b4abccba1461091d578063cd1234b314610984578063cea55f5714610a0a57610225565b80637927ebf81461076a578063844b5c7c146107b95780638dbdbe6d146107e4578063904b3ece1461085057610225565b8063451ee4a1116101b157806361d027b31161017557806361d027b31461062b57806363b3256b1461066c578063741bef1a146106bd578063759076e5146106fe57806377b818951461072957610225565b8063451ee4a1146104c857806346f68ee91461051d5780634cf088d91461056e578063507930ec146105af5780635a96ac0a1461061457610225565b80630ab69367116101f85780630ab69367146103285780631e321a0f146103915780631ed2d71a146103d95780631feed31f1461042a5780632f3f470a1461049b57610225565b8063016a42841461022a57806301b88ee81461026b5780630505c8c9146102d0578063089208d814610311575b600080fd5b34801561023657600080fd5b5061023f610c8f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561027757600080fd5b506102ba6004803603602081101561028e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cb3565b6040518082815260200191505060405180910390f35b3480156102dc57600080fd5b506102e5610d41565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561031d57600080fd5b50610326610d6a565b005b34801561033457600080fd5b5061038f600480360360a081101561034b57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190505050610ee9565b005b34801561039d57600080fd5b506103d7600480360360408110156103b457600080fd5b81019080803560ff16906020019092919080359060200190929190505050611204565b005b3480156103e557600080fd5b50610428600480360360208110156103fc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061146d565b005b34801561043657600080fd5b506104856004803603604081101561044d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050611589565b6040518082815260200191505060405180910390f35b3480156104a757600080fd5b506104b06119e1565b60405180821515815260200191505060405180910390f35b3480156104d457600080fd5b506104dd6119f4565b6040518086151581526020018581526020018481526020018363ffffffff1681526020018263ffffffff1681526020019550505050505060405180910390f35b34801561052957600080fd5b5061056c6004803603602081101561054057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611a45565b005b34801561057a57600080fd5b50610583611c4a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156105bb57600080fd5b506105fe600480360360208110156105d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c70565b6040518082815260200191505060405180910390f35b34801561062057600080fd5b50610629611d97565b005b34801561063757600080fd5b50610640611f3d565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561067857600080fd5b506106bb6004803603602081101561068f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f61565b005b3480156106c957600080fd5b506106d2612120565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561070a57600080fd5b50610713612146565b6040518082815260200191505060405180910390f35b34801561073557600080fd5b5061073e612169565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561077657600080fd5b506107a36004803603602081101561078d57600080fd5b810190808035906020019092919050505061218f565b6040518082815260200191505060405180910390f35b3480156107c557600080fd5b506107ce6121c0565b6040518082815260200191505060405180910390f35b61083a600480360360608110156107fa57600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506121fd565b6040518082815260200191505060405180910390f35b34801561085c57600080fd5b50610865612b99565b6040518082815260200191505060405180910390f35b34801561088757600080fd5b50610890612c72565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108c857600080fd5b5061091b600480360360808110156108df57600080fd5b810190808035151590602001909291908035906020019092919080359060200190929190803563ffffffff169060200190929190505050612c96565b005b34801561092957600080fd5b5061096c6004803603602081101561094057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612f29565b60405180821515815260200191505060405180910390f35b34801561099057600080fd5b506109d3600480360360208110156109a757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506131a4565b604051808581526020018481526020018363ffffffff1681526020018263ffffffff16815260200194505050505060405180910390f35b348015610a1657600080fd5b50610a1f6131f4565b6040518082815260200191505060405180910390f35b348015610a4157600080fd5b50610a4a6132e0565b6040518082815260200191505060405180910390f35b348015610a6c57600080fd5b50610abb60048036036040811015610a8357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035151590602001909291905050506133bb565b005b348015610ac957600080fd5b50610ad26135e7565b604051808681526020018581526020018481526020018381526020018263ffffffff1681526020019550505050505060405180910390f35b348015610b1657600080fd5b50610b1f61361b565b6040518082815260200191505060405180910390f35b348015610b4157600080fd5b50610b8460048036036020811015610b5857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613663565b60405180821515815260200191505060405180910390f35b348015610ba857600080fd5b50610bb1613683565b6040518082815260200191505060405180910390f35b348015610bd357600080fd5b50610bdc61374e565b6040518082815260200191505060405180910390f35b348015610bfe57600080fd5b50610c076137d3565b604051808263ffffffff16815260200191505060405180910390f35b348015610c2f57600080fd5b50610c386137e9565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610c7057600080fd5b50610c7961380d565b6040518082815260200191505060405180910390f35b7f000000000000000000000000471ece3750da237f93b8e339c536989b8978a43881565b600080610cbf83611c70565b90506000600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506127108210610d1957809250610d3a565b612710610d2f838361381390919063ffffffff16565b81610d3657fe5b0492505b5050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610e2b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba60405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610faa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000610fb4612146565b1461100a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806149a96021913960400191505060405180910390fd5b6028851015611081576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616e206c6f636b2061646a7573746d656e740000000000000000000000000081525060200191505060405180910390fd5b6103e88311156110f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5061796f75742063616e6e6f742062652061626f766520312070657263656e7481525060200191505060405180910390fd5b6201fa408163ffffffff16101561115b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806149ed6024913960400191505060405180910390fd5b6040518060a001604052808681526020018581526020018481526020018381526020018263ffffffff1681525060056000820151816000015560208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548163ffffffff021916908363ffffffff16021790555090505042601060006101000a81548163ffffffff021916908363ffffffff1602179055505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146112c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600060038111156112d257fe5b8260038111156112de57fe5b1415611369576201fa40811015611340576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806149ed6024913960400191505060405180910390fd5b80600560040160006101000a81548163ffffffff021916908363ffffffff160217905550611469565b6001600381111561137657fe5b82600381111561138257fe5b141561140f576103e8811115611400576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5061796f75742063616e6e6f742062652061626f766520312070657263656e7481525060200191505060405180910390fd5b80600560020181905550611468565b6002600381111561141c57fe5b82600381111561142857fe5b141561143d5780600560030181905550611467565b60038081111561144957fe5b82600381111561145557fe5b141561146657806005600101819055505b5b5b5b5050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461152e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461162c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260028152602001807f4e4100000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6116346148d5565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681525050905060006116eb85611c70565b905061271081106117e957600e60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160006101000a81549063ffffffff02191690556002820160046101000a81549063ffffffff021916905550508473ffffffffffffffffffffffffffffffffffffffff167f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b183600001516000604051808381526020018281526020019250505060405180910390a26117e08585846000015161383f565b925050506119db565b600061271061180583856000015161381390919063ffffffff16565b8161180c57fe5b0490506040518060800160405280611831838660000151613c9690919063ffffffff16565b81526020018460200151815260200161187961186086606001514263ffffffff16613cb090919063ffffffff16565b866040015163ffffffff16613cb090919063ffffffff16565b63ffffffff1681526020014263ffffffff16815250600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548163ffffffff021916908363ffffffff16021790555060608201518160020160046101000a81548163ffffffff021916908363ffffffff1602179055509050508573ffffffffffffffffffffffffffffffffffffffff167f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b182600e60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154604051808381526020018281526020019250505060405180910390a26119d586868361383f565b93505050505b92915050565b600460149054906101000a900460ff1681565b600a8060000160009054906101000a900460ff16908060010154908060020154908060030160009054906101000a900463ffffffff16908060030160049054906101000a900463ffffffff16905085565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611b8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061493b6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba60405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000611c7a6148d5565b600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152505090506000611d4582606001514263ffffffff16613cb090919063ffffffff16565b63ffffffff1690506000826040015163ffffffff1690506000811115611d8a5780611d7b6127108461381390919063ffffffff16565b81611d8257fe5b049350611d8f565b600093505b505050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e3d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806149616022913960400191505060405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167faa151555690c956fc3ea32f106bb9f119b5237a061eaa8557cff3e51e3792c8d60405160405180910390a3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b7f000000000000000000000000ce78d38e71b5a0461e1bfe945fe62aa2b88aa6d581565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612022576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156120c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260038152602001807f5a4e41000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001601160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061216461215361374e565b600f54613c9690919063ffffffff16565b905090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000655af3107a40006121b16121ac846121a761361b565b613cd6565b613fb7565b816121b857fe5b049050919050565b60006121f8620f42406121ea6121d46132e0565b6121dc61361b565b61381390919063ffffffff16565b61381390919063ffffffff16565b905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156122a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f496e76616c69642061646472657373000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806123245750601160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b612396576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260048152602001807f4c464e410000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61239e613ff3565b600560030154600f54111561241b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4d6178206361706163697479207265616368656400000000000000000000000081525060200191505060405180910390fd5b60006124256121c0565b90506000612431614038565b90508085101561248c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806149ca6023913960400191505060405180910390fd5b60007f000000000000000000000000ce78d38e71b5a0461e1bfe945fe62aa2b88aa6d573ffffffffffffffffffffffffffffffffffffffff16631eec5a9a7f000000000000000000000000471ece3750da237f93b8e339c536989b8978a438896040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060206040518083038186803b15801561253d57600080fd5b505afa158015612551573d6000803e3d6000fd5b505050506040513d602081101561256757600080fd5b8101908080519060200190929190505050905060006125858261218f565b905062989680811015612600576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f20736d616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b612608613683565b81111561267d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f206c6172676500000000000000000000000000000000000081525060200191505060405180910390fd5b87471061286c578734146126f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260028152602001807f554100000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b7f000000000000000000000000471ece3750da237f93b8e339c536989b8978a43873ffffffffffffffffffffffffffffffffffffffff1663d0e30db0896040518263ffffffff1660e01b81526004016000604051808303818588803b15801561276157600080fd5b505af1158015612775573d6000803e3d6000fd5b50505050507f000000000000000000000000471ece3750da237f93b8e339c536989b8978a43873ffffffffffffffffffffffffffffffffffffffff1663a9059cbb7f000000000000000000000000ce78d38e71b5a0461e1bfe945fe62aa2b88aa6d58a6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561282b57600080fd5b505af115801561283f573d6000803e3d6000fd5b505050506040513d602081101561285557600080fd5b8101908080519060200190929190505050506128da565b6128d9337f000000000000000000000000ce78d38e71b5a0461e1bfe945fe62aa2b88aa6d58a7f000000000000000000000000471ece3750da237f93b8e339c536989b8978a43873ffffffffffffffffffffffffffffffffffffffff166140b4909392919063ffffffff16565b5b7f000000000000000000000000ce78d38e71b5a0461e1bfe945fe62aa2b88aa6d573ffffffffffffffffffffffffffffffffffffffff16636a20de9230836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561296b57600080fd5b505af115801561297f573d6000803e3d6000fd5b5050505061299882600f5461417590919063ffffffff16565b600f8190555060405180608001604052806129fe83600e60008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015461417590919063ffffffff16565b8152602001858152602001600560040160009054906101000a900463ffffffff1663ffffffff1681526020014263ffffffff16815250600e60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548163ffffffff021916908363ffffffff16021790555060608201518160020160046101000a81548163ffffffff021916908363ffffffff16021790555090505083612b07600560040160009054906101000a900463ffffffff1663ffffffff164261417590919063ffffffff16565b827f1fec6dc81f140574bf43f6b1e420ae1dd47928b9d57db8cbd7b8611063b85ae58b6040518082815260200191505060405180910390a4612b476131f4565b612b4f614038565b612b576121c0565b7f375b221f40939bfd8f49723a17cf7bc6d576ebf72efe2cc3e991826f5b3f390a60405160405180910390a4612b8b61418f565b809450505050509392505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612c0357600080fd5b505afa158015612c17573d6000803e3d6000fd5b505050506040513d6020811015612c2d57600080fd5b810190808051906020019092919050505060ff16600a0a612c65612c4f6132e0565b612c576131f4565b61381390919063ffffffff16565b81612c6c57fe5b04905090565b7f0000000000000000000000000879270f8ba78126628595bec8d10dcdad0e4c8981565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612d57576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6103e8612d73601960056000015461381390919063ffffffff16565b81612d7a57fe5b04831115612df0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e6372656d656e7420746f6f206c617267650000000000000000000000000081525060200191505060405180910390fd5b6028821015612e67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6578742041646a7573746d656e7420636f756c64206265206c6f636b65640081525060200191505060405180910390fd5b6040518060a0016040528085151581526020018481526020018381526020018263ffffffff1681526020014263ffffffff16815250600a60008201518160000160006101000a81548160ff021916908315150217905550602082015181600101556040820151816002015560608201518160030160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160030160046101000a81548163ffffffff021916908363ffffffff16021790555090505050505050565b60007f000000000000000000000000768c665e57ee879a61a3253cb319f484489b0f9a73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612fed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260038152602001807f4e4154000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b7f000000000000000000000000471ece3750da237f93b8e339c536989b8978a43873ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156130af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260038152602001807f4e4150000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61319b7f0000000000000000000000000879270f8ba78126628595bec8d10dcdad0e4c898373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561313a57600080fd5b505afa15801561314e573d6000803e3d6000fd5b505050506040513d602081101561316457600080fd5b81019080805190602001909291905050508473ffffffffffffffffffffffffffffffffffffffff1661433b9092919063ffffffff16565b60019050919050565b600e6020528060005260406000206000915090508060000154908060010154908060020160009054906101000a900463ffffffff16908060020160049054906101000a900463ffffffff16905084565b6000807f000000000000000000000000768c665e57ee879a61a3253cb319f484489b0f9a73ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561325d57600080fd5b505afa158015613271573d6000803e3d6000fd5b505050506040513d602081101561328757600080fd5b81019080805190602001909291905050509050670de0b6b3a76400006132d26132cd6132c7633b9aca006132b9612146565b61381390919063ffffffff16565b84613cd6565b613fb7565b816132d957fe5b0491505090565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561334b57600080fd5b505afa15801561335f573d6000803e3d6000fd5b505050506040513d60a081101561337557600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291905050505050509150508091505090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461347c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561351f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260028152602001807f494100000000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8015613586576001600460146101000a81548160ff02191690831515021790555081600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506135e3565b6000600460146101000a81548160ff02191690831515021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5050565b60058060000154908060010154908060020154908060030154908060040160009054906101000a900463ffffffff16905085565b6000620186a061364061362c6131f4565b60056000015461381390919063ffffffff16565b8161364757fe5b0490506005600101548110156136605760056001015490505b90565b60116020528060005260406000206000915054906101000a900460ff1681565b6000620186a06137416005600201547f000000000000000000000000768c665e57ee879a61a3253cb319f484489b0f9a73ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156136f857600080fd5b505afa15801561370c573d6000803e3d6000fd5b505050506040513d602081101561372257600080fd5b810190808051906020019092919050505061381390919063ffffffff16565b8161374857fe5b04905090565b60008061377c601060009054906101000a900463ffffffff164263ffffffff16613cb090919063ffffffff16565b9050600560040160009054906101000a900463ffffffff1663ffffffff166137b58263ffffffff16600f5461381390919063ffffffff16565b816137bc57fe5b049150600f548211156137cf57600f5491505b5090565b601060009054906101000a900463ffffffff1681565b7f000000000000000000000000768c665e57ee879a61a3253cb319f484489b0f9a81565b600f5481565b600080831480613830575081838385029250828161382d57fe5b04145b61383957600080fd5b92915050565b600082613918577f000000000000000000000000768c665e57ee879a61a3253cb319f484489b0f9a73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156138d757600080fd5b505af11580156138eb573d6000803e3d6000fd5b505050506040513d602081101561390157600080fd5b810190808051906020019092919050505050613c8c565b600460149054906101000a900460ff1615613acc577f000000000000000000000000768c665e57ee879a61a3253cb319f484489b0f9a73ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156139e057600080fd5b505af11580156139f4573d6000803e3d6000fd5b505050506040513d6020811015613a0a57600080fd5b810190808051906020019092919050505050600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637acb775783866040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b158015613aaf57600080fd5b505af1158015613ac3573d6000803e3d6000fd5b50505050613c8b565b7f000000000000000000000000768c665e57ee879a61a3253cb319f484489b0f9a73ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015613b7f57600080fd5b505af1158015613b93573d6000803e3d6000fd5b505050506040513d6020811015613ba957600080fd5b810190808051906020019092919050505050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637acb775783866040518363ffffffff1660e01b8152600401808381526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600087803b158015613c4e57600080fd5b505af1158015613c62573d6000803e3d6000fd5b505050506040513d6020811015613c7857600080fd5b8101908080519060200190929190505050505b5b8190509392505050565b6000828284039150811115613caa57600080fd5b92915050565b60008263ffffffff1682840391508163ffffffff161115613cd057600080fd5b92915050565b613cde614909565b60008211613d37576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806149836026913960400191505060405180910390fd5b6000831415613d7557604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509050613fb1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff71ffffffffffffffffffffffffffffffffffff168311613eae57600082607060ff1685901b81613dc257fe5b0490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16811115613e79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815250915050613fb1565b6000613eca846e010000000000000000000000000000856143dd565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16811115613f80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509150505b92915050565b60006612725dd1d243ab82600001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681613feb57fe5b049050919050565b61400f613ffe61374e565b600f54613c9690919063ffffffff16565b600f8190555042601060006101000a81548163ffffffff021916908363ffffffff160217905550565b600062989680614073633b9aca006140656140516131f4565b60056000015461381390919063ffffffff16565b61417590919063ffffffff16565b8161407a57fe5b0490506005600101548110156140975760056001015490506140b1565b6000600560010154146140b05760006005600101819055505b5b90565b61416f846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061449f565b50505050565b600082828401915081101561418957600080fd5b92915050565b60006141d4600a60030160009054906101000a900463ffffffff16600a60030160049054906101000a900463ffffffff1663ffffffff1661458e90919063ffffffff16565b63ffffffff1690506000600a60010154141580156141f25750804210155b156143385760006005600001549050600a60000160009054906101000a900460ff161561426157614236600a6001015460056000015461417590919063ffffffff16565b600560000181905550600a600201546005600001541061425c576000600a600101819055505b6142a5565b61427e600a60010154600560000154613c9690919063ffffffff16565b600560000181905550600a60020154600560000154116142a4576000600a600101819055505b5b42600a60030160046101000a81548163ffffffff021916908363ffffffff1602179055507fb923e581a0f83128e9e1d8297aa52b18d6744310476e0b54509c054cd7a93b2a81600560000154600a60010154600a60000160009054906101000a900460ff1660405180858152602001848152602001838152602001821515815260200194505050505060405180910390a1505b50565b6143d88363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061449f565b505050565b60008060006143ec86866145b4565b91509150600084806143fa57fe5b86880990508281111561440e576001820391505b8083039250848210614488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f46756c6c4d6174683a3a6d756c4469763a206f766572666c6f7700000000000081525060200191505060405180910390fd5b614493838387614607565b93505050509392505050565b6060614501826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166146a49092919063ffffffff16565b90506000815111156145895780806020019051602081101561452257600080fd5b8101908080519060200190929190505050614588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180614a11602a913960400191505060405180910390fd5b5b505050565b60008263ffffffff1682840191508163ffffffff1610156145ae57600080fd5b92915050565b60008060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff806145e157fe5b848609905083850292508281039150828110156145ff576001820391505b509250929050565b600080826000038316905080838161461b57fe5b04925080858161462757fe5b049450600181826000038161463857fe5b04018402850194506000600190508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808602925050509392505050565b60606146b384846000856146bc565b90509392505050565b60606146c7856148c2565b614739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106147895780518252602082019150602081019050602083039250614766565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146147eb576040519150601f19603f3d011682016040523d82523d6000602084013e6147f0565b606091505b509150915081156148055780925050506148ba565b6000815111156148185780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561487f578082015181840152602081019050614864565b50505050905090810190601f1680156148ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b949350505050565b600080823b905060008111915050919050565b60405180608001604052806000815260200160008152602001600063ffffffff168152602001600063ffffffff1681525090565b604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a206d757374206265206e6577206f776e657220746f2070756c6c4669786564506f696e743a3a6672616374696f6e3a206469766973696f6e206279207a65726f44656274206d757374206265203020666f7220696e697469616c697a6174696f6e536c697070616765206c696d69743a206d6f7265207468616e206d617820707269636556657374696e67206d757374206265206c6f6e676572207468616e20333620686f7572735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a26469706673582212204df0ba713b23133555d6844107438e5e66e8ad5be491f98f4909ea044653a3c864736f6c63430007050033