Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 internal transactions (View All)
Advanced mode:
Loading...
Loading
Contract Name:
OlympusProFactory
Compiler Version
v0.7.5+commit.eb77ed08
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-09-23 */ // File contracts/interfaces/IOlympusProFactoryStorage.sol pragma solidity 0.7.5; interface IOlympusProFactoryStorage { function pushBond(address _payoutToken, address _principleToken, address _customTreasury, address _customBond, address _initialOwner, uint[] calldata _tierCeilings, uint[] calldata _fees) external returns(address _treasury, address _bond); } // File contracts/types/Ownable.sol pragma solidity 0.7.5; contract Ownable { address public policy; constructor () { policy = msg.sender; } modifier onlyPolicy() { require( policy == msg.sender, "Ownable: caller is not the owner" ); _; } function transferManagment(address _newOwner) external onlyPolicy() { require( _newOwner != address(0) ); policy = _newOwner; } } // File contracts/libraries/SafeMath.sol pragma solidity 0.7.5; library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; return c; } function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } function sqrrt(uint256 a) internal pure returns (uint c) { if (a > 3) { c = a; uint b = add( div( a, 2), 1 ); while (b < c) { c = b; b = div( add( div( a, b ), b), 2 ); } } else if (a != 0) { c = 1; } } } // File contracts/libraries/Address.sol pragma solidity 0.7.5; 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); } } // File contracts/interfaces/IERC20.sol pragma solidity 0.7.5; 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); } // File contracts/libraries/SafeERC20.sol pragma solidity 0.7.5; library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } 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"); } } } // File contracts/libraries/FullMath.sol pragma solidity 0.7.5; 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); } } // File contracts/libraries/FixedPoint.sol pragma solidity 0.7.5; library Babylonian { function sqrt(uint256 x) internal pure returns (uint256) { if (x == 0) return 0; uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return (r < r1 ? r : r1); } } library BitMath { function mostSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0, 'BitMath::mostSignificantBit: zero'); if (x >= 0x100000000000000000000000000000000) { x >>= 128; r += 128; } if (x >= 0x10000000000000000) { x >>= 64; r += 64; } if (x >= 0x100000000) { x >>= 32; r += 32; } if (x >= 0x10000) { x >>= 16; r += 16; } if (x >= 0x100) { x >>= 8; r += 8; } if (x >= 0x10) { x >>= 4; r += 4; } if (x >= 0x4) { x >>= 2; r += 2; } if (x >= 0x2) r += 1; } } 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)); } } // square root of a UQ112x112 // lossy between 0/1 and 40 bits function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) { if (self._x <= uint144(-1)) { return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << 112))); } uint8 safeShiftBits = 255 - BitMath.mostSignificantBit(self._x); safeShiftBits -= safeShiftBits % 2; return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << safeShiftBits) << ((112 - safeShiftBits) / 2))); } } // File contracts/interfaces/ITreasury.sol pragma solidity 0.7.5; interface ITreasury { function deposit(address _principleTokenAddress, uint _amountPrincipleToken, uint _amountPayoutToken) external; function valueOfToken( address _principleTokenAddress, uint _amount ) external view returns ( uint value_ ); } // File contracts/OlympusProCustomBond.sol pragma solidity 0.7.5; contract CustomBond is Ownable { using FixedPoint for *; using SafeERC20 for IERC20; using SafeMath for uint; /* ======== EVENTS ======== */ event BondCreated( uint deposit, uint payout, uint expires ); event BondRedeemed( address recipient, uint payout, uint remaining ); event BondPriceChanged( uint internalPrice, uint debtRatio ); event ControlVariableAdjustment( uint initialBCV, uint newBCV, uint adjustment, bool addition ); /* ======== STATE VARIABLES ======== */ IERC20 immutable payoutToken; // token paid for principal IERC20 immutable principalToken; // inflow token ITreasury immutable customTreasury; // pays for and receives principal address immutable olympusDAO; address olympusTreasury; // receives fee uint public totalPrincipalBonded; uint public totalPayoutGiven; Terms public terms; // stores terms for new bonds Adjust public adjustment; // stores adjustment to BCV data FeeTiers[] private feeTiers; // stores fee tiers mapping( address => Bond ) public bondInfo; // stores bond information for depositors uint public totalDebt; // total value of outstanding bonds; used for pricing uint public lastDecay; // reference block for debt decay address immutable subsidyRouter; // pays subsidy in OHM to custom treasury uint payoutSinceLastSubsidy; // principal accrued since subsidy paid /* ======== STRUCTS ======== */ struct FeeTiers { uint tierCeilings; // principal bonded till next tier uint fees; // in ten-thousandths (i.e. 33300 = 3.33%) } // Info for creating new bonds struct Terms { uint controlVariable; // scaling variable for price uint vestingTerm; // in blocks uint minimumPrice; // vs principal value uint maxPayout; // in thousandths of a %. i.e. 500 = 0.5% uint maxDebt; // payout token decimal debt ratio, max % total supply created as debt } // Info for bond holder struct Bond { uint payout; // payout token remaining to be paid uint vesting; // Blocks left to vest uint lastBlock; // Last interaction uint truePricePaid; // Price paid (principal tokens per payout token) in ten-millionths - 4000000 = 0.4 } // Info for incremental adjustments to control variable struct Adjust { bool add; // addition or subtraction uint rate; // increment uint target; // BCV when adjustment finished uint buffer; // minimum length (in blocks) between adjustments uint lastBlock; // block when last adjustment made } /* ======== CONSTRUCTOR ======== */ constructor( address _customTreasury, address _payoutToken, address _principalToken, address _olympusTreasury, address _subsidyRouter, address _initialOwner, address _olympusDAO, uint[] memory _tierCeilings, uint[] memory _fees ) { require( _customTreasury != address(0) ); customTreasury = ITreasury( _customTreasury ); require( _payoutToken != address(0) ); payoutToken = IERC20( _payoutToken ); require( _principalToken != address(0) ); principalToken = IERC20( _principalToken ); require( _olympusTreasury != address(0) ); olympusTreasury = _olympusTreasury; require( _subsidyRouter != address(0) ); subsidyRouter = _subsidyRouter; require( _initialOwner != address(0) ); policy = _initialOwner; require( _olympusDAO != address(0) ); olympusDAO = _olympusDAO; require(_tierCeilings.length == _fees.length, "tier length and fee length not the same"); for(uint i; i < _tierCeilings.length; i++) { feeTiers.push( FeeTiers({ tierCeilings: _tierCeilings[i], fees: _fees[i] })); } } /* ======== INITIALIZATION ======== */ /** * @notice initializes bond parameters * @param _controlVariable uint * @param _vestingTerm uint * @param _minimumPrice uint * @param _maxPayout uint * @param _maxDebt uint * @param _initialDebt uint */ function initializeBond( uint _controlVariable, uint _vestingTerm, uint _minimumPrice, uint _maxPayout, uint _maxDebt, uint _initialDebt ) external onlyPolicy() { require( currentDebt() == 0, "Debt must be 0 for initialization" ); terms = Terms ({ controlVariable: _controlVariable, vestingTerm: _vestingTerm, minimumPrice: _minimumPrice, maxPayout: _maxPayout, maxDebt: _maxDebt }); totalDebt = _initialDebt; lastDecay = block.number; } /* ======== POLICY FUNCTIONS ======== */ enum PARAMETER { VESTING, PAYOUT, DEBT } /** * @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 >= 10000, "Vesting must be longer than 36 hours" ); terms.vestingTerm = _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; } } /** * @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, uint _buffer ) external onlyPolicy() { require( _increment <= terms.controlVariable.mul( 30 ).div( 1000 ), "Increment too large" ); adjustment = Adjust({ add: _addition, rate: _increment, target: _target, buffer: _buffer, lastBlock: block.number }); } /** * @notice change address of Olympus Treasury * @param _olympusTreasury uint */ function changeOlympusTreasury(address _olympusTreasury) external { require( msg.sender == olympusDAO, "Only Olympus DAO" ); olympusTreasury = _olympusTreasury; } /** * @notice subsidy controller checks payouts since last subsidy and resets counter * @return payoutSinceLastSubsidy_ uint */ function paySubsidy() external returns ( uint payoutSinceLastSubsidy_ ) { require( msg.sender == subsidyRouter, "Only subsidy controller" ); payoutSinceLastSubsidy_ = payoutSinceLastSubsidy; payoutSinceLastSubsidy = 0; } /* ======== 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 returns (uint) { require( _depositor != address(0), "Invalid address" ); decayDebt(); require( totalDebt <= terms.maxDebt, "Max capacity reached" ); uint nativePrice = trueBondPrice(); require( _maxPrice >= nativePrice, "Slippage limit: more than max price" ); // slippage protection uint value = customTreasury.valueOfToken( address(principalToken), _amount ); uint payout = _payoutFor( value ); // payout to bonder is computed require( payout >= 10 ** payoutToken.decimals() / 100, "Bond too small" ); // must be > 0.01 payout token ( underflow protection ) require( payout <= maxPayout(), "Bond too large"); // size protection because there is no slippage // profits are calculated uint fee = payout.mul( currentOlympusFee() ).div( 1e6 ); /** principal is transferred in approved and deposited into the treasury, returning (_amount - profit) payout token */ principalToken.safeTransferFrom( msg.sender, address(this), _amount ); principalToken.approve( address(customTreasury), _amount ); customTreasury.deposit( address(principalToken), _amount, payout ); if ( fee != 0 ) { // fee is transferred to dao payoutToken.transfer(olympusTreasury, fee); } // total debt is increased totalDebt = totalDebt.add( value ); // depositor info is stored bondInfo[ _depositor ] = Bond({ payout: bondInfo[ _depositor ].payout.add( payout.sub(fee) ), vesting: terms.vestingTerm, lastBlock: block.number, truePricePaid: trueBondPrice() }); // indexed events are emitted emit BondCreated( _amount, payout, block.number.add( terms.vestingTerm ) ); emit BondPriceChanged( _bondPrice(), debtRatio() ); totalPrincipalBonded = totalPrincipalBonded.add(_amount); // total bonded increased totalPayoutGiven = totalPayoutGiven.add(payout); // total payout increased payoutSinceLastSubsidy = payoutSinceLastSubsidy.add( payout ); // subsidy counter increased adjust(); // control variable is adjusted return payout; } /** * @notice redeem bond for user * @return uint */ function redeem(address _depositor) external returns (uint) { Bond memory info = bondInfo[ _depositor ]; uint percentVested = percentVestedFor( _depositor ); // (blocks since last interaction / vesting term remaining) if ( percentVested >= 10000 ) { // if fully vested delete bondInfo[ _depositor ]; // delete user info emit BondRedeemed( _depositor, info.payout, 0 ); // emit bond data payoutToken.transfer( _depositor, info.payout ); return info.payout; } else { // if unfinished // calculate payout vested uint payout = info.payout.mul( percentVested ).div( 10000 ); // store updated deposit info bondInfo[ _depositor ] = Bond({ payout: info.payout.sub( payout ), vesting: info.vesting.sub( block.number.sub( info.lastBlock ) ), lastBlock: block.number, truePricePaid: info.truePricePaid }); emit BondRedeemed( _depositor, payout, bondInfo[ _depositor ].payout ); payoutToken.transfer( _depositor, payout ); return payout; } } /* ======== INTERNAL HELPER FUNCTIONS ======== */ /** * @notice makes incremental adjustment to control variable */ function adjust() internal { uint blockCanAdjust = adjustment.lastBlock.add( adjustment.buffer ); if( adjustment.rate != 0 && block.number >= blockCanAdjust ) { 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.lastBlock = block.number; emit ControlVariableAdjustment( initial, terms.controlVariable, adjustment.rate, adjustment.add ); } } /** * @notice reduce total debt */ function decayDebt() internal { totalDebt = totalDebt.sub( debtDecay() ); lastDecay = block.number; } /** * @notice calculate current bond price and remove floor if above * @return price_ uint */ function _bondPrice() internal returns ( uint price_ ) { price_ = terms.controlVariable.mul( debtRatio() ).div( 10 ** (uint256(payoutToken.decimals()).sub(5)) ); if ( price_ < terms.minimumPrice ) { price_ = terms.minimumPrice; } else if ( terms.minimumPrice != 0 ) { terms.minimumPrice = 0; } } /* ======== VIEW FUNCTIONS ======== */ /** * @notice calculate current bond premium * @return price_ uint */ function bondPrice() public view returns ( uint price_ ) { price_ = terms.controlVariable.mul( debtRatio() ).div( 10 ** (uint256(payoutToken.decimals()).sub(5)) ); if ( price_ < terms.minimumPrice ) { price_ = terms.minimumPrice; } } /** * @notice calculate true bond price a user pays * @return price_ uint */ function trueBondPrice() public view returns ( uint price_ ) { price_ = bondPrice().add(bondPrice().mul( currentOlympusFee() ).div( 1e6 ) ); } /** * @notice determine maximum bond size * @return uint */ function maxPayout() public view returns ( uint ) { return payoutToken.totalSupply().mul( terms.maxPayout ).div( 100000 ); } /** * @notice calculate total interest due for new bond * @param _value uint * @return uint */ function _payoutFor( uint _value ) internal view returns ( uint ) { return FixedPoint.fraction( _value, bondPrice() ).decode112with18().div( 1e11 ); } /** * @notice calculate user's interest due for new bond, accounting for Olympus Fee * @param _value uint * @return uint */ function payoutFor( uint _value ) external view returns ( uint ) { uint total = FixedPoint.fraction( _value, bondPrice() ).decode112with18().div( 1e11 ); return total.sub(total.mul( currentOlympusFee() ).div( 1e6 )); } /** * @notice calculate current ratio of debt to payout token supply * @notice protocols using Olympus Pro should be careful when quickly adding large %s to total supply * @return debtRatio_ uint */ function debtRatio() public view returns ( uint debtRatio_ ) { debtRatio_ = FixedPoint.fraction( currentDebt().mul( 10 ** payoutToken.decimals() ), payoutToken.totalSupply() ).decode112with18().div( 1e18 ); } /** * @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_ ) { uint blocksSinceLast = block.number.sub( lastDecay ); decay_ = totalDebt.mul( blocksSinceLast ).div( 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 blocksSinceLast = block.number.sub( bond.lastBlock ); uint vesting = bond.vesting; if ( vesting > 0 ) { percentVested_ = blocksSinceLast.mul( 10000 ).div( vesting ); } else { percentVested_ = 0; } } /** * @notice calculate amount of payout token 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 ).div( 10000 ); } } /** * @notice current fee Olympus takes of each bond * @return currentFee_ uint */ function currentOlympusFee() public view returns( uint currentFee_ ) { uint tierLength = feeTiers.length; for(uint i; i < tierLength; i++) { if(totalPrincipalBonded < feeTiers[i].tierCeilings || i == tierLength - 1 ) { return feeTiers[i].fees; } } } } // File contracts/OlympusProCustomTreasury.sol pragma solidity 0.7.5; contract CustomTreasury is Ownable { /* ======== DEPENDENCIES ======== */ using SafeERC20 for IERC20; using SafeMath for uint; /* ======== STATE VARIABLS ======== */ address public immutable payoutToken; mapping(address => bool) public bondContract; /* ======== EVENTS ======== */ event BondContractToggled(address bondContract, bool approved); event Withdraw(address token, address destination, uint amount); /* ======== CONSTRUCTOR ======== */ constructor(address _payoutToken, address _initialOwner) { require( _payoutToken != address(0) ); payoutToken = _payoutToken; require( _initialOwner != address(0) ); policy = _initialOwner; } /* ======== BOND CONTRACT FUNCTION ======== */ /** * @notice deposit principle token and recieve back payout token * @param _principleTokenAddress address * @param _amountPrincipleToken uint * @param _amountPayoutToken uint */ function deposit(address _principleTokenAddress, uint _amountPrincipleToken, uint _amountPayoutToken) external { require(bondContract[msg.sender], "msg.sender is not a bond contract"); IERC20(_principleTokenAddress).safeTransferFrom(msg.sender, address(this), _amountPrincipleToken); IERC20(payoutToken).safeTransfer(msg.sender, _amountPayoutToken); } /* ======== VIEW FUNCTION ======== */ /** * @notice returns payout token valuation of priciple * @param _principleTokenAddress address * @param _amount uint * @return value_ uint */ function valueOfToken( address _principleTokenAddress, uint _amount ) public view returns ( uint value_ ) { // convert amount to match payout token decimals value_ = _amount.mul( 10 ** IERC20( payoutToken ).decimals() ).div( 10 ** IERC20( _principleTokenAddress ).decimals() ); } /* ======== POLICY FUNCTIONS ======== */ /** * @notice policy can withdraw ERC20 token to desired address * @param _token uint * @param _destination address * @param _amount uint */ function withdraw(address _token, address _destination, uint _amount) external onlyPolicy() { IERC20(_token).safeTransfer(_destination, _amount); emit Withdraw(_token, _destination, _amount); } /** @notice toggle bond contract @param _bondContract address */ function toggleBondContract(address _bondContract) external onlyPolicy() { bondContract[_bondContract] = !bondContract[_bondContract]; emit BondContractToggled(_bondContract, bondContract[_bondContract]); } } // File contracts/OlympusProFactory.sol // SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.7.5; contract OlympusProFactory is Ownable { /* ======== STATE VARIABLS ======== */ address immutable public olympusTreasury; address immutable public olympusProFactoryStorage; address immutable public olumpusProSubsidyRouter; address immutable public olympusDAO; /* ======== CONSTRUCTION ======== */ constructor(address _olympusTreasury, address _olympusProFactoryStorage, address _olumpusProSubsidyRouter, address _olympusDAO) { require( _olympusTreasury != address(0) ); olympusTreasury = _olympusTreasury; require( _olympusProFactoryStorage != address(0) ); olympusProFactoryStorage = _olympusProFactoryStorage; require( _olumpusProSubsidyRouter != address(0) ); olumpusProSubsidyRouter = _olumpusProSubsidyRouter; require( _olympusDAO != address(0) ); olympusDAO = _olympusDAO; } /* ======== POLICY FUNCTIONS ======== */ /** @notice deploys custom treasury and custom bond contracts and returns address of both @param _payoutToken address @param _principleToken address @param _initialOwner address @return _treasury address @return _bond address */ function createBondAndTreasury(address _payoutToken, address _principleToken, address _initialOwner, uint[] calldata _tierCeilings, uint[] calldata _fees) external onlyPolicy() returns(address _treasury, address _bond) { CustomTreasury treasury = new CustomTreasury(_payoutToken, _initialOwner); CustomBond bond = new CustomBond(address(treasury), _payoutToken, _principleToken, olympusTreasury, olumpusProSubsidyRouter, _initialOwner, olympusDAO, _tierCeilings, _fees); return IOlympusProFactoryStorage(olympusProFactoryStorage).pushBond( _payoutToken, _principleToken, address(treasury), address(bond), _initialOwner, _tierCeilings, _fees ); } /** @notice deploys custom treasury and custom bond contracts and returns address of both @param _payoutToken address @param _principleToken address @param _customTreasury address @param _initialOwner address @return _treasury address @return _bond address */ function createBond(address _payoutToken, address _principleToken, address _customTreasury, address _initialOwner, uint[] calldata _tierCeilings, uint[] calldata _fees ) external onlyPolicy() returns(address _treasury, address _bond) { CustomBond bond = new CustomBond(_customTreasury, _payoutToken, _principleToken, _customTreasury, olumpusProSubsidyRouter, _initialOwner, olympusDAO, _tierCeilings, _fees); return IOlympusProFactoryStorage(olympusProFactoryStorage).pushBond( _payoutToken, _principleToken, _customTreasury, address(bond), _initialOwner, _tierCeilings, _fees ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_olympusTreasury","type":"address"},{"internalType":"address","name":"_olympusProFactoryStorage","type":"address"},{"internalType":"address","name":"_olumpusProSubsidyRouter","type":"address"},{"internalType":"address","name":"_olympusDAO","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_payoutToken","type":"address"},{"internalType":"address","name":"_principleToken","type":"address"},{"internalType":"address","name":"_customTreasury","type":"address"},{"internalType":"address","name":"_initialOwner","type":"address"},{"internalType":"uint256[]","name":"_tierCeilings","type":"uint256[]"},{"internalType":"uint256[]","name":"_fees","type":"uint256[]"}],"name":"createBond","outputs":[{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_bond","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_payoutToken","type":"address"},{"internalType":"address","name":"_principleToken","type":"address"},{"internalType":"address","name":"_initialOwner","type":"address"},{"internalType":"uint256[]","name":"_tierCeilings","type":"uint256[]"},{"internalType":"uint256[]","name":"_fees","type":"uint256[]"}],"name":"createBondAndTreasury","outputs":[{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_bond","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"olumpusProSubsidyRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"olympusDAO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"olympusProFactoryStorage","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"olympusTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"policy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferManagment","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61010060405234801561001157600080fd5b506040516162c23803806162c28339818101604052608081101561003457600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156100dd57600080fd5b8373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561014e57600080fd5b8273ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156101bf57600080fd5b8173ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561023057600080fd5b8073ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1660601b815250505050505060805160601c60a05160601c60c05160601c60e05160601c615ff36102cf6000398061067052806107ed5280610cbc52508061069452806107cb5280610c9a5250806106dc52806109785280610e475250806106b85280610c795250615ff36000f3fe60806040523480156200001157600080fd5b5060043610620000945760003560e01c806371bcc39c116200006357806371bcc39c1462000182578063d47eb70214620001b8578063ed61e29314620001ee578063f185a889146200038c5762000094565b80630505c8c914620000995780633bfdd7de14620000cf5780634adf843214620001165780635a4222cc146200014c575b600080fd5b620000a36200050a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6200011460048036036020811015620000e757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506200052e565b005b620001206200066e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6200015662000692565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6200018c620006b6565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b620001c2620006da565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b62000343600480360360c08110156200020657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115620002a457600080fd5b820183602082011115620002b757600080fd5b80359060200191846020830284011164010000000083111715620002da57600080fd5b909192939192939080359060200190640100000000811115620002fc57600080fd5b8201836020820111156200030f57600080fd5b803590602001918460208302840111640100000000831117156200033257600080fd5b9091929391929390505050620006fe565b604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b620004c1600480360360a0811015620003a457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001906401000000008111156200042257600080fd5b8201836020820111156200043557600080fd5b803590602001918460208302840111640100000000831117156200045857600080fd5b9091929391929390803590602001906401000000008111156200047a57600080fd5b8201836020820111156200048d57600080fd5b80359060200191846020830284011164010000000083111715620004b057600080fd5b909192939192939050505062000b3e565b604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614620005f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200062b57600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000803373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614620007c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000888b8b8b7f00000000000000000000000000000000000000000000000000000000000000008c7f00000000000000000000000000000000000000000000000000000000000000008d8d8d8d6040516200081e906200100d565b808c73ffffffffffffffffffffffffffffffffffffffff1681526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509d5050505050505050505050505050604051809103906000f08015801562000973573d6000803e3d6000fd5b5090507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630e8dbe248c8c8c858d8d8d8d8d6040518a63ffffffff1660e01b8152600401808a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509b5050505050505050505050506040805180830381600087803b15801562000ae557600080fd5b505af115801562000afa573d6000803e3d6000fd5b505050506040513d604081101562000b1157600080fd5b81019080805190602001909291908051906020019092919050505092509250509850989650505050505050565b6000803373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161462000c03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000898860405162000c15906200101b565b808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050604051809103906000f08015801562000c6f573d6000803e3d6000fd5b5090506000818b8b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008d7f00000000000000000000000000000000000000000000000000000000000000008e8e8e8e60405162000ced906200100d565b808c73ffffffffffffffffffffffffffffffffffffffff1681526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509d5050505050505050505050505050604051809103906000f08015801562000e42573d6000803e3d6000fd5b5090507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630e8dbe248c8c85858e8e8e8e8e6040518a63ffffffff1660e01b8152600401808a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509b5050505050505050505050506040805180830381600087803b15801562000fb457600080fd5b505af115801562000fc9573d6000803e3d6000fd5b505050506040513d604081101562000fe057600080fd5b81019080805190602001909291908051906020019092919050505093509350505097509795505050505050565b613ca9806200102a83390190565b6112eb8062004cd38339019056fe6101206040523480156200001257600080fd5b5060405162003ca938038062003ca983398181016040526101208110156200003957600080fd5b810190808051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080516040519392919084640100000000821115620000a057600080fd5b83820191506020820185811115620000b757600080fd5b8251866020820283011164010000000082111715620000d557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156200010e578082015181840152602081019050620000f1565b50505050905001604052602001805160405193929190846401000000008211156200013857600080fd5b838201915060208201858111156200014f57600080fd5b82518660208202830111640100000000821117156200016d57600080fd5b8083526020830192505050908051906020019060200280838360005b83811015620001a657808201518184015260208101905062000189565b50505050905001604052505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156200022e57600080fd5b8873ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415620002a057600080fd5b8773ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614156200031257600080fd5b8673ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156200038457600080fd5b85600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156200040057600080fd5b8473ffffffffffffffffffffffffffffffffffffffff166101008173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156200047357600080fd5b836000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415620004ee57600080fd5b8273ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050805182511462000581576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018062003c826027913960400191505060405180910390fd5b60005b82518110156200061a57600e6040518060400160405280858481518110620005a857fe5b60200260200101518152602001848481518110620005c257fe5b6020026020010151815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000155602082015181600101555050808060010191505062000584565b5050505050505050505060805160601c60a05160601c60c05160601c60e05160601c6101005160601c6135ce620006b4600039806120a7525080610d8d52508061126552806115bd528061166e5250806112a1528061153a528061158152806116aa52508061136052806117475280611bb95280611e3752806121bf528061227c528061236852806124775280612b8f52506135ce6000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80637cbe044c116100de578063cea55f5711610097578063e0176de811610071578063e0176de8146106c1578063e392a262146106df578063f5c2ab5b146106fd578063fc7b9c181461071b5761018e565b8063cea55f571461064b578063d502562514610669578063d7ccfb0b146106a35761018e565b80637cbe044c1461047e5780638dbdbe6d1461049c57806395a2251f14610508578063a50603b214610560578063a9bc6b71146105c0578063cd1234b3146105de5761018e565b80633bfdd7de1161014b5780634799afda116101255780634799afda146103a8578063507930ec146103c6578063759076e51461041e5780637927ebf81461043c5761018e565b80633bfdd7de146102e45780633f0fb92f14610328578063451ee4a11461036c5761018e565b806301b88ee8146101935780630505c8c9146101eb5780630a7484891461021f5780631a3d00681461023d5780631e321a0f1461028b5780632bab6bde146102c6575b600080fd5b6101d5600480360360208110156101a957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610739565b6040518082815260200191505060405180910390f35b6101f36107d0565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102276107f4565b6040518082815260200191505060405180910390f35b6102896004803603608081101561025357600080fd5b8101908080351515906020019092919080359060200190929190803590602001909291908035906020019092919050505061084a565b005b6102c4600480360360408110156102a157600080fd5b81019080803560ff16906020019092919080359060200190929190505050610a29565b005b6102ce610c47565b6040518082815260200191505060405180910390f35b610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c4d565b005b61036a6004803603602081101561033e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d8b565b005b610374610e90565b6040518086151581526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b6103b0610ec1565b6040518082815260200191505060405180910390f35b610408600480360360208110156103dc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f47565b6040518082815260200191505060405180910390f35b61042661102d565b6040518082815260200191505060405180910390f35b6104686004803603602081101561045257600080fd5b8101908080359060200190929190505050611050565b6040518082815260200191505060405180910390f35b6104866110ce565b6040518082815260200191505060405180910390f35b6104f2600480360360608110156104b257600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110d4565b6040518082815260200191505060405180910390f35b61054a6004803603602081101561051e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611a5f565b6040518082815260200191505060405180910390f35b6105be600480360360c081101561057657600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050611f0e565b005b6105c86120a3565b6040518082815260200191505060405180910390f35b610620600480360360208110156105f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612176565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b6106536121a6565b6040518082815260200191505060405180910390f35b610671612338565b604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b6106ab61235c565b6040518082815260200191505060405180910390f35b6106c9612463565b6040518082815260200191505060405180910390f35b6106e7612537565b6040518082815260200191505060405180910390f35b610705612593565b6040518082815260200191505060405180910390f35b610723612599565b6040518082815260200191505060405180910390f35b60008061074583610f47565b90506000600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001549050612710821061079f578092506107c9565b6107c66127106107b8848461259f90919063ffffffff16565b61262590919063ffffffff16565b92505b5050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061084561082f620f424061082161080b610ec1565b61081361235c565b61259f90919063ffffffff16565b61262590919063ffffffff16565b61083761235c565b61266f90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461090b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6109386103e861092a601e60046000015461259f90919063ffffffff16565b61262590919063ffffffff16565b8311156109ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e6372656d656e7420746f6f206c617267650000000000000000000000000081525060200191505060405180910390fd5b6040518060a00160405280851515815260200184815260200183815260200182815260200143815250600960008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015590505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610aea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60006002811115610af757fe5b826002811115610b0357fe5b1415610b7357612710811015610b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061354b6024913960400191505060405180910390fd5b80600460010181905550610c43565b60016002811115610b8057fe5b826002811115610b8c57fe5b1415610c19576103e8811115610c0a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5061796f75742063616e6e6f742062652061626f766520312070657263656e7481525060200191505060405180910390fd5b80600460030181905550610c42565b600280811115610c2557fe5b826002811115610c3157fe5b1415610c41578060048001819055505b5b5b5050565b60035481565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d0e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610d4857600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e4c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f4f6e6c79204f6c796d7075732044414f0000000000000000000000000000000081525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60098060000160009054906101000a900460ff16908060010154908060020154908060030154908060040154905085565b600080600e80549050905060005b81811015610f4157600e8181548110610ee457fe5b9060005260206000209060020201600001546002541080610f0757506001820381145b15610f3457600e8181548110610f1957fe5b90600052602060002090600202016001015492505050610f44565b8080600101915050610ecf565b50505b90565b6000610f51613466565b600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505090506000610fde8260400151436126f790919063ffffffff16565b90506000826020015190506000811115611020576110198161100b6127108561259f90919063ffffffff16565b61262590919063ffffffff16565b9350611025565b600093505b505050919050565b600061104b61103a612537565b6010546126f790919063ffffffff16565b905090565b60008061108364174876e8006110756110708661106b61235c565b612741565b612a22565b61262590919063ffffffff16565b90506110c66110b7620f42406110a961109a610ec1565b8561259f90919063ffffffff16565b61262590919063ffffffff16565b826126f790919063ffffffff16565b915050919050565b60025481565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611178576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f496e76616c69642061646472657373000000000000000000000000000000000081525060200191505060405180910390fd5b611180612a5e565b600480015460105411156111fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4d6178206361706163697479207265616368656400000000000000000000000081525060200191505060405180910390fd5b60006112066107f4565b905080841015611261576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806135286023913960400191505060405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d1b317e57f0000000000000000000000000000000000000000000000000000000000000000886040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060206040518083038186803b15801561131257600080fd5b505afa158015611326573d6000803e3d6000fd5b505050506040513d602081101561133c57600080fd5b81019080805190602001909291905050509050600061135a82612a89565b905060647f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c457600080fd5b505afa1580156113d8573d6000803e3d6000fd5b505050506040513d60208110156113ee57600080fd5b810190808051906020019092919050505060ff16600a0a8161140c57fe5b04811015611482576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f20736d616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b61148a612463565b8111156114ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f206c6172676500000000000000000000000000000000000081525060200191505060405180910390fd5b6000611530620f4240611522611513610ec1565b8561259f90919063ffffffff16565b61262590919063ffffffff16565b905061157f33308a7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612ac2909392919063ffffffff16565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663095ea7b37f00000000000000000000000000000000000000000000000000000000000000008a6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561163057600080fd5b505af1158015611644573d6000803e3d6000fd5b505050506040513d602081101561165a57600080fd5b8101908080519060200190929190505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630efe6a8b7f00000000000000000000000000000000000000000000000000000000000000008a856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018281526020019350505050600060405180830381600087803b15801561172557600080fd5b505af1158015611739573d6000803e3d6000fd5b5050505060008114611835577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156117f857600080fd5b505af115801561180c573d6000803e3d6000fd5b505050506040513d602081101561182257600080fd5b8101908080519060200190929190505050505b61184a8360105461266f90919063ffffffff16565b60108190555060405180608001604052806118c261187184866126f790919063ffffffff16565b600f60008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015461266f90919063ffffffff16565b815260200160046001015481526020014381526020016118e06107f4565b815250600f60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050507fb7ce5a2d90f1705ca02547b0eb827724683e0df3b809477ae4326d0eefed0bc088836119886004600101544361266f90919063ffffffff16565b60405180848152602001838152602001828152602001935050505060405180910390a17f2cb17bd1fd2a1fecfefae2de1e6a59194abaa62179652924ccdca01617f0bf166119d4612b83565b6119dc6121a6565b604051808381526020018281526020019250505060405180910390a1611a0d8860025461266f90919063ffffffff16565b600281905550611a288260035461266f90919063ffffffff16565b600381905550611a438260125461266f90919063ffffffff16565b601281905550611a51612ca8565b819450505050509392505050565b6000611a69613466565b600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505090506000611ae884610f47565b90506127108110611c9657600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160009055600382016000905550507f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b18483600001516000604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a17f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8584600001516040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611c4c57600080fd5b505af1158015611c60573d6000803e3d6000fd5b505050506040513d6020811015611c7657600080fd5b810190808051906020019092919050505050816000015192505050611f09565b6000611cc3612710611cb584866000015161259f90919063ffffffff16565b61262590919063ffffffff16565b90506040518060800160405280611ce78386600001516126f790919063ffffffff16565b8152602001611d19611d068660400151436126f790919063ffffffff16565b86602001516126f790919063ffffffff16565b81526020014381526020018460600151815250600f60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050507f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b18582600f60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a17f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb86836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611ec657600080fd5b505af1158015611eda573d6000803e3d6000fd5b505050506040513d6020811015611ef057600080fd5b8101908080519060200190929190505050508093505050505b919050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611fcf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000611fd961102d565b1461202f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806134e66021913960400191505060405180910390fd5b6040518060a0016040528087815260200186815260200185815260200184815260200183815250600460008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050508060108190555043601181905550505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612166576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4f6e6c79207375627369647920636f6e74726f6c6c657200000000000000000081525060200191505060405180910390fd5b6012549050600060128190555090565b600f6020528060005260406000206000915090508060000154908060010154908060020154908060030154905084565b6000612333670de0b6b3a764000061232561232061227a7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561222357600080fd5b505afa158015612237573d6000803e3d6000fd5b505050506040513d602081101561224d57600080fd5b810190808051906020019092919050505060ff16600a0a61226c61102d565b61259f90919063ffffffff16565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156122e057600080fd5b505afa1580156122f4573d6000803e3d6000fd5b505050506040513d602081101561230a57600080fd5b8101908080519060200190929190505050612741565b612a22565b61262590919063ffffffff16565b905090565b60048060000154908060010154908060020154908060030154908060040154905085565b600061244861241860057f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156123cc57600080fd5b505afa1580156123e0573d6000803e3d6000fd5b505050506040513d60208110156123f657600080fd5b810190808051906020019092919050505060ff166126f790919063ffffffff16565b600a0a61243a6124266121a6565b60046000015461259f90919063ffffffff16565b61262590919063ffffffff16565b90506004600201548110156124605760046002015490505b90565b6000612532620186a06125246004600301547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124db57600080fd5b505afa1580156124ef573d6000803e3d6000fd5b505050506040513d602081101561250557600080fd5b810190808051906020019092919050505061259f90919063ffffffff16565b61262590919063ffffffff16565b905090565b60008061254f601154436126f790919063ffffffff16565b905061257d60046001015461256f8360105461259f90919063ffffffff16565b61262590919063ffffffff16565b915060105482111561258f5760105491505b5090565b60115481565b60105481565b6000808314156125b2576000905061261f565b60008284029050828482816125c357fe5b041461261a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806135076021913960400191505060405180910390fd5b809150505b92915050565b600061266783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612e0e565b905092915050565b6000808284019050838110156126ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600061273983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612ed4565b905092915050565b61274961348e565b600082116127a2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806134c06026913960400191505060405180910390fd5b60008314156127e057604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509050612a1c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff71ffffffffffffffffffffffffffffffffffff16831161291957600082607060ff1685901b8161282d57fe5b0490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168111156128e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815250915050612a1c565b6000612935846e01000000000000000000000000000085612f94565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168111156129eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509150505b92915050565b60006612725dd1d243ab82600001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681612a5657fe5b049050919050565b612a7a612a69612537565b6010546126f790919063ffffffff16565b60108190555043601181905550565b6000612abb64174876e800612aad612aa885612aa361235c565b612741565b612a22565b61262590919063ffffffff16565b9050919050565b612b7d846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613056565b50505050565b6000612c6f612c3f60057f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612bf357600080fd5b505afa158015612c07573d6000803e3d6000fd5b505050506040513d6020811015612c1d57600080fd5b810190808051906020019092919050505060ff166126f790919063ffffffff16565b600a0a612c61612c4d6121a6565b60046000015461259f90919063ffffffff16565b61262590919063ffffffff16565b9050600460020154811015612c8b576004600201549050612ca5565b600060046002015414612ca45760006004600201819055505b5b90565b6000612cc760096003015460096004015461266f90919063ffffffff16565b9050600060096001015414158015612cdf5750804310155b15612e0b5760006004600001549050600960000160009054906101000a900460ff1615612d4e57612d2360096001015460046000015461266f90919063ffffffff16565b60046000018190555060096002015460046000015410612d495760006009600101819055505b612d92565b612d6b6009600101546004600001546126f790919063ffffffff16565b60046000018190555060096002015460046000015411612d915760006009600101819055505b5b436009600401819055507fb923e581a0f83128e9e1d8297aa52b18d6744310476e0b54509c054cd7a93b2a81600460000154600960010154600960000160009054906101000a900460ff1660405180858152602001848152602001838152602001821515815260200194505050505060405180910390a1505b50565b60008083118290612eba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e7f578082015181840152602081019050612e64565b50505050905090810190601f168015612eac5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612ec657fe5b049050809150509392505050565b6000838311158290612f81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612f46578082015181840152602081019050612f2b565b50505050905090810190601f168015612f735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000806000612fa38686613145565b9150915060008480612fb157fe5b868809905082811115612fc5576001820391505b808303925084821061303f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f46756c6c4d6174683a3a6d756c4469763a206f766572666c6f7700000000000081525060200191505060405180910390fd5b61304a838387613198565b93505050509392505050565b60606130b8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132359092919063ffffffff16565b9050600081511115613140578080602001905160208110156130d957600080fd5b810190808051906020019092919050505061313f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061356f602a913960400191505060405180910390fd5b5b505050565b60008060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061317257fe5b84860990508385029250828103915082811015613190576001820391505b509250929050565b60008082600003831690508083816131ac57fe5b0492508085816131b857fe5b04945060018182600003816131c957fe5b04018402850194506000600190508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808602925050509392505050565b6060613244848460008561324d565b90509392505050565b606061325885613453565b6132ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061331a57805182526020820191506020810190506020830392506132f7565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461337c576040519150601f19603f3d011682016040523d82523d6000602084013e613381565b606091505b5091509150811561339657809250505061344b565b6000815111156133a95780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156134105780820151818401526020810190506133f5565b50505050905090810190601f16801561343d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b949350505050565b600080823b905060008111915050919050565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509056fe4669786564506f696e743a3a6672616374696f6e3a206469766973696f6e206279207a65726f44656274206d757374206265203020666f7220696e697469616c697a6174696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77536c697070616765206c696d69743a206d6f7265207468616e206d617820707269636556657374696e67206d757374206265206c6f6e676572207468616e20333620686f7572735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220534e04728123362f376f70180716c54d4c6a44d2c6775c6f7aee44a2c8273bae64736f6c6343000705003374696572206c656e67746820616e6420666565206c656e677468206e6f74207468652073616d6560a060405234801561001057600080fd5b506040516112eb3803806112eb8339818101604052604081101561003357600080fd5b810190808051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156100c857600080fd5b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561013957600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505060805160601c6111496101a2600039806103f952806105a2528061065552506111496000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80634efa82b61161005b5780634efa82b6146101b7578063d1b317e5146101eb578063d9caed121461024d578063f95c2306146102bb57610088565b80630505c8c91461008d5780630efe6a8b146100c157806324705db3146101195780633bfdd7de14610173575b600080fd5b6100956102ff565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610117600480360360608110156100d757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190505050610323565b005b61015b6004803603602081101561012f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610442565b60405180821515815260200191505060405180910390f35b6101b56004803603602081101561018957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610462565b005b6101bf6105a0565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102376004803603604081101561020157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105c4565b6040518082815260200191505060405180910390f35b6102b96004803603606081101561026357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061071f565b005b6102fd600480360360208110156102d157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610883565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166103c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806110c96021913960400191505060405180910390fd5b6103f23330848673ffffffffffffffffffffffffffffffffffffffff16610a8e909392919063ffffffff16565b61043d33827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610b4f9092919063ffffffff16565b505050565b60016020528060005260406000206000915054906101000a900460ff1681565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610523576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561055d57600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006107178373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561060f57600080fd5b505afa158015610623573d6000803e3d6000fd5b505050506040513d602081101561063957600080fd5b810190808051906020019092919050505060ff16600a0a6107097f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156106b957600080fd5b505afa1580156106cd573d6000803e3d6000fd5b505050506040513d60208110156106e357600080fd5b810190808051906020019092919050505060ff16600a0a85610bf190919063ffffffff16565b610c7790919063ffffffff16565b905092915050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61080b82828573ffffffffffffffffffffffffffffffffffffffff16610b4f9092919063ffffffff16565b7f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb838383604051808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610944576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f661abc66f13f27ca765c6a753171d10aa4861f03f1b506c5b1297a2dc80cf8ee81600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16604051808373ffffffffffffffffffffffffffffffffffffffff16815260200182151581526020019250505060405180910390a150565b610b49846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610cc1565b50505050565b610bec8363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610cc1565b505050565b600080831415610c045760009050610c71565b6000828402905082848281610c1557fe5b0414610c6c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806110a86021913960400191505060405180910390fd5b809150505b92915050565b6000610cb983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250610db0565b905092915050565b6060610d23826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16610e769092919063ffffffff16565b9050600081511115610dab57808060200190516020811015610d4457600080fd5b8101908080519060200190929190505050610daa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806110ea602a913960400191505060405180910390fd5b5b505050565b60008083118290610e5c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610e21578082015181840152602081019050610e06565b50505050905090810190601f168015610e4e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581610e6857fe5b049050809150509392505050565b6060610e858484600085610e8e565b90509392505050565b6060610e9985611094565b610f0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310610f5b5780518252602082019150602081019050602083039250610f38565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610fbd576040519150601f19603f3d011682016040523d82523d6000602084013e610fc2565b606091505b50915091508115610fd757809250505061108c565b600081511115610fea5780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611051578082015181840152602081019050611036565b50505050905090810190601f16801561107e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b949350505050565b600080823b90506000811191505091905056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f776d73672e73656e646572206973206e6f74206120626f6e6420636f6e74726163745361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220ae943e3dd47c06e2371fc79b5bf2a7cc118aad99a891a88554da78b9b536456a64736f6c63430007050033a2646970667358221220bb016eec3b27d8efb60408b613895988bcb7d6fc22b8ae9c666099d24574264d64736f6c6343000705003300000000000000000000000031f8cc382c9898b273eff4e0b7626a6987c846e80000000000000000000000006828d71014d797533c3b49b6990ca1781656b71f00000000000000000000000097fac4ea361338eab5c89792ee196da8712c9a4a000000000000000000000000245cc372c84b3645bf0ffe6538620b04a217988b
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620000945760003560e01c806371bcc39c116200006357806371bcc39c1462000182578063d47eb70214620001b8578063ed61e29314620001ee578063f185a889146200038c5762000094565b80630505c8c914620000995780633bfdd7de14620000cf5780634adf843214620001165780635a4222cc146200014c575b600080fd5b620000a36200050a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6200011460048036036020811015620000e757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506200052e565b005b620001206200066e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6200015662000692565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6200018c620006b6565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b620001c2620006da565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b62000343600480360360c08110156200020657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115620002a457600080fd5b820183602082011115620002b757600080fd5b80359060200191846020830284011164010000000083111715620002da57600080fd5b909192939192939080359060200190640100000000811115620002fc57600080fd5b8201836020820111156200030f57600080fd5b803590602001918460208302840111640100000000831117156200033257600080fd5b9091929391929390505050620006fe565b604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b620004c1600480360360a0811015620003a457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001906401000000008111156200042257600080fd5b8201836020820111156200043557600080fd5b803590602001918460208302840111640100000000831117156200045857600080fd5b9091929391929390803590602001906401000000008111156200047a57600080fd5b8201836020820111156200048d57600080fd5b80359060200191846020830284011164010000000083111715620004b057600080fd5b909192939192939050505062000b3e565b604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614620005f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200062b57600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b7f000000000000000000000000245cc372c84b3645bf0ffe6538620b04a217988b81565b7f00000000000000000000000097fac4ea361338eab5c89792ee196da8712c9a4a81565b7f00000000000000000000000031f8cc382c9898b273eff4e0b7626a6987c846e881565b7f0000000000000000000000006828d71014d797533c3b49b6990ca1781656b71f81565b6000803373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614620007c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000888b8b8b7f00000000000000000000000097fac4ea361338eab5c89792ee196da8712c9a4a8c7f000000000000000000000000245cc372c84b3645bf0ffe6538620b04a217988b8d8d8d8d6040516200081e906200100d565b808c73ffffffffffffffffffffffffffffffffffffffff1681526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509d5050505050505050505050505050604051809103906000f08015801562000973573d6000803e3d6000fd5b5090507f0000000000000000000000006828d71014d797533c3b49b6990ca1781656b71f73ffffffffffffffffffffffffffffffffffffffff16630e8dbe248c8c8c858d8d8d8d8d6040518a63ffffffff1660e01b8152600401808a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509b5050505050505050505050506040805180830381600087803b15801562000ae557600080fd5b505af115801562000afa573d6000803e3d6000fd5b505050506040513d604081101562000b1157600080fd5b81019080805190602001909291908051906020019092919050505092509250509850989650505050505050565b6000803373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161462000c03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000898860405162000c15906200101b565b808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200192505050604051809103906000f08015801562000c6f573d6000803e3d6000fd5b5090506000818b8b7f00000000000000000000000031f8cc382c9898b273eff4e0b7626a6987c846e87f00000000000000000000000097fac4ea361338eab5c89792ee196da8712c9a4a8d7f000000000000000000000000245cc372c84b3645bf0ffe6538620b04a217988b8e8e8e8e60405162000ced906200100d565b808c73ffffffffffffffffffffffffffffffffffffffff1681526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509d5050505050505050505050505050604051809103906000f08015801562000e42573d6000803e3d6000fd5b5090507f0000000000000000000000006828d71014d797533c3b49b6990ca1781656b71f73ffffffffffffffffffffffffffffffffffffffff16630e8dbe248c8c85858e8e8e8e8e6040518a63ffffffff1660e01b8152600401808a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018381038352878782818152602001925060200280828437600081840152601f19601f8201169050808301925050508381038252858582818152602001925060200280828437600081840152601f19601f8201169050808301925050509b5050505050505050505050506040805180830381600087803b15801562000fb457600080fd5b505af115801562000fc9573d6000803e3d6000fd5b505050506040513d604081101562000fe057600080fd5b81019080805190602001909291908051906020019092919050505093509350505097509795505050505050565b613ca9806200102a83390190565b6112eb8062004cd38339019056fe6101206040523480156200001257600080fd5b5060405162003ca938038062003ca983398181016040526101208110156200003957600080fd5b810190808051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080516040519392919084640100000000821115620000a057600080fd5b83820191506020820185811115620000b757600080fd5b8251866020820283011164010000000082111715620000d557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156200010e578082015181840152602081019050620000f1565b50505050905001604052602001805160405193929190846401000000008211156200013857600080fd5b838201915060208201858111156200014f57600080fd5b82518660208202830111640100000000821117156200016d57600080fd5b8083526020830192505050908051906020019060200280838360005b83811015620001a657808201518184015260208101905062000189565b50505050905001604052505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156200022e57600080fd5b8873ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415620002a057600080fd5b8773ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614156200031257600080fd5b8673ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156200038457600080fd5b85600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156200040057600080fd5b8473ffffffffffffffffffffffffffffffffffffffff166101008173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156200047357600080fd5b836000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415620004ee57600080fd5b8273ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1660601b81525050805182511462000581576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018062003c826027913960400191505060405180910390fd5b60005b82518110156200061a57600e6040518060400160405280858481518110620005a857fe5b60200260200101518152602001848481518110620005c257fe5b6020026020010151815250908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000155602082015181600101555050808060010191505062000584565b5050505050505050505060805160601c60a05160601c60c05160601c60e05160601c6101005160601c6135ce620006b4600039806120a7525080610d8d52508061126552806115bd528061166e5250806112a1528061153a528061158152806116aa52508061136052806117475280611bb95280611e3752806121bf528061227c528061236852806124775280612b8f52506135ce6000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80637cbe044c116100de578063cea55f5711610097578063e0176de811610071578063e0176de8146106c1578063e392a262146106df578063f5c2ab5b146106fd578063fc7b9c181461071b5761018e565b8063cea55f571461064b578063d502562514610669578063d7ccfb0b146106a35761018e565b80637cbe044c1461047e5780638dbdbe6d1461049c57806395a2251f14610508578063a50603b214610560578063a9bc6b71146105c0578063cd1234b3146105de5761018e565b80633bfdd7de1161014b5780634799afda116101255780634799afda146103a8578063507930ec146103c6578063759076e51461041e5780637927ebf81461043c5761018e565b80633bfdd7de146102e45780633f0fb92f14610328578063451ee4a11461036c5761018e565b806301b88ee8146101935780630505c8c9146101eb5780630a7484891461021f5780631a3d00681461023d5780631e321a0f1461028b5780632bab6bde146102c6575b600080fd5b6101d5600480360360208110156101a957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610739565b6040518082815260200191505060405180910390f35b6101f36107d0565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102276107f4565b6040518082815260200191505060405180910390f35b6102896004803603608081101561025357600080fd5b8101908080351515906020019092919080359060200190929190803590602001909291908035906020019092919050505061084a565b005b6102c4600480360360408110156102a157600080fd5b81019080803560ff16906020019092919080359060200190929190505050610a29565b005b6102ce610c47565b6040518082815260200191505060405180910390f35b610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c4d565b005b61036a6004803603602081101561033e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d8b565b005b610374610e90565b6040518086151581526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b6103b0610ec1565b6040518082815260200191505060405180910390f35b610408600480360360208110156103dc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f47565b6040518082815260200191505060405180910390f35b61042661102d565b6040518082815260200191505060405180910390f35b6104686004803603602081101561045257600080fd5b8101908080359060200190929190505050611050565b6040518082815260200191505060405180910390f35b6104866110ce565b6040518082815260200191505060405180910390f35b6104f2600480360360608110156104b257600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110d4565b6040518082815260200191505060405180910390f35b61054a6004803603602081101561051e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611a5f565b6040518082815260200191505060405180910390f35b6105be600480360360c081101561057657600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050611f0e565b005b6105c86120a3565b6040518082815260200191505060405180910390f35b610620600480360360208110156105f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612176565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b6106536121a6565b6040518082815260200191505060405180910390f35b610671612338565b604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b6106ab61235c565b6040518082815260200191505060405180910390f35b6106c9612463565b6040518082815260200191505060405180910390f35b6106e7612537565b6040518082815260200191505060405180910390f35b610705612593565b6040518082815260200191505060405180910390f35b610723612599565b6040518082815260200191505060405180910390f35b60008061074583610f47565b90506000600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001549050612710821061079f578092506107c9565b6107c66127106107b8848461259f90919063ffffffff16565b61262590919063ffffffff16565b92505b5050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061084561082f620f424061082161080b610ec1565b61081361235c565b61259f90919063ffffffff16565b61262590919063ffffffff16565b61083761235c565b61266f90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461090b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6109386103e861092a601e60046000015461259f90919063ffffffff16565b61262590919063ffffffff16565b8311156109ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e6372656d656e7420746f6f206c617267650000000000000000000000000081525060200191505060405180910390fd5b6040518060a00160405280851515815260200184815260200183815260200182815260200143815250600960008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015590505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610aea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60006002811115610af757fe5b826002811115610b0357fe5b1415610b7357612710811015610b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061354b6024913960400191505060405180910390fd5b80600460010181905550610c43565b60016002811115610b8057fe5b826002811115610b8c57fe5b1415610c19576103e8811115610c0a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5061796f75742063616e6e6f742062652061626f766520312070657263656e7481525060200191505060405180910390fd5b80600460030181905550610c42565b600280811115610c2557fe5b826002811115610c3157fe5b1415610c41578060048001819055505b5b5b5050565b60035481565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d0e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610d4857600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e4c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f4f6e6c79204f6c796d7075732044414f0000000000000000000000000000000081525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60098060000160009054906101000a900460ff16908060010154908060020154908060030154908060040154905085565b600080600e80549050905060005b81811015610f4157600e8181548110610ee457fe5b9060005260206000209060020201600001546002541080610f0757506001820381145b15610f3457600e8181548110610f1957fe5b90600052602060002090600202016001015492505050610f44565b8080600101915050610ecf565b50505b90565b6000610f51613466565b600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505090506000610fde8260400151436126f790919063ffffffff16565b90506000826020015190506000811115611020576110198161100b6127108561259f90919063ffffffff16565b61262590919063ffffffff16565b9350611025565b600093505b505050919050565b600061104b61103a612537565b6010546126f790919063ffffffff16565b905090565b60008061108364174876e8006110756110708661106b61235c565b612741565b612a22565b61262590919063ffffffff16565b90506110c66110b7620f42406110a961109a610ec1565b8561259f90919063ffffffff16565b61262590919063ffffffff16565b826126f790919063ffffffff16565b915050919050565b60025481565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611178576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f496e76616c69642061646472657373000000000000000000000000000000000081525060200191505060405180910390fd5b611180612a5e565b600480015460105411156111fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4d6178206361706163697479207265616368656400000000000000000000000081525060200191505060405180910390fd5b60006112066107f4565b905080841015611261576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806135286023913960400191505060405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d1b317e57f0000000000000000000000000000000000000000000000000000000000000000886040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060206040518083038186803b15801561131257600080fd5b505afa158015611326573d6000803e3d6000fd5b505050506040513d602081101561133c57600080fd5b81019080805190602001909291905050509050600061135a82612a89565b905060647f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c457600080fd5b505afa1580156113d8573d6000803e3d6000fd5b505050506040513d60208110156113ee57600080fd5b810190808051906020019092919050505060ff16600a0a8161140c57fe5b04811015611482576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f20736d616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b61148a612463565b8111156114ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f426f6e6420746f6f206c6172676500000000000000000000000000000000000081525060200191505060405180910390fd5b6000611530620f4240611522611513610ec1565b8561259f90919063ffffffff16565b61262590919063ffffffff16565b905061157f33308a7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612ac2909392919063ffffffff16565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663095ea7b37f00000000000000000000000000000000000000000000000000000000000000008a6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561163057600080fd5b505af1158015611644573d6000803e3d6000fd5b505050506040513d602081101561165a57600080fd5b8101908080519060200190929190505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630efe6a8b7f00000000000000000000000000000000000000000000000000000000000000008a856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018381526020018281526020019350505050600060405180830381600087803b15801561172557600080fd5b505af1158015611739573d6000803e3d6000fd5b5050505060008114611835577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156117f857600080fd5b505af115801561180c573d6000803e3d6000fd5b505050506040513d602081101561182257600080fd5b8101908080519060200190929190505050505b61184a8360105461266f90919063ffffffff16565b60108190555060405180608001604052806118c261187184866126f790919063ffffffff16565b600f60008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015461266f90919063ffffffff16565b815260200160046001015481526020014381526020016118e06107f4565b815250600f60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050507fb7ce5a2d90f1705ca02547b0eb827724683e0df3b809477ae4326d0eefed0bc088836119886004600101544361266f90919063ffffffff16565b60405180848152602001838152602001828152602001935050505060405180910390a17f2cb17bd1fd2a1fecfefae2de1e6a59194abaa62179652924ccdca01617f0bf166119d4612b83565b6119dc6121a6565b604051808381526020018281526020019250505060405180910390a1611a0d8860025461266f90919063ffffffff16565b600281905550611a288260035461266f90919063ffffffff16565b600381905550611a438260125461266f90919063ffffffff16565b601281905550611a51612ca8565b819450505050509392505050565b6000611a69613466565b600f60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505090506000611ae884610f47565b90506127108110611c9657600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008082016000905560018201600090556002820160009055600382016000905550507f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b18483600001516000604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a17f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8584600001516040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611c4c57600080fd5b505af1158015611c60573d6000803e3d6000fd5b505050506040513d6020811015611c7657600080fd5b810190808051906020019092919050505050816000015192505050611f09565b6000611cc3612710611cb584866000015161259f90919063ffffffff16565b61262590919063ffffffff16565b90506040518060800160405280611ce78386600001516126f790919063ffffffff16565b8152602001611d19611d068660400151436126f790919063ffffffff16565b86602001516126f790919063ffffffff16565b81526020014381526020018460600151815250600f60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301559050507f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b18582600f60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a17f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb86836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611ec657600080fd5b505af1158015611eda573d6000803e3d6000fd5b505050506040513d6020811015611ef057600080fd5b8101908080519060200190929190505050508093505050505b919050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611fcf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000611fd961102d565b1461202f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806134e66021913960400191505060405180910390fd5b6040518060a0016040528087815260200186815260200185815260200184815260200183815250600460008201518160000155602082015181600101556040820151816002015560608201518160030155608082015181600401559050508060108190555043601181905550505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612166576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4f6e6c79207375627369647920636f6e74726f6c6c657200000000000000000081525060200191505060405180910390fd5b6012549050600060128190555090565b600f6020528060005260406000206000915090508060000154908060010154908060020154908060030154905084565b6000612333670de0b6b3a764000061232561232061227a7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561222357600080fd5b505afa158015612237573d6000803e3d6000fd5b505050506040513d602081101561224d57600080fd5b810190808051906020019092919050505060ff16600a0a61226c61102d565b61259f90919063ffffffff16565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156122e057600080fd5b505afa1580156122f4573d6000803e3d6000fd5b505050506040513d602081101561230a57600080fd5b8101908080519060200190929190505050612741565b612a22565b61262590919063ffffffff16565b905090565b60048060000154908060010154908060020154908060030154908060040154905085565b600061244861241860057f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156123cc57600080fd5b505afa1580156123e0573d6000803e3d6000fd5b505050506040513d60208110156123f657600080fd5b810190808051906020019092919050505060ff166126f790919063ffffffff16565b600a0a61243a6124266121a6565b60046000015461259f90919063ffffffff16565b61262590919063ffffffff16565b90506004600201548110156124605760046002015490505b90565b6000612532620186a06125246004600301547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156124db57600080fd5b505afa1580156124ef573d6000803e3d6000fd5b505050506040513d602081101561250557600080fd5b810190808051906020019092919050505061259f90919063ffffffff16565b61262590919063ffffffff16565b905090565b60008061254f601154436126f790919063ffffffff16565b905061257d60046001015461256f8360105461259f90919063ffffffff16565b61262590919063ffffffff16565b915060105482111561258f5760105491505b5090565b60115481565b60105481565b6000808314156125b2576000905061261f565b60008284029050828482816125c357fe5b041461261a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806135076021913960400191505060405180910390fd5b809150505b92915050565b600061266783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612e0e565b905092915050565b6000808284019050838110156126ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600061273983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612ed4565b905092915050565b61274961348e565b600082116127a2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806134c06026913960400191505060405180910390fd5b60008314156127e057604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509050612a1c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff71ffffffffffffffffffffffffffffffffffff16831161291957600082607060ff1685901b8161282d57fe5b0490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168111156128e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815250915050612a1c565b6000612935846e01000000000000000000000000000085612f94565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168111156129eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f77000081525060200191505060405180910390fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509150505b92915050565b60006612725dd1d243ab82600001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681612a5657fe5b049050919050565b612a7a612a69612537565b6010546126f790919063ffffffff16565b60108190555043601181905550565b6000612abb64174876e800612aad612aa885612aa361235c565b612741565b612a22565b61262590919063ffffffff16565b9050919050565b612b7d846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613056565b50505050565b6000612c6f612c3f60057f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612bf357600080fd5b505afa158015612c07573d6000803e3d6000fd5b505050506040513d6020811015612c1d57600080fd5b810190808051906020019092919050505060ff166126f790919063ffffffff16565b600a0a612c61612c4d6121a6565b60046000015461259f90919063ffffffff16565b61262590919063ffffffff16565b9050600460020154811015612c8b576004600201549050612ca5565b600060046002015414612ca45760006004600201819055505b5b90565b6000612cc760096003015460096004015461266f90919063ffffffff16565b9050600060096001015414158015612cdf5750804310155b15612e0b5760006004600001549050600960000160009054906101000a900460ff1615612d4e57612d2360096001015460046000015461266f90919063ffffffff16565b60046000018190555060096002015460046000015410612d495760006009600101819055505b612d92565b612d6b6009600101546004600001546126f790919063ffffffff16565b60046000018190555060096002015460046000015411612d915760006009600101819055505b5b436009600401819055507fb923e581a0f83128e9e1d8297aa52b18d6744310476e0b54509c054cd7a93b2a81600460000154600960010154600960000160009054906101000a900460ff1660405180858152602001848152602001838152602001821515815260200194505050505060405180910390a1505b50565b60008083118290612eba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e7f578082015181840152602081019050612e64565b50505050905090810190601f168015612eac5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612ec657fe5b049050809150509392505050565b6000838311158290612f81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612f46578082015181840152602081019050612f2b565b50505050905090810190601f168015612f735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000806000612fa38686613145565b9150915060008480612fb157fe5b868809905082811115612fc5576001820391505b808303925084821061303f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f46756c6c4d6174683a3a6d756c4469763a206f766572666c6f7700000000000081525060200191505060405180910390fd5b61304a838387613198565b93505050509392505050565b60606130b8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132359092919063ffffffff16565b9050600081511115613140578080602001905160208110156130d957600080fd5b810190808051906020019092919050505061313f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061356f602a913960400191505060405180910390fd5b5b505050565b60008060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8061317257fe5b84860990508385029250828103915082811015613190576001820391505b509250929050565b60008082600003831690508083816131ac57fe5b0492508085816131b857fe5b04945060018182600003816131c957fe5b04018402850194506000600190508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808402600203810290508084026002038102905080840260020381029050808602925050509392505050565b6060613244848460008561324d565b90509392505050565b606061325885613453565b6132ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061331a57805182526020820191506020810190506020830392506132f7565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461337c576040519150601f19603f3d011682016040523d82523d6000602084013e613381565b606091505b5091509150811561339657809250505061344b565b6000815111156133a95780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156134105780820151818401526020810190506133f5565b50505050905090810190601f16801561343d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b949350505050565b600080823b905060008111915050919050565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b604051806020016040528060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152509056fe4669786564506f696e743a3a6672616374696f6e3a206469766973696f6e206279207a65726f44656274206d757374206265203020666f7220696e697469616c697a6174696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77536c697070616765206c696d69743a206d6f7265207468616e206d617820707269636556657374696e67206d757374206265206c6f6e676572207468616e20333620686f7572735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220534e04728123362f376f70180716c54d4c6a44d2c6775c6f7aee44a2c8273bae64736f6c6343000705003374696572206c656e67746820616e6420666565206c656e677468206e6f74207468652073616d6560a060405234801561001057600080fd5b506040516112eb3803806112eb8339818101604052604081101561003357600080fd5b810190808051906020019092919080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156100c857600080fd5b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561013957600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505060805160601c6111496101a2600039806103f952806105a2528061065552506111496000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80634efa82b61161005b5780634efa82b6146101b7578063d1b317e5146101eb578063d9caed121461024d578063f95c2306146102bb57610088565b80630505c8c91461008d5780630efe6a8b146100c157806324705db3146101195780633bfdd7de14610173575b600080fd5b6100956102ff565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610117600480360360608110156100d757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190505050610323565b005b61015b6004803603602081101561012f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610442565b60405180821515815260200191505060405180910390f35b6101b56004803603602081101561018957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610462565b005b6101bf6105a0565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102376004803603604081101561020157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105c4565b6040518082815260200191505060405180910390f35b6102b96004803603606081101561026357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061071f565b005b6102fd600480360360208110156102d157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610883565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166103c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806110c96021913960400191505060405180910390fd5b6103f23330848673ffffffffffffffffffffffffffffffffffffffff16610a8e909392919063ffffffff16565b61043d33827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610b4f9092919063ffffffff16565b505050565b60016020528060005260406000206000915054906101000a900460ff1681565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610523576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561055d57600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006107178373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561060f57600080fd5b505afa158015610623573d6000803e3d6000fd5b505050506040513d602081101561063957600080fd5b810190808051906020019092919050505060ff16600a0a6107097f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156106b957600080fd5b505afa1580156106cd573d6000803e3d6000fd5b505050506040513d60208110156106e357600080fd5b810190808051906020019092919050505060ff16600a0a85610bf190919063ffffffff16565b610c7790919063ffffffff16565b905092915050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61080b82828573ffffffffffffffffffffffffffffffffffffffff16610b4f9092919063ffffffff16565b7f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb838383604051808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610944576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f661abc66f13f27ca765c6a753171d10aa4861f03f1b506c5b1297a2dc80cf8ee81600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16604051808373ffffffffffffffffffffffffffffffffffffffff16815260200182151581526020019250505060405180910390a150565b610b49846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610cc1565b50505050565b610bec8363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610cc1565b505050565b600080831415610c045760009050610c71565b6000828402905082848281610c1557fe5b0414610c6c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806110a86021913960400191505060405180910390fd5b809150505b92915050565b6000610cb983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250610db0565b905092915050565b6060610d23826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16610e769092919063ffffffff16565b9050600081511115610dab57808060200190516020811015610d4457600080fd5b8101908080519060200190929190505050610daa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806110ea602a913960400191505060405180910390fd5b5b505050565b60008083118290610e5c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610e21578082015181840152602081019050610e06565b50505050905090810190601f168015610e4e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581610e6857fe5b049050809150509392505050565b6060610e858484600085610e8e565b90509392505050565b6060610e9985611094565b610f0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310610f5b5780518252602082019150602081019050602083039250610f38565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610fbd576040519150601f19603f3d011682016040523d82523d6000602084013e610fc2565b606091505b50915091508115610fd757809250505061108c565b600081511115610fea5780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611051578082015181840152602081019050611036565b50505050905090810190601f16801561107e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b949350505050565b600080823b90506000811191505091905056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f776d73672e73656e646572206973206e6f74206120626f6e6420636f6e74726163745361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220ae943e3dd47c06e2371fc79b5bf2a7cc118aad99a891a88554da78b9b536456a64736f6c63430007050033a2646970667358221220bb016eec3b27d8efb60408b613895988bcb7d6fc22b8ae9c666099d24574264d64736f6c63430007050033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000031f8cc382c9898b273eff4e0b7626a6987c846e80000000000000000000000006828d71014d797533c3b49b6990ca1781656b71f00000000000000000000000097fac4ea361338eab5c89792ee196da8712c9a4a000000000000000000000000245cc372c84b3645bf0ffe6538620b04a217988b
-----Decoded View---------------
Arg [0] : _olympusTreasury (address): 0x31F8Cc382c9898b273eff4e0b7626a6987C846E8
Arg [1] : _olympusProFactoryStorage (address): 0x6828D71014D797533C3b49B6990Ca1781656B71f
Arg [2] : _olumpusProSubsidyRouter (address): 0x97Fac4EA361338EaB5c89792eE196DA8712C9a4a
Arg [3] : _olympusDAO (address): 0x245cc372C84B3645Bf0Ffe6538620B04a217988B
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000031f8cc382c9898b273eff4e0b7626a6987c846e8
Arg [1] : 0000000000000000000000006828d71014d797533c3b49b6990ca1781656b71f
Arg [2] : 00000000000000000000000097fac4ea361338eab5c89792ee196da8712c9a4a
Arg [3] : 000000000000000000000000245cc372c84b3645bf0ffe6538620b04a217988b
Deployed Bytecode Sourcemap
36593:2969:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;470:21;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;693:150;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;36852:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;36797:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;36694:40;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;36741:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;38923:630;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37866:715;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;470:21;;;;;;;;;;;;:::o;693:150::-;613:10;603:20;;:6;;;;;;;;;;:20;;;594:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;802:1:::1;781:23;;:9;:23;;;;772:34;;;::::0;::::1;;826:9;817:6;::::0;:18:::1;;;;;;;;;;;;;;;;;;693:150:::0;:::o;36852:35::-;;;:::o;36797:48::-;;;:::o;36694:40::-;;;:::o;36741:49::-;;;:::o;38923:630::-;39123:17;39142:13;613:10;603:20;;:6;;;;;;;;;;:20;;;594:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39170:15:::1;39203;39220:12;39234:15;39251;39268:23;39293:13;39308:10;39320:13;;39335:5;;39188:153;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;39170:171;;39387:24;39361:60;;;39436:12;39450:15;39467;39492:4;39499:13;39514;;39529:5;;39361:184;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;39354:191;;;;;38923:630:::0;;;;;;;;;;;:::o;37866:715::-;38051:17;38070:13;613:10;603:20;;:6;;;;;;;;;;:20;;;594:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38102:23:::1;38147:12;38161:13;38128:47;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;38102:73;;38186:15;38227:8;38238:12;38252:15;38269;38286:23;38311:13;38326:10;38338:13;;38353:5;;38204:155;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;38186:173;;38413:24;38387:60;;;38462:12;38476:15;38501:8;38520:4;38527:13;38542;;38557:5;;38387:186;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;38380:193;;;;;;37866:715:::0;;;;;;;;;;:::o;-1:-1:-1:-;;;;;;;;:::o;:::-;;;;;;;;:::o
Swarm Source
ipfs://bb016eec3b27d8efb60408b613895988bcb7d6fc22b8ae9c666099d24574264d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.