Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
DVM
Compiler Version
v0.6.9+commit.3e3065ac
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// File: contracts/intf/IDODOCallee.sol /* Copyright 2020 DODO ZOO. SPDX-License-Identifier: Apache-2.0 */ pragma solidity 0.6.9; pragma experimental ABIEncoderV2; interface IDODOCallee { function DVMSellShareCall( address sender, uint256 burnShareAmount, uint256 baseAmount, uint256 quoteAmount, bytes calldata data ) external; function DVMFlashLoanCall( address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data ) external; function DPPFlashLoanCall( address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data ) external; function DSPFlashLoanCall( address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data ) external; function CPCancelCall( address sender, uint256 amount, bytes calldata data ) external; function CPClaimBidCall( address sender, uint256 baseAmount, uint256 quoteAmount, bytes calldata data ) external; function NFTRedeemCall( address payable assetTo, uint256 quoteAmount, bytes calldata ) external; } // File: contracts/lib/ReentrancyGuard.sol /** * @title ReentrancyGuard * @author DODO Breeder * * @notice Protect functions from Reentrancy Attack */ contract ReentrancyGuard { // https://solidity.readthedocs.io/en/latest/control-structures.html?highlight=zero-state#scoping-and-declarations // zero-state of _ENTERED_ is false bool private _ENTERED_; modifier preventReentrant() { require(!_ENTERED_, "REENTRANT"); _ENTERED_ = true; _; _ENTERED_ = false; } } // File: contracts/lib/SafeMath.sol /** * @title SafeMath * @author DODO Breeder * * @notice Math operations with safety checks that revert on error */ library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "MUL_ERROR"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "DIVIDING_ERROR"); return a / b; } function divCeil(uint256 a, uint256 b) internal pure returns (uint256) { uint256 quotient = div(a, b); uint256 remainder = a - quotient * b; if (remainder > 0) { return quotient + 1; } else { return quotient; } } function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SUB_ERROR"); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "ADD_ERROR"); return c; } function sqrt(uint256 x) internal pure returns (uint256 y) { uint256 z = x / 2 + 1; y = x; while (z < y) { y = z; z = (x / z + z) / 2; } } } // File: contracts/lib/DecimalMath.sol /** * @title DecimalMath * @author DODO Breeder * * @notice Functions for fixed point number with 18 decimals */ library DecimalMath { using SafeMath for uint256; uint256 internal constant ONE = 10**18; uint256 internal constant ONE2 = 10**36; function mulFloor(uint256 target, uint256 d) internal pure returns (uint256) { return target.mul(d) / (10**18); } function mulCeil(uint256 target, uint256 d) internal pure returns (uint256) { return target.mul(d).divCeil(10**18); } function divFloor(uint256 target, uint256 d) internal pure returns (uint256) { return target.mul(10**18).div(d); } function divCeil(uint256 target, uint256 d) internal pure returns (uint256) { return target.mul(10**18).divCeil(d); } function reciprocalFloor(uint256 target) internal pure returns (uint256) { return uint256(10**36).div(target); } function reciprocalCeil(uint256 target) internal pure returns (uint256) { return uint256(10**36).divCeil(target); } function powFloor(uint256 target, uint256 e) internal pure returns (uint256) { if (e == 0) { return 10 ** 18; } else if (e == 1) { return target; } else { uint p = powFloor(target, e.div(2)); p = p.mul(p) / (10**18); if (e % 2 == 1) { p = p.mul(target) / (10**18); } return p; } } } // File: contracts/lib/DODOMath.sol /** * @title DODOMath * @author DODO Breeder * * @notice Functions for complex calculating. Including ONE Integration and TWO Quadratic solutions */ library DODOMath { using SafeMath for uint256; /* Integrate dodo curve from V1 to V2 require V0>=V1>=V2>0 res = (1-k)i(V1-V2)+ikV0*V0(1/V2-1/V1) let V1-V2=delta res = i*delta*(1-k+k(V0^2/V1/V2)) i is the price of V-res trading pair support k=1 & k=0 case [round down] */ function _GeneralIntegrate( uint256 V0, uint256 V1, uint256 V2, uint256 i, uint256 k ) internal pure returns (uint256) { require(V0 > 0, "TARGET_IS_ZERO"); uint256 fairAmount = i.mul(V1.sub(V2)); // i*delta if (k == 0) { return fairAmount.div(DecimalMath.ONE); } uint256 V0V0V1V2 = DecimalMath.divFloor(V0.mul(V0).div(V1), V2); uint256 penalty = DecimalMath.mulFloor(k, V0V0V1V2); // k(V0^2/V1/V2) return DecimalMath.ONE.sub(k).add(penalty).mul(fairAmount).div(DecimalMath.ONE2); } /* Follow the integration function above i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2) Assume Q2=Q0, Given Q1 and deltaB, solve Q0 i is the price of delta-V trading pair give out target of V support k=1 & k=0 case [round down] */ function _SolveQuadraticFunctionForTarget( uint256 V1, uint256 delta, uint256 i, uint256 k ) internal pure returns (uint256) { if (k == 0) { return V1.add(DecimalMath.mulFloor(i, delta)); } // V0 = V1*(1+(sqrt-1)/2k) // sqrt = √(1+4kidelta/V1) // premium = 1+(sqrt-1)/2k // uint256 sqrt = (4 * k).mul(i).mul(delta).div(V1).add(DecimalMath.ONE2).sqrt(); if (V1 == 0) { return 0; } uint256 sqrt; uint256 ki = (4 * k).mul(i); if (ki == 0) { sqrt = DecimalMath.ONE; } else if ((ki * delta) / ki == delta) { sqrt = (ki * delta).div(V1).add(DecimalMath.ONE2).sqrt(); } else { sqrt = ki.div(V1).mul(delta).add(DecimalMath.ONE2).sqrt(); } uint256 premium = DecimalMath.divFloor(sqrt.sub(DecimalMath.ONE), k * 2).add(DecimalMath.ONE); // V0 is greater than or equal to V1 according to the solution return DecimalMath.mulFloor(V1, premium); } /* Follow the integration expression above, we have: i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2) Given Q1 and deltaB, solve Q2 This is a quadratic function and the standard version is aQ2^2 + bQ2 + c = 0, where a=1-k -b=(1-k)Q1-kQ0^2/Q1+i*deltaB c=-kQ0^2 and Q2=(-b+sqrt(b^2+4(1-k)kQ0^2))/2(1-k) note: another root is negative, abondan if deltaBSig=true, then Q2>Q1, user sell Q and receive B if deltaBSig=false, then Q2<Q1, user sell B and receive Q return |Q1-Q2| as we only support sell amount as delta, the deltaB is always negative the input ideltaB is actually -ideltaB in the equation i is the price of delta-V trading pair support k=1 & k=0 case [round down] */ function _SolveQuadraticFunctionForTrade( uint256 V0, uint256 V1, uint256 delta, uint256 i, uint256 k ) internal pure returns (uint256) { require(V0 > 0, "TARGET_IS_ZERO"); if (delta == 0) { return 0; } if (k == 0) { return DecimalMath.mulFloor(i, delta) > V1 ? V1 : DecimalMath.mulFloor(i, delta); } if (k == DecimalMath.ONE) { // if k==1 // Q2=Q1/(1+ideltaBQ1/Q0/Q0) // temp = ideltaBQ1/Q0/Q0 // Q2 = Q1/(1+temp) // Q1-Q2 = Q1*(1-1/(1+temp)) = Q1*(temp/(1+temp)) // uint256 temp = i.mul(delta).mul(V1).div(V0.mul(V0)); uint256 temp; uint256 idelta = i.mul(delta); if (idelta == 0) { temp = 0; } else if ((idelta * V1) / idelta == V1) { temp = (idelta * V1).div(V0.mul(V0)); } else { temp = delta.mul(V1).div(V0).mul(i).div(V0); } return V1.mul(temp).div(temp.add(DecimalMath.ONE)); } // calculate -b value and sig // b = kQ0^2/Q1-i*deltaB-(1-k)Q1 // part1 = (1-k)Q1 >=0 // part2 = kQ0^2/Q1-i*deltaB >=0 // bAbs = abs(part1-part2) // if part1>part2 => b is negative => bSig is false // if part2>part1 => b is positive => bSig is true uint256 part2 = k.mul(V0).div(V1).mul(V0).add(i.mul(delta)); // kQ0^2/Q1-i*deltaB uint256 bAbs = DecimalMath.ONE.sub(k).mul(V1); // (1-k)Q1 bool bSig; if (bAbs >= part2) { bAbs = bAbs - part2; bSig = false; } else { bAbs = part2 - bAbs; bSig = true; } bAbs = bAbs.div(DecimalMath.ONE); // calculate sqrt uint256 squareRoot = DecimalMath.mulFloor( DecimalMath.ONE.sub(k).mul(4), DecimalMath.mulFloor(k, V0).mul(V0) ); // 4(1-k)kQ0^2 squareRoot = bAbs.mul(bAbs).add(squareRoot).sqrt(); // sqrt(b*b+4(1-k)kQ0*Q0) // final res uint256 denominator = DecimalMath.ONE.sub(k).mul(2); // 2(1-k) uint256 numerator; if (bSig) { numerator = squareRoot.sub(bAbs); if (numerator == 0) { revert("DODOMath: should not be zero"); } } else { numerator = bAbs.add(squareRoot); } uint256 V2 = DecimalMath.divCeil(numerator, denominator); if (V2 > V1) { return 0; } else { return V1 - V2; } } } // File: contracts/lib/PMMPricing.sol /** * @title Pricing * @author DODO Breeder * * @notice DODO Pricing model */ library PMMPricing { using SafeMath for uint256; enum RState {ONE, ABOVE_ONE, BELOW_ONE} struct PMMState { uint256 i; uint256 K; uint256 B; uint256 Q; uint256 B0; uint256 Q0; RState R; } // ============ buy & sell ============ function sellBaseToken(PMMState memory state, uint256 payBaseAmount) internal pure returns (uint256 receiveQuoteAmount, RState newR) { if (state.R == RState.ONE) { // case 1: R=1 // R falls below one receiveQuoteAmount = _ROneSellBaseToken(state, payBaseAmount); newR = RState.BELOW_ONE; } else if (state.R == RState.ABOVE_ONE) { uint256 backToOnePayBase = state.B0.sub(state.B); uint256 backToOneReceiveQuote = state.Q.sub(state.Q0); // case 2: R>1 // complex case, R status depends on trading amount if (payBaseAmount < backToOnePayBase) { // case 2.1: R status do not change receiveQuoteAmount = _RAboveSellBaseToken(state, payBaseAmount); newR = RState.ABOVE_ONE; if (receiveQuoteAmount > backToOneReceiveQuote) { // [Important corner case!] may enter this branch when some precision problem happens. And consequently contribute to negative spare quote amount // to make sure spare quote>=0, mannually set receiveQuote=backToOneReceiveQuote receiveQuoteAmount = backToOneReceiveQuote; } } else if (payBaseAmount == backToOnePayBase) { // case 2.2: R status changes to ONE receiveQuoteAmount = backToOneReceiveQuote; newR = RState.ONE; } else { // case 2.3: R status changes to BELOW_ONE receiveQuoteAmount = backToOneReceiveQuote.add( _ROneSellBaseToken(state, payBaseAmount.sub(backToOnePayBase)) ); newR = RState.BELOW_ONE; } } else { // state.R == RState.BELOW_ONE // case 3: R<1 receiveQuoteAmount = _RBelowSellBaseToken(state, payBaseAmount); newR = RState.BELOW_ONE; } } function sellQuoteToken(PMMState memory state, uint256 payQuoteAmount) internal pure returns (uint256 receiveBaseAmount, RState newR) { if (state.R == RState.ONE) { receiveBaseAmount = _ROneSellQuoteToken(state, payQuoteAmount); newR = RState.ABOVE_ONE; } else if (state.R == RState.ABOVE_ONE) { receiveBaseAmount = _RAboveSellQuoteToken(state, payQuoteAmount); newR = RState.ABOVE_ONE; } else { uint256 backToOnePayQuote = state.Q0.sub(state.Q); uint256 backToOneReceiveBase = state.B.sub(state.B0); if (payQuoteAmount < backToOnePayQuote) { receiveBaseAmount = _RBelowSellQuoteToken(state, payQuoteAmount); newR = RState.BELOW_ONE; if (receiveBaseAmount > backToOneReceiveBase) { receiveBaseAmount = backToOneReceiveBase; } } else if (payQuoteAmount == backToOnePayQuote) { receiveBaseAmount = backToOneReceiveBase; newR = RState.ONE; } else { receiveBaseAmount = backToOneReceiveBase.add( _ROneSellQuoteToken(state, payQuoteAmount.sub(backToOnePayQuote)) ); newR = RState.ABOVE_ONE; } } } // ============ R = 1 cases ============ function _ROneSellBaseToken(PMMState memory state, uint256 payBaseAmount) internal pure returns ( uint256 // receiveQuoteToken ) { // in theory Q2 <= targetQuoteTokenAmount // however when amount is close to 0, precision problems may cause Q2 > targetQuoteTokenAmount return DODOMath._SolveQuadraticFunctionForTrade( state.Q0, state.Q0, payBaseAmount, state.i, state.K ); } function _ROneSellQuoteToken(PMMState memory state, uint256 payQuoteAmount) internal pure returns ( uint256 // receiveBaseToken ) { return DODOMath._SolveQuadraticFunctionForTrade( state.B0, state.B0, payQuoteAmount, DecimalMath.reciprocalFloor(state.i), state.K ); } // ============ R < 1 cases ============ function _RBelowSellQuoteToken(PMMState memory state, uint256 payQuoteAmount) internal pure returns ( uint256 // receiveBaseToken ) { return DODOMath._GeneralIntegrate( state.Q0, state.Q.add(payQuoteAmount), state.Q, DecimalMath.reciprocalFloor(state.i), state.K ); } function _RBelowSellBaseToken(PMMState memory state, uint256 payBaseAmount) internal pure returns ( uint256 // receiveQuoteToken ) { return DODOMath._SolveQuadraticFunctionForTrade( state.Q0, state.Q, payBaseAmount, state.i, state.K ); } // ============ R > 1 cases ============ function _RAboveSellBaseToken(PMMState memory state, uint256 payBaseAmount) internal pure returns ( uint256 // receiveQuoteToken ) { return DODOMath._GeneralIntegrate( state.B0, state.B.add(payBaseAmount), state.B, state.i, state.K ); } function _RAboveSellQuoteToken(PMMState memory state, uint256 payQuoteAmount) internal pure returns ( uint256 // receiveBaseToken ) { return DODOMath._SolveQuadraticFunctionForTrade( state.B0, state.B, payQuoteAmount, DecimalMath.reciprocalFloor(state.i), state.K ); } // ============ Helper functions ============ function adjustedTarget(PMMState memory state) internal pure { if (state.R == RState.BELOW_ONE) { state.Q0 = DODOMath._SolveQuadraticFunctionForTarget( state.Q, state.B.sub(state.B0), state.i, state.K ); } else if (state.R == RState.ABOVE_ONE) { state.B0 = DODOMath._SolveQuadraticFunctionForTarget( state.B, state.Q.sub(state.Q0), DecimalMath.reciprocalFloor(state.i), state.K ); } } function getMidPrice(PMMState memory state) internal pure returns (uint256) { if (state.R == RState.BELOW_ONE) { uint256 R = DecimalMath.divFloor(state.Q0.mul(state.Q0).div(state.Q), state.Q); R = DecimalMath.ONE.sub(state.K).add(DecimalMath.mulFloor(state.K, R)); return DecimalMath.divFloor(state.i, R); } else { uint256 R = DecimalMath.divFloor(state.B0.mul(state.B0).div(state.B), state.B); R = DecimalMath.ONE.sub(state.K).add(DecimalMath.mulFloor(state.K, R)); return DecimalMath.mulFloor(state.i, R); } } } // File: contracts/intf/IERC20.sol // This is a file copied from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); function decimals() external view returns (uint8); function name() external view returns (string memory); function symbol() external view returns (string memory); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); } // File: contracts/lib/SafeERC20.sol /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; 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 { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "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/lib/InitializableOwnable.sol /** * @title Ownable * @author DODO Breeder * * @notice Ownership related functions */ contract InitializableOwnable { address public _OWNER_; address public _NEW_OWNER_; bool internal _INITIALIZED_; // ============ Events ============ event OwnershipTransferPrepared(address indexed previousOwner, address indexed newOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // ============ Modifiers ============ modifier notInitialized() { require(!_INITIALIZED_, "DODO_INITIALIZED"); _; } modifier onlyOwner() { require(msg.sender == _OWNER_, "NOT_OWNER"); _; } // ============ Functions ============ function initOwner(address newOwner) public notInitialized { _INITIALIZED_ = true; _OWNER_ = newOwner; } function transferOwnership(address newOwner) public onlyOwner { emit OwnershipTransferPrepared(_OWNER_, newOwner); _NEW_OWNER_ = newOwner; } function claimOwnership() public { require(msg.sender == _NEW_OWNER_, "INVALID_CLAIM"); emit OwnershipTransferred(_OWNER_, _NEW_OWNER_); _OWNER_ = _NEW_OWNER_; _NEW_OWNER_ = address(0); } } // File: contracts/lib/FeeRateModel.sol interface IFeeRateImpl { function getFeeRate(address pool, address trader) external view returns (uint256); } interface IFeeRateModel { function getFeeRate(address trader) external view returns (uint256); } contract FeeRateModel is InitializableOwnable { address public feeRateImpl; function setFeeProxy(address _feeRateImpl) public onlyOwner { feeRateImpl = _feeRateImpl; } function getFeeRate(address trader) external view returns (uint256) { if(feeRateImpl == address(0)) return 0; return IFeeRateImpl(feeRateImpl).getFeeRate(msg.sender,trader); } } // File: contracts/DODOVendingMachine/impl/DVMStorage.sol contract DVMStorage is ReentrancyGuard { using SafeMath for uint256; bool public _IS_OPEN_TWAP_ = false; bool internal _DVM_INITIALIZED_; // ============ Core Address ============ address public _MAINTAINER_; IERC20 public _BASE_TOKEN_; IERC20 public _QUOTE_TOKEN_; uint112 public _BASE_RESERVE_; uint112 public _QUOTE_RESERVE_; uint32 public _BLOCK_TIMESTAMP_LAST_; uint256 public _BASE_PRICE_CUMULATIVE_LAST_; // ============ Shares (ERC20) ============ string public symbol; uint8 public decimals; string public name; uint256 public totalSupply; mapping(address => uint256) internal _SHARES_; mapping(address => mapping(address => uint256)) internal _ALLOWED_; // ================= Permit ====================== bytes32 public DOMAIN_SEPARATOR; // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; mapping(address => uint256) public nonces; // ============ Variables for Pricing ============ uint256 public _LP_FEE_RATE_; IFeeRateModel public _MT_FEE_RATE_MODEL_; uint256 public _K_; uint256 public _I_; // ============ Helper Functions ============ function getPMMState() public view returns (PMMPricing.PMMState memory state) { state.i = _I_; state.K = _K_; state.B = _BASE_RESERVE_; state.Q = _QUOTE_RESERVE_; state.B0 = 0; // will be calculated in adjustedTarget state.Q0 = 0; state.R = PMMPricing.RState.ABOVE_ONE; PMMPricing.adjustedTarget(state); } function getPMMStateForCall() external view returns ( uint256 i, uint256 K, uint256 B, uint256 Q, uint256 B0, uint256 Q0, uint256 R ) { PMMPricing.PMMState memory state = getPMMState(); i = state.i; K = state.K; B = state.B; Q = state.Q; B0 = state.B0; Q0 = state.Q0; R = uint256(state.R); } function getMidPrice() public view returns (uint256 midPrice) { return PMMPricing.getMidPrice(getPMMState()); } } // File: contracts/DODOVendingMachine/impl/DVMVault.sol contract DVMVault is DVMStorage { using SafeMath for uint256; using SafeERC20 for IERC20; // ============ Events ============ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); event Mint(address indexed user, uint256 value); event Burn(address indexed user, uint256 value); // ============ View Functions ============ function getVaultReserve() external view returns (uint256 baseReserve, uint256 quoteReserve) { baseReserve = _BASE_RESERVE_; quoteReserve = _QUOTE_RESERVE_; } function getUserFeeRate(address user) external view returns (uint256 lpFeeRate, uint256 mtFeeRate) { lpFeeRate = _LP_FEE_RATE_; mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(user); } // ============ Asset In ============ function getBaseInput() public view returns (uint256 input) { return _BASE_TOKEN_.balanceOf(address(this)).sub(uint256(_BASE_RESERVE_)); } function getQuoteInput() public view returns (uint256 input) { return _QUOTE_TOKEN_.balanceOf(address(this)).sub(uint256(_QUOTE_RESERVE_)); } // ============ TWAP UPDATE =========== function _twapUpdate() internal { uint32 blockTimestamp = uint32(block.timestamp % 2**32); uint32 timeElapsed = blockTimestamp - _BLOCK_TIMESTAMP_LAST_; if (timeElapsed > 0 && _BASE_RESERVE_ != 0 && _QUOTE_RESERVE_ != 0) { _BASE_PRICE_CUMULATIVE_LAST_ += getMidPrice() * timeElapsed; } _BLOCK_TIMESTAMP_LAST_ = blockTimestamp; } // ============ Set States ============ function _setReserve(uint256 baseReserve, uint256 quoteReserve) internal { require(baseReserve <= uint112(-1) && quoteReserve <= uint112(-1), "OVERFLOW"); _BASE_RESERVE_ = uint112(baseReserve); _QUOTE_RESERVE_ = uint112(quoteReserve); if(_IS_OPEN_TWAP_) _twapUpdate(); } function _sync() internal { uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)); uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)); require(baseBalance <= uint112(-1) && quoteBalance <= uint112(-1), "OVERFLOW"); if (baseBalance != _BASE_RESERVE_) { _BASE_RESERVE_ = uint112(baseBalance); } if (quoteBalance != _QUOTE_RESERVE_) { _QUOTE_RESERVE_ = uint112(quoteBalance); } if(_IS_OPEN_TWAP_) _twapUpdate(); } function sync() external preventReentrant { _sync(); } // ============ Asset Out ============ function _transferBaseOut(address to, uint256 amount) internal { if (amount > 0) { _BASE_TOKEN_.safeTransfer(to, amount); } } function _transferQuoteOut(address to, uint256 amount) internal { if (amount > 0) { _QUOTE_TOKEN_.safeTransfer(to, amount); } } // ============ Shares (ERC20) ============ /** * @dev transfer token for a specified address * @param to The address to transfer to. * @param amount The amount to be transferred. */ function transfer(address to, uint256 amount) public returns (bool) { require(amount <= _SHARES_[msg.sender], "BALANCE_NOT_ENOUGH"); _SHARES_[msg.sender] = _SHARES_[msg.sender].sub(amount); _SHARES_[to] = _SHARES_[to].add(amount); emit Transfer(msg.sender, to, amount); return true; } /** * @dev Gets the balance of the specified address. * @param owner The address to query the the balance of. * @return balance An uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) external view returns (uint256 balance) { return _SHARES_[owner]; } /** * @dev Transfer tokens from one address to another * @param from address The address which you want to send tokens from * @param to address The address which you want to transfer to * @param amount uint256 the amount of tokens to be transferred */ function transferFrom( address from, address to, uint256 amount ) public returns (bool) { require(amount <= _SHARES_[from], "BALANCE_NOT_ENOUGH"); require(amount <= _ALLOWED_[from][msg.sender], "ALLOWANCE_NOT_ENOUGH"); _SHARES_[from] = _SHARES_[from].sub(amount); _SHARES_[to] = _SHARES_[to].add(amount); _ALLOWED_[from][msg.sender] = _ALLOWED_[from][msg.sender].sub(amount); emit Transfer(from, to, amount); return true; } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * @param spender The address which will spend the funds. * @param amount The amount of tokens to be spent. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(msg.sender, spender, amount); return true; } function _approve( address owner, address spender, uint256 amount ) private { _ALLOWED_[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Function to check the amount of tokens that an owner _ALLOWED_ to a spender. * @param owner address The address which owns the funds. * @param spender address The address which will spend the funds. * @return A uint256 specifying the amount of tokens still available for the spender. */ function allowance(address owner, address spender) public view returns (uint256) { return _ALLOWED_[owner][spender]; } function _mint(address user, uint256 value) internal { require(value > 1000, "MINT_INVALID"); _SHARES_[user] = _SHARES_[user].add(value); totalSupply = totalSupply.add(value); emit Mint(user, value); emit Transfer(address(0), user, value); } function _burn(address user, uint256 value) internal { _SHARES_[user] = _SHARES_[user].sub(value); totalSupply = totalSupply.sub(value); emit Burn(user, value); emit Transfer(user, address(0), value); } // ============================ Permit ====================================== function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external { require(deadline >= block.timestamp, "DODO_DVM_LP: EXPIRED"); bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256( abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline) ) ) ); address recoveredAddress = ecrecover(digest, v, r, s); require( recoveredAddress != address(0) && recoveredAddress == owner, "DODO_DVM_LP: INVALID_SIGNATURE" ); _approve(owner, spender, value); } } // File: contracts/DODOVendingMachine/impl/DVMFunding.sol contract DVMFunding is DVMVault { // ============ Events ============ event BuyShares(address to, uint256 increaseShares, uint256 totalShares); event SellShares(address payer, address to, uint256 decreaseShares, uint256 totalShares); // ============ Buy & Sell Shares ============ // buy shares [round down] function buyShares(address to) external preventReentrant returns ( uint256 shares, uint256 baseInput, uint256 quoteInput ) { uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)); uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)); uint256 baseReserve = _BASE_RESERVE_; uint256 quoteReserve = _QUOTE_RESERVE_; baseInput = baseBalance.sub(baseReserve); quoteInput = quoteBalance.sub(quoteReserve); require(baseInput > 0, "NO_BASE_INPUT"); // Round down when withdrawing. Therefore, never be a situation occuring balance is 0 but totalsupply is not 0 // But May Happen,reserve >0 But totalSupply = 0 if (totalSupply == 0) { // case 1. initial supply shares = baseBalance; // 以免出现balance很大但shares很小的情况 require(shares > 2001, "MINT_AMOUNT_NOT_ENOUGH"); _mint(address(0), 1001); shares -= 1001; } else if (baseReserve > 0 && quoteReserve == 0) { // case 2. supply when quote reserve is 0 shares = baseInput.mul(totalSupply).div(baseReserve); } else if (baseReserve > 0 && quoteReserve > 0) { // case 3. normal case uint256 baseInputRatio = DecimalMath.divFloor(baseInput, baseReserve); uint256 quoteInputRatio = DecimalMath.divFloor(quoteInput, quoteReserve); uint256 mintRatio = quoteInputRatio < baseInputRatio ? quoteInputRatio : baseInputRatio; shares = DecimalMath.mulFloor(totalSupply, mintRatio); } _mint(to, shares); _setReserve(baseBalance, quoteBalance); emit BuyShares(to, shares, _SHARES_[to]); } // sell shares [round down] function sellShares( uint256 shareAmount, address to, uint256 baseMinAmount, uint256 quoteMinAmount, bytes calldata data, uint256 deadline ) external preventReentrant returns (uint256 baseAmount, uint256 quoteAmount) { require(deadline >= block.timestamp, "TIME_EXPIRED"); require(shareAmount <= _SHARES_[msg.sender], "DLP_NOT_ENOUGH"); require(to != address(this), "SELL_BACK_NOT_ALLOWED"); uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)); uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)); uint256 totalShares = totalSupply; baseAmount = baseBalance.mul(shareAmount).div(totalShares); quoteAmount = quoteBalance.mul(shareAmount).div(totalShares); require( baseAmount >= baseMinAmount && quoteAmount >= quoteMinAmount, "WITHDRAW_NOT_ENOUGH" ); _burn(msg.sender, shareAmount); _transferBaseOut(to, baseAmount); _transferQuoteOut(to, quoteAmount); _sync(); if (data.length > 0) { IDODOCallee(to).DVMSellShareCall( msg.sender, shareAmount, baseAmount, quoteAmount, data ); } emit SellShares(msg.sender, to, shareAmount, _SHARES_[msg.sender]); } } // File: contracts/DODOVendingMachine/impl/DVMTrader.sol contract DVMTrader is DVMVault { using SafeMath for uint256; // ============ Events ============ event DODOSwap( address fromToken, address toToken, uint256 fromAmount, uint256 toAmount, address trader, address receiver ); event DODOFlashLoan( address borrower, address assetTo, uint256 baseAmount, uint256 quoteAmount ); // ============ Trade Functions ============ function sellBase(address to) external preventReentrant returns (uint256 receiveQuoteAmount) { uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)); uint256 baseInput = baseBalance.sub(uint256(_BASE_RESERVE_)); uint256 mtFee; (receiveQuoteAmount, mtFee) = querySellBase(tx.origin, baseInput); _transferQuoteOut(to, receiveQuoteAmount); _transferQuoteOut(_MAINTAINER_, mtFee); _setReserve(baseBalance, _QUOTE_TOKEN_.balanceOf(address(this))); emit DODOSwap( address(_BASE_TOKEN_), address(_QUOTE_TOKEN_), baseInput, receiveQuoteAmount, msg.sender, to ); } function sellQuote(address to) external preventReentrant returns (uint256 receiveBaseAmount) { uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)); uint256 quoteInput = quoteBalance.sub(uint256(_QUOTE_RESERVE_)); uint256 mtFee; (receiveBaseAmount, mtFee) = querySellQuote(tx.origin, quoteInput); _transferBaseOut(to, receiveBaseAmount); _transferBaseOut(_MAINTAINER_, mtFee); _setReserve(_BASE_TOKEN_.balanceOf(address(this)), quoteBalance); emit DODOSwap( address(_QUOTE_TOKEN_), address(_BASE_TOKEN_), quoteInput, receiveBaseAmount, msg.sender, to ); } function flashLoan( uint256 baseAmount, uint256 quoteAmount, address assetTo, bytes calldata data ) external preventReentrant { _transferBaseOut(assetTo, baseAmount); _transferQuoteOut(assetTo, quoteAmount); if (data.length > 0) IDODOCallee(assetTo).DVMFlashLoanCall(msg.sender, baseAmount, quoteAmount, data); uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)); uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)); // no input -> pure loss require( baseBalance >= _BASE_RESERVE_ || quoteBalance >= _QUOTE_RESERVE_, "FLASH_LOAN_FAILED" ); // sell quote if (baseBalance < _BASE_RESERVE_) { uint256 quoteInput = quoteBalance.sub(uint256(_QUOTE_RESERVE_)); (uint256 receiveBaseAmount, uint256 mtFee) = querySellQuote(tx.origin, quoteInput); require(uint256(_BASE_RESERVE_).sub(baseBalance) <= receiveBaseAmount, "FLASH_LOAN_FAILED"); _transferBaseOut(_MAINTAINER_, mtFee); emit DODOSwap( address(_QUOTE_TOKEN_), address(_BASE_TOKEN_), quoteInput, receiveBaseAmount, msg.sender, assetTo ); } // sell base if (quoteBalance < _QUOTE_RESERVE_) { uint256 baseInput = baseBalance.sub(uint256(_BASE_RESERVE_)); (uint256 receiveQuoteAmount, uint256 mtFee) = querySellBase(tx.origin, baseInput); require(uint256(_QUOTE_RESERVE_).sub(quoteBalance) <= receiveQuoteAmount, "FLASH_LOAN_FAILED"); _transferQuoteOut(_MAINTAINER_, mtFee); emit DODOSwap( address(_BASE_TOKEN_), address(_QUOTE_TOKEN_), baseInput, receiveQuoteAmount, msg.sender, assetTo ); } _sync(); emit DODOFlashLoan(msg.sender, assetTo, baseAmount, quoteAmount); } // ============ Query Functions ============ function querySellBase(address trader, uint256 payBaseAmount) public view returns (uint256 receiveQuoteAmount, uint256 mtFee) { (receiveQuoteAmount, ) = PMMPricing.sellBaseToken(getPMMState(), payBaseAmount); uint256 lpFeeRate = _LP_FEE_RATE_; uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader); mtFee = DecimalMath.mulFloor(receiveQuoteAmount, mtFeeRate); receiveQuoteAmount = receiveQuoteAmount .sub(DecimalMath.mulFloor(receiveQuoteAmount, lpFeeRate)) .sub(mtFee); } function querySellQuote(address trader, uint256 payQuoteAmount) public view returns (uint256 receiveBaseAmount, uint256 mtFee) { (receiveBaseAmount, ) = PMMPricing.sellQuoteToken(getPMMState(), payQuoteAmount); uint256 lpFeeRate = _LP_FEE_RATE_; uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader); mtFee = DecimalMath.mulFloor(receiveBaseAmount, mtFeeRate); receiveBaseAmount = receiveBaseAmount .sub(DecimalMath.mulFloor(receiveBaseAmount, lpFeeRate)) .sub(mtFee); } } // File: contracts/DODOVendingMachine/impl/DVM.sol /** * @title DODO VendingMachine * @author DODO Breeder * * @notice DODOVendingMachine initialization */ contract DVM is DVMTrader, DVMFunding { function init( address maintainer, address baseTokenAddress, address quoteTokenAddress, uint256 lpFeeRate, address mtFeeRateModel, uint256 i, uint256 k, bool isOpenTWAP ) external { require(!_DVM_INITIALIZED_, "DVM_INITIALIZED"); _DVM_INITIALIZED_ = true; require(baseTokenAddress != quoteTokenAddress, "BASE_QUOTE_CAN_NOT_BE_SAME"); _BASE_TOKEN_ = IERC20(baseTokenAddress); _QUOTE_TOKEN_ = IERC20(quoteTokenAddress); require(i > 0 && i <= 10**36); _I_ = i; require(k <= 10**18); _K_ = k; _LP_FEE_RATE_ = lpFeeRate; _MT_FEE_RATE_MODEL_ = IFeeRateModel(mtFeeRateModel); _MAINTAINER_ = maintainer; _IS_OPEN_TWAP_ = isOpenTWAP; if(isOpenTWAP) _BLOCK_TIMESTAMP_LAST_ = uint32(block.timestamp % 2**32); string memory connect = "_"; string memory suffix = "DLP"; name = string(abi.encodePacked(suffix, connect, addressToShortString(address(this)))); symbol = "DLP"; decimals = _BASE_TOKEN_.decimals(); // ============================== Permit ==================================== uint256 chainId; assembly { chainId := chainid() } DOMAIN_SEPARATOR = keccak256( abi.encode( // keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, keccak256(bytes(name)), keccak256(bytes("1")), chainId, address(this) ) ); // ========================================================================== } function addressToShortString(address _addr) public pure returns (string memory) { bytes32 value = bytes32(uint256(_addr)); bytes memory alphabet = "0123456789abcdef"; bytes memory str = new bytes(8); for (uint256 i = 0; i < 4; i++) { str[i * 2] = alphabet[uint8(value[i + 12] >> 4)]; str[1 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; } return string(str); } // ============ Version Control ============ function version() external pure returns (string memory) { return "DVM 1.0.3"; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"increaseShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalShares","type":"uint256"}],"name":"BuyShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"assetTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"baseAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"name":"DODOFlashLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"fromToken","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"}],"name":"DODOSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"decreaseShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalShares","type":"uint256"}],"name":"SellShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BASE_PRICE_CUMULATIVE_LAST_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BASE_RESERVE_","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BASE_TOKEN_","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_BLOCK_TIMESTAMP_LAST_","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_IS_OPEN_TWAP_","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_I_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_K_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_LP_FEE_RATE_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MAINTAINER_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MT_FEE_RATE_MODEL_","outputs":[{"internalType":"contract IFeeRateModel","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_QUOTE_RESERVE_","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_QUOTE_TOKEN_","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"addressToShortString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"buyShares","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"baseInput","type":"uint256"},{"internalType":"uint256","name":"quoteInput","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"},{"internalType":"address","name":"assetTo","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBaseInput","outputs":[{"internalType":"uint256","name":"input","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMidPrice","outputs":[{"internalType":"uint256","name":"midPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPMMState","outputs":[{"components":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"K","type":"uint256"},{"internalType":"uint256","name":"B","type":"uint256"},{"internalType":"uint256","name":"Q","type":"uint256"},{"internalType":"uint256","name":"B0","type":"uint256"},{"internalType":"uint256","name":"Q0","type":"uint256"},{"internalType":"enum PMMPricing.RState","name":"R","type":"uint8"}],"internalType":"struct PMMPricing.PMMState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPMMStateForCall","outputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"K","type":"uint256"},{"internalType":"uint256","name":"B","type":"uint256"},{"internalType":"uint256","name":"Q","type":"uint256"},{"internalType":"uint256","name":"B0","type":"uint256"},{"internalType":"uint256","name":"Q0","type":"uint256"},{"internalType":"uint256","name":"R","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuoteInput","outputs":[{"internalType":"uint256","name":"input","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserFeeRate","outputs":[{"internalType":"uint256","name":"lpFeeRate","type":"uint256"},{"internalType":"uint256","name":"mtFeeRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultReserve","outputs":[{"internalType":"uint256","name":"baseReserve","type":"uint256"},{"internalType":"uint256","name":"quoteReserve","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"maintainer","type":"address"},{"internalType":"address","name":"baseTokenAddress","type":"address"},{"internalType":"address","name":"quoteTokenAddress","type":"address"},{"internalType":"uint256","name":"lpFeeRate","type":"uint256"},{"internalType":"address","name":"mtFeeRateModel","type":"address"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"k","type":"uint256"},{"internalType":"bool","name":"isOpenTWAP","type":"bool"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"payBaseAmount","type":"uint256"}],"name":"querySellBase","outputs":[{"internalType":"uint256","name":"receiveQuoteAmount","type":"uint256"},{"internalType":"uint256","name":"mtFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trader","type":"address"},{"internalType":"uint256","name":"payQuoteAmount","type":"uint256"}],"name":"querySellQuote","outputs":[{"internalType":"uint256","name":"receiveBaseAmount","type":"uint256"},{"internalType":"uint256","name":"mtFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"sellBase","outputs":[{"internalType":"uint256","name":"receiveQuoteAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"sellQuote","outputs":[{"internalType":"uint256","name":"receiveBaseAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareAmount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"baseMinAmount","type":"uint256"},{"internalType":"uint256","name":"quoteMinAmount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"sellShares","outputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
60806040526000805461ff001916905534801561001b57600080fd5b50613f7a8061002b6000396000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c80637d72150411610151578063d4b97046116100c3578063ee27c68911610087578063ee27c689146104e1578063f6b06e70146104e9578063f811d692146104f1578063fd1ed7e9146104f9578063fe24cb7f14610514578063fff6cae91461051c57610269565b8063d4b9704614610498578063d505accf146104a0578063dd62ed3e146104b3578063dd93f59a146104c6578063ec2fd46d146104d957610269565b8063a9059cbb11610115578063a9059cbb1461043c578063ab44a7a31461044f578063b56ceaa614610457578063bbf5ce781461046a578063bd6015b414610472578063d0a494e41461048557610269565b80637d721504146103e25780637ecebe00146103f7578063880a4d871461040a57806395d89b411461041f578063a382d1b91461042757610269565b80634322ec83116101ea57806354fd4d50116101ae57806354fd4d501461039157806365f6fcbb1461039957806366410a21146103a157806370a08231146103b457806371f9100c146103c757806379a04876146103cf57610269565b80634322ec831461032a578063440966091461033f5780634a248d2a146103525780634c85b4251461035a5780635039972a1461037c57610269565b80632df6cb48116102315780632df6cb48146102e757806330adf81f146102ef578063313ce567146102f757806336223ce91461030c5780633644e5151461032257610269565b806306fdde031461026e578063095ea7b31461028c57806317101940146102ac57806318160ddd146102bf57806323b872dd146102d4575b600080fd5b610276610524565b604051610283919061396d565b60405180910390f35b61029f61029a366004613540565b6105b2565b60405161028391906138db565b6102766102ba3660046133ba565b6105c9565b6102c76106f3565b60405161028391906138e6565b61029f6102e2366004613492565b6106f9565b61029f61087d565b6102c761088b565b6102ff6108af565b6040516102839190613e98565b6103146108b8565b604051610283929190613e33565b6102c76108d3565b6103326108d9565b60405161028391906137b1565b61031461034d3660046133ba565b6108ef565b61033261097a565b61036d6103683660046133ba565b610989565b60405161028393929190613e41565b61038f61038a366004613409565b610c79565b005b610276610fb7565b6102c7610fdb565b6103146103af366004613540565b611082565b6102c76103c23660046133ba565b611157565b6102c7611172565b6103146103dd366004613540565b6111be565b6103ea6111d2565b6040516102839190613e1f565b6102c76104053660046133ba565b6111e1565b6104126111f3565b6040516102839190613e87565b610276611206565b61042f611261565b6040516102839190613dc5565b61029f61044a366004613540565b6112b5565b6102c7611384565b61031461046536600461359e565b61138a565b6103ea6116ac565b6102c76104803660046133ba565b6116c2565b61038f610493366004613618565b6118ae565b610332611cdc565b61038f6104ae3660046134d2565b611ceb565b6102c76104c13660046133d5565b611e5a565b6102c76104d43660046133ba565b611e85565b6102c7612055565b6102c761205b565b61033261206d565b6102c761207c565b610501612082565b6040516102839796959493929190613e57565b6102c76120e5565b61038f6120eb565b6007805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105aa5780601f1061057f576101008083540402835291602001916105aa565b820191906000526020600020905b81548152906001019060200180831161058d57829003601f168201915b505050505081565b60006105bf33848461212f565b5060015b92915050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b6020820152815160088082528184019093526060926001600160a01b0385169291849160208201818036833701905050905060005b60048110156106e8578260048583600c016020811061063a57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061065a57fe5b602001015160f81c60f81b82826002028151811061067457fe5b60200101906001600160f81b031916908160001a905350828482600c016020811061069b57fe5b825191901a600f169081106106ac57fe5b602001015160f81c60f81b8282600202600101815181106106c957fe5b60200101906001600160f81b031916908160001a90535060010161061f565b50925050505b919050565b60085481565b6001600160a01b03831660009081526009602052604081205482111561073a5760405162461bcd60e51b815260040161073190613c8a565b60405180910390fd5b6001600160a01b0384166000908152600a6020908152604080832033845290915290205482111561077d5760405162461bcd60e51b8152600401610731906139fb565b6001600160a01b0384166000908152600960205260409020546107a6908363ffffffff61219716565b6001600160a01b0380861660009081526009602052604080822093909355908516815220546107db908363ffffffff6121bf16565b6001600160a01b038085166000908152600960209081526040808320949094559187168152600a8252828120338252909152205461081f908363ffffffff61219716565b6001600160a01b038086166000818152600a60209081526040808320338452909152908190209390935591519085169190600080516020613f058339815191529061086b9086906138e6565b60405180910390a35060019392505050565b600054610100900460ff1681565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b6003546001600160701b0380821692600160701b9092041690565b600b5481565b600054630100000090046001600160a01b031681565b600d54600e54604051638198edbf60e01b81526000916001600160a01b031690638198edbf906109239086906004016137b1565b60206040518083038186803b15801561093b57600080fd5b505afa15801561094f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109739190613586565b9050915091565b6001546001600160a01b031681565b600080548190819060ff16156109b15760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660019081178255546040516370a0823160e01b81526001600160a01b03909116906370a08231906109ee9030906004016137b1565b60206040518083038186803b158015610a0657600080fd5b505afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190613586565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190610a749030906004016137b1565b60206040518083038186803b158015610a8c57600080fd5b505afa158015610aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac49190613586565b6003549091506001600160701b0380821691600160701b900416610aee848363ffffffff61219716565b9550610b00838263ffffffff61219716565b945060008611610b225760405162461bcd60e51b815260040161073190613b0f565b600854610b66578396506107d18711610b4d5760405162461bcd60e51b8152600401610731906139cb565b610b5a60006103e96121eb565b6103e987039650610bfb565b600082118015610b74575080155b15610ba557610b9e82610b92600854896122e590919063ffffffff16565b9063ffffffff61231f16565b9650610bfb565b600082118015610bb55750600081115b15610bfb576000610bc68784612351565b90506000610bd48784612351565b90506000828210610be55782610be7565b815b9050610bf56008548261236f565b99505050505b610c0588886121eb565b610c0f8484612391565b6001600160a01b038816600090815260096020526040908190205490517f1c172440bdebb59cd92a7f08f4227903a3305ab6f880cb25f93eddb66843a10291610c5b918b918b916138ba565b60405180910390a150506000805460ff191690555092949193509150565b60005462010000900460ff1615610ca25760405162461bcd60e51b815260040161073190613b5e565b6000805462ff00001916620100001790556001600160a01b038781169087161415610cdf5760405162461bcd60e51b815260040161073190613aa3565b600180546001600160a01b03808a166001600160a01b03199283161790925560028054928916929091169190911790558215801590610d2d57506ec097ce7bc90715b34b9f10000000008311155b610d3657600080fd5b6010839055670de0b6b3a7640000821115610d5057600080fd5b600f829055600d859055600e80546001600160a01b038087166001600160a01b03199092169190911790915560008054831580156101000261ff0019948d166301000000026301000000600160b81b03199093169290921793909316179055610dd157600380546001600160e01b03164263ffffffff16600160e01b021790555b60408051808201825260018152605f60f81b602080830191909152825180840190935260038352620444c560ec1b90830152908082610e0f306105c9565b604051602001610e2193929190613751565b60405160208183030381529060405260079080519060200190610e45929190613284565b50604080518082019091526003808252620444c560ec1b6020909201918252610e7091600591613284565b50600160009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610ebf57600080fd5b505afa158015610ed3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef7919061367f565b6006805460ff191660ff9290921691909117905560405146907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90610f3e906007906136e1565b60408051918290038220828201825260018352603160f81b6020938401529051610f8f93927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6918691309101613941565b60408051601f198184030181529190528051602090910120600b555050505050505050505050565b60408051808201909152600981526844564d20312e302e3360b81b60208201525b90565b6003546001546040516370a0823160e01b815260009261107d926001600160701b03909116916001600160a01b03909116906370a08231906110219030906004016137b1565b60206040518083038186803b15801561103957600080fd5b505afa15801561104d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110719190613586565b9063ffffffff61219716565b905090565b600080611096611090611261565b84612420565b50600d54600e54604051638198edbf60e01b815292945090916000916001600160a01b031690638198edbf906110d09089906004016137b1565b60206040518083038186803b1580156110e857600080fd5b505afa1580156110fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111209190613586565b905061112c848261236f565b925061114c8361107161113f878661236f565b879063ffffffff61219716565b935050509250929050565b6001600160a01b031660009081526009602052604090205490565b6003546002546040516370a0823160e01b815260009261107d92600160701b9091046001600160701b0316916001600160a01b03909116906370a08231906110219030906004016137b1565b6000806110966111cc611261565b84612526565b6003546001600160701b031681565b600c6020526000908152604090205481565b600354600160e01b900463ffffffff1681565b6005805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105aa5780601f1061057f576101008083540402835291602001916105aa565b611269613302565b6010548152600f5460208201526003546001600160701b038082166040840152600160701b90910416606082015260006080820181905260a0820152600160c0820152610fd881612627565b336000908152600960205260408120548211156112e45760405162461bcd60e51b815260040161073190613c8a565b33600090815260096020526040902054611304908363ffffffff61219716565b33600090815260096020526040808220929092556001600160a01b03851681522054611336908363ffffffff6121bf16565b6001600160a01b038416600081815260096020526040908190209290925590513390600080516020613f05833981519152906113739086906138e6565b60405180910390a350600192915050565b600d5481565b60008054819060ff16156113b05760405162461bcd60e51b815260040161073190613a51565b6000805460ff19166001179055428310156113dd5760405162461bcd60e51b815260040161073190613d7c565b3360009081526009602052604090205489111561140c5760405162461bcd60e51b815260040161073190613c62565b6001600160a01b0388163014156114355760405162461bcd60e51b815260040161073190613a74565b6001546040516370a0823160e01b81526000916001600160a01b0316906370a08231906114669030906004016137b1565b60206040518083038186803b15801561147e57600080fd5b505afa158015611492573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b69190613586565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906114ec9030906004016137b1565b60206040518083038186803b15801561150457600080fd5b505afa158015611518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153c9190613586565b60085490915061155681610b92858f63ffffffff6122e516565b945061156c81610b92848f63ffffffff6122e516565b935089851015801561157e5750888410155b61159a5760405162461bcd60e51b815260040161073190613c35565b6115a4338d6126d1565b6115ae8b8661279e565b6115b88b856127c1565b6115c06127e4565b861561162f578a6001600160a01b0316632411d338338e88888d8d6040518763ffffffff1660e01b81526004016115fc96959493929190613827565b600060405180830381600087803b15801561161657600080fd5b505af115801561162a573d6000803e3d6000fd5b505050505b7f55caccde83781f39bfc1296eff45655b6496729443a7d48958b18b3b685600a5338c8e60096000336001600160a01b03166001600160a01b031681526020019081526020016000205460405161168994939291906137c5565b60405180910390a150506000805460ff1916905550909890975095505050505050565b600354600160701b90046001600160701b031681565b6000805460ff16156116e65760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660019081178255546040516370a0823160e01b81526001600160a01b03909116906370a08231906117239030906004016137b1565b60206040518083038186803b15801561173b57600080fd5b505afa15801561174f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117739190613586565b6003549091506000906117969083906001600160701b031663ffffffff61219716565b905060006117a432836111be565b90945090506117b385856127c1565b6000546117d090630100000090046001600160a01b0316826127c1565b6002546040516370a0823160e01b815261185b9185916001600160a01b03909116906370a08231906118069030906004016137b1565b60206040518083038186803b15801561181e57600080fd5b505afa158015611832573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118569190613586565b612391565b600154600254604051600080516020613f2583398151915292611894926001600160a01b03918216929116908690899033908c90613867565b60405180910390a150506000805460ff1916905550919050565b60005460ff16156118d15760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660011790556118e8838661279e565b6118f283856127c1565b801561195f5760405163eb2021c360e01b81526001600160a01b0384169063eb2021c39061192c90339089908990889088906004016137ee565b600060405180830381600087803b15801561194657600080fd5b505af115801561195a573d6000803e3d6000fd5b505050505b6001546040516370a0823160e01b81526000916001600160a01b0316906370a08231906119909030906004016137b1565b60206040518083038186803b1580156119a857600080fd5b505afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e09190613586565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190611a169030906004016137b1565b60206040518083038186803b158015611a2e57600080fd5b505afa158015611a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a669190613586565b6003549091506001600160701b031682101580611a955750600354600160701b90046001600160701b03168110155b611ab15760405162461bcd60e51b8152600401610731906139a0565b6003546001600160701b0316821015611b9757600354600090611ae5908390600160701b90046001600160701b0316612197565b9050600080611af43284611082565b60035491935091508290611b17906001600160701b03168763ffffffff61219716565b1115611b355760405162461bcd60e51b8152600401610731906139a0565b600054611b5290630100000090046001600160a01b03168261279e565b600254600154604051600080516020613f2583398151915292611b8b926001600160a01b03918216929116908790879033908f90613867565b60405180910390a15050505b600354600160701b90046001600160701b0316811015611c8457600354600090611bd19084906001600160701b031663ffffffff61219716565b9050600080611be032846111be565b60035491935091508290611c0490600160701b90046001600160701b031686612197565b1115611c225760405162461bcd60e51b8152600401610731906139a0565b600054611c3f90630100000090046001600160a01b0316826127c1565b600154600254604051600080516020613f2583398151915292611c78926001600160a01b03918216929116908790879033908f90613867565b60405180910390a15050505b611c8c6127e4565b7f0b82e93068db15abd9fbb2682c65462ea8a0a10582dce93a5664818e296f54eb33868989604051611cc194939291906137c5565b60405180910390a150506000805460ff191690555050505050565b6002546001600160a01b031681565b42841015611d0b5760405162461bcd60e51b815260040161073190613c07565b600b546001600160a01b0388166000908152600c602090815260408083208054600181019091559051929392611d6c927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d92918d91016138ef565b60405160208183030381529060405280519060200120604051602001611d93929190613796565b604051602081830303815290604052805190602001209050600060018286868660405160008152602001604052604051611dd09493929190613923565b6020604051602081039080840390855afa158015611df2573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611e285750886001600160a01b0316816001600160a01b0316145b611e445760405162461bcd60e51b815260040161073190613d45565b611e4f89898961212f565b505050505050505050565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b6000805460ff1615611ea95760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660011781556002546040516370a0823160e01b81526001600160a01b03909116906370a0823190611ee69030906004016137b1565b60206040518083038186803b158015611efe57600080fd5b505afa158015611f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f369190613586565b600354909150600090611f5a908390600160701b90046001600160701b0316612197565b90506000611f683283611082565b9094509050611f77858561279e565b600054611f9490630100000090046001600160a01b03168261279e565b6001546040516370a0823160e01b815261201c916001600160a01b0316906370a0823190611fc69030906004016137b1565b60206040518083038186803b158015611fde57600080fd5b505afa158015611ff2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120169190613586565b84612391565b600254600154604051600080516020613f2583398151915292611894926001600160a01b03918216929116908690899033908c90613867565b600f5481565b600061107d612068611261565b6129ab565b600e546001600160a01b031681565b60105481565b6000806000806000806000612095613302565b61209d611261565b905080600001519750806020015196508060400151955080606001519450806080015193508060a0015192508060c0015160028111156120d957fe5b91505090919293949596565b60045481565b60005460ff161561210e5760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660011790556121236127e4565b6000805460ff19169055565b6001600160a01b038084166000818152600a602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061218a9085906138e6565b60405180910390a3505050565b6000828211156121b95760405162461bcd60e51b815260040161073190613be4565b50900390565b6000828201838110156121e45760405162461bcd60e51b815260040161073190613cd8565b9392505050565b6103e8811161220c5760405162461bcd60e51b815260040161073190613bbe565b6001600160a01b038216600090815260096020526040902054612235908263ffffffff6121bf16565b6001600160a01b038316600090815260096020526040902055600854612261908263ffffffff6121bf16565b6008556040516001600160a01b038316907f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968859061229f9084906138e6565b60405180910390a2816001600160a01b031660006001600160a01b0316600080516020613f05833981519152836040516122d991906138e6565b60405180910390a35050565b6000826122f4575060006105c3565b8282028284828161230157fe5b04146121e45760405162461bcd60e51b815260040161073190613da2565b60008082116123405760405162461bcd60e51b815260040161073190613b36565b81838161234957fe5b049392505050565b60006121e482610b9285670de0b6b3a764000063ffffffff6122e516565b6000670de0b6b3a764000061238a848463ffffffff6122e516565b8161234957fe5b6001600160701b0382118015906123af57506001600160701b038111155b6123cb5760405162461bcd60e51b815260040161073190613cb6565b600380546001600160701b03838116600160701b02600160701b600160e01b03199186166001600160701b0319909316929092171617905560005460ff610100909104161561241c5761241c612a9d565b5050565b600080808460c00151600281111561243457fe5b141561244f576124448484612b32565b91506001905061251f565b60018460c00151600281111561246157fe5b1415612471576124448484612b59565b600061248e85606001518660a0015161219790919063ffffffff16565b905060006124ad8660800151876040015161219790919063ffffffff16565b9050818510156124d8576124c18686612b76565b935060029250808411156124d3578093505b61251c565b818514156124ec578093506000925061251c565b61251561250887612503888663ffffffff61219716565b612b32565b829063ffffffff6121bf16565b9350600192505b50505b9250929050565b600080808460c00151600281111561253a57fe5b14156125555761254a8484612bb1565b91506002905061251f565b60018460c00151600281111561256757fe5b141561261257600061258a8560400151866080015161219790919063ffffffff16565b905060006125a98660a00151876060015161219790919063ffffffff16565b9050818510156125d4576125bd8686612bd0565b935060019250808411156125cf578093505b61260b565b818514156125e8578093506000925061260b565b612604612508876125ff888663ffffffff61219716565b612bb1565b9350600292505b505061251f565b61261c8484612c02565b946002945092505050565b60028160c00151600281111561263957fe5b14156126785761266e81606001516126628360800151846040015161219790919063ffffffff16565b83516020850151612c21565b60a08201526126ce565b60018160c00151600281111561268a57fe5b14156126ce576126c881604001516126b38360a00151846060015161219790919063ffffffff16565b83516126be90612d47565b8460200151612c21565b60808201525b50565b6001600160a01b0382166000908152600960205260409020546126fa908263ffffffff61219716565b6001600160a01b038316600090815260096020526040902055600854612726908263ffffffff61219716565b6008556040516001600160a01b038316907fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5906127649084906138e6565b60405180910390a260006001600160a01b0316826001600160a01b0316600080516020613f05833981519152836040516122d991906138e6565b801561241c5760015461241c906001600160a01b0316838363ffffffff612d6816565b801561241c5760025461241c906001600160a01b0316838363ffffffff612d6816565b6001546040516370a0823160e01b81526000916001600160a01b0316906370a08231906128159030906004016137b1565b60206040518083038186803b15801561282d57600080fd5b505afa158015612841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128659190613586565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a082319061289b9030906004016137b1565b60206040518083038186803b1580156128b357600080fd5b505afa1580156128c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128eb9190613586565b90506001600160701b03821180159061290b57506001600160701b038111155b6129275760405162461bcd60e51b815260040161073190613cb6565b6003546001600160701b0316821461295557600380546001600160701b0319166001600160701b0384161790555b600354600160701b90046001600160701b031681146129935760038054600160701b600160e01b031916600160701b6001600160701b038416021790555b600054610100900460ff161561241c5761241c612a9d565b600060028260c0015160028111156129bf57fe5b1415612a4a57606082015160a08301516000916129f5916129eb9190610b92908063ffffffff6122e516565b8460600151612351565b9050612a32612a0884602001518361236f565b6020850151612a2690670de0b6b3a76400009063ffffffff61219716565b9063ffffffff6121bf16565b9050612a42836000015182612351565b9150506106ee565b60408201516080830151600091612a7a91612a709190610b92908063ffffffff6122e516565b8460400151612351565b9050612a8d612a0884602001518361236f565b9050612a4283600001518261236f565b60035463ffffffff42811691600160e01b90048116820390811615801590612acf57506003546001600160701b031615155b8015612aec5750600354600160701b90046001600160701b031615155b15612b0c578063ffffffff16612b0061205b565b60048054919092020190555b506003805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b60006121e48360800151846080015184612b4f8760000151612d47565b8760200151612dc3565b60006121e48360800151846040015184612b4f8760000151612d47565b60006121e48360a00151612b978486606001516121bf90919063ffffffff16565b60608601518651612ba790612d47565b8760200151613060565b60006121e48360a001518460a001518486600001518760200151612dc3565b60006121e48360800151612bf18486604001516121bf90919063ffffffff16565b604086015186516020880151613060565b60006121e48360a0015184606001518486600001518760200151612dc3565b600081612c4957612c42612c35848661236f565b869063ffffffff6121bf16565b9050612d3f565b84612c5657506000612d3f565b600080612c6c600485028663ffffffff6122e516565b905080612c8357670de0b6b3a76400009150612d03565b858187830281612c8f57fe5b041415612cca57612cc3612cbe6ec097ce7bc90715b34b9f1000000000612a26848a028b63ffffffff61231f16565b613139565b9150612d03565b612d00612cbe6ec097ce7bc90715b34b9f1000000000612a2689612cf4868d63ffffffff61231f16565b9063ffffffff6122e516565b91505b6000612d2d670de0b6b3a7640000612a26612d24868363ffffffff61219716565b88600202612351565b9050612d39888261236f565b93505050505b949350505050565b60006105c36ec097ce7bc90715b34b9f10000000008363ffffffff61231f16565b612dbe8363a9059cbb60e01b8484604051602401612d879291906138a1565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613170565b505050565b6000808611612de45760405162461bcd60e51b815260040161073190613a29565b83612df157506000613057565b81612e1e5784612e01848661236f565b11612e1557612e10838561236f565b612e17565b845b9050613057565b670de0b6b3a7640000821415612ede57600080612e41858763ffffffff6122e516565b905080612e515760009150612eaa565b868188830281612e5d57fe5b041415612e8d57612e86612e77898063ffffffff6122e516565b8289029063ffffffff61231f16565b9150612eaa565b612ea788610b9287612cf483838c8e63ffffffff6122e516565b91505b612ed5612ec583670de0b6b3a764000063ffffffff6121bf16565b610b92898563ffffffff6122e516565b92505050613057565b6000612f0b612ef3858763ffffffff6122e516565b612a2689612cf48a610b92898463ffffffff6122e516565b90506000612f2b87612cf4670de0b6b3a76400008763ffffffff61219716565b90506000828210612f4157508190036000612f47565b50810360015b612f5f82670de0b6b3a764000063ffffffff61231f16565b91506000612f96612f836004612cf4670de0b6b3a76400008a63ffffffff61219716565b612f918c612cf48a8f61236f565b61236f565b9050612faf612cbe82612a26868063ffffffff6122e516565b90506000612fd06002612cf4670de0b6b3a76400008a63ffffffff61219716565b90506000831561300e57612fea838663ffffffff61219716565b9050806130095760405162461bcd60e51b815260040161073190613b87565b613021565b61301e858463ffffffff6121bf16565b90505b600061302d828461322d565b90508b811115613047576000975050505050505050613057565b8b03965061305795505050505050565b95945050505050565b60008086116130815760405162461bcd60e51b815260040161073190613a29565b60006130a3613096878763ffffffff61219716565b859063ffffffff6122e516565b9050826130ca576130c281670de0b6b3a764000063ffffffff61231f16565b915050613057565b60006130e96130e388610b928b8063ffffffff6122e516565b87612351565b905060006130f7858361236f565b905061312c6ec097ce7bc90715b34b9f1000000000610b9285612cf485612a26670de0b6b3a76400008c63ffffffff61219716565b9998505050505050505050565b80600160028204015b8181101561316a5780915060028182858161315957fe5b04018161316257fe5b049050613142565b50919050565b60006060836001600160a01b03168360405161318c91906136c5565b6000604051808303816000865af19150503d80600081146131c9576040519150601f19603f3d011682016040523d82523d6000602084013e6131ce565b606091505b5091509150816131f05760405162461bcd60e51b815260040161073190613ada565b805115613227578080602001905181019061320b919061356a565b6132275760405162461bcd60e51b815260040161073190613cfb565b50505050565b60006121e48261324b85670de0b6b3a764000063ffffffff6122e516565b9063ffffffff61325716565b600080613264848461231f565b90508281028403801561327c575060010190506105c3565b5090506105c3565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106132c557805160ff19168380011785556132f2565b828001600101855582156132f2579182015b828111156132f25782518255916020019190600101906132d7565b506132fe929150613349565b5090565b6040518060e001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000600281111561334457fe5b905290565b610fd891905b808211156132fe576000815560010161334f565b80356001600160a01b03811681146105c357600080fd5b60008083601f84011261338b578182fd5b50813567ffffffffffffffff8111156133a2578182fd5b60208301915083602082850101111561251f57600080fd5b6000602082840312156133cb578081fd5b6121e48383613363565b600080604083850312156133e7578081fd5b6133f18484613363565b91506134008460208501613363565b90509250929050565b600080600080600080600080610100898b031215613425578384fd5b61342f8a8a613363565b975061343e8a60208b01613363565b965061344d8a60408b01613363565b9550606089013594506134638a60808b01613363565b935060a0890135925060c0890135915060e089013561348181613ee7565b809150509295985092959890939650565b6000806000606084860312156134a6578283fd5b83356134b181613ed2565b925060208401356134c181613ed2565b929592945050506040919091013590565b600080600080600080600060e0888a0312156134ec578283fd5b6134f68989613363565b96506135058960208a01613363565b95506040880135945060608801359350608088013561352381613ef5565b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215613552578182fd5b61355c8484613363565b946020939093013593505050565b60006020828403121561357b578081fd5b81516121e481613ee7565b600060208284031215613597578081fd5b5051919050565b600080600080600080600060c0888a0312156135b8578283fd5b8735965060208801356135ca81613ed2565b95506040880135945060608801359350608088013567ffffffffffffffff8111156135f3578384fd5b6135ff8a828b0161337a565b989b979a5095989497959660a090950135949350505050565b60008060008060006080868803121561362f578081fd5b85359450602086013593506136478760408801613363565b9250606086013567ffffffffffffffff811115613662578182fd5b61366e8882890161337a565b969995985093965092949392505050565b600060208284031215613690578081fd5b81516121e481613ef5565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600082516136d7818460208701613ea6565b9190910192915050565b6000808354600180821660008114613700576001811461371757613746565b60ff198316865260028304607f1686019350613746565b600283048786526020808720875b8381101561373e5781548a820152908501908201613725565b505050860193505b509195945050505050565b60008451613763818460208901613ea6565b8451908301613776828260208901613ea6565b8451918101613789838260208901613ea6565b9091019695505050505050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b600060018060a01b03871682528560208301528460408301526080606083015261381c60808301848661369b565b979650505050505050565b600060018060a01b038816825286602083015285604083015284606083015260a0608083015261385b60a08301848661369b565b98975050505050505050565b6001600160a01b0396871681529486166020860152604085019390935260608401919091528316608083015290911660a082015260c00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b93845260ff9290921660208401526040830152606082015260800190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b600060208252825180602084015261398c816040850160208701613ea6565b601f01601f19169190910160400192915050565b60208082526011908201527011931054d217d313d05397d19052531151607a1b604082015260600190565b60208082526016908201527509a929ca8be829a9eaa9ca8be9c9ea8be8a9c9eaa8e960531b604082015260600190565b60208082526014908201527308298989eae829c868abe9c9ea8be8a9c9eaa8e960631b604082015260600190565b6020808252600e908201526d5441524745545f49535f5a45524f60901b604082015260600190565b60208082526009908201526814915153951490539560ba1b604082015260600190565b60208082526015908201527414d1531317d09050d2d7d393d517d0531313d5d151605a1b604082015260600190565b6020808252601a908201527f424153455f51554f54455f43414e5f4e4f545f42455f53414d45000000000000604082015260600190565b6020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b6020808252600d908201526c1393d7d09054d157d253941555609a1b604082015260600190565b6020808252600e908201526d2224ab24a224a723afa2a92927a960911b604082015260600190565b6020808252600f908201526e11159357d253925512505312569151608a1b604082015260600190565b6020808252601c908201527f444f444f4d6174683a2073686f756c64206e6f74206265207a65726f00000000604082015260600190565b6020808252600c908201526b1352539517d253959053125160a21b604082015260600190565b60208082526009908201526829aaa12fa2a92927a960b91b604082015260600190565b6020808252601490820152731113d113d7d1159357d3140e881156141254915160621b604082015260600190565b6020808252601390820152720ae92a89088a482aebe9c9ea8be8a9c9eaa8e9606b1b604082015260600190565b6020808252600e908201526d08898a0be9c9ea8be8a9c9eaa8e960931b604082015260600190565b6020808252601290820152710848298829c868abe9c9ea8be8a9c9eaa8e960731b604082015260600190565b6020808252600890820152674f564552464c4f5760c01b604082015260600190565b60208082526009908201526820a2222fa2a92927a960b91b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601e908201527f444f444f5f44564d5f4c503a20494e56414c49445f5349474e41545552450000604082015260600190565b6020808252600c908201526b1512535157d156141254915160a21b604082015260600190565b60208082526009908201526826aaa62fa2a92927a960b91b604082015260600190565b600060e082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160038110613e1257fe5b8060c08401525092915050565b6001600160701b0391909116815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b968752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b60005b83811015613ec1578181015183820152602001613ea9565b838111156132275750506000910152565b6001600160a01b03811681146126ce57600080fd5b80151581146126ce57600080fd5b60ff811681146126ce57600080fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc2c0245e056d5fb095f04cd6373bc770802ebd1e6c918eb78fdef843cdb37b0fa26469706673582212208dc1e53cd0f7ddf502addf70542602e79231d0fe593256d661abf502be47314364736f6c63430006090033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102695760003560e01c80637d72150411610151578063d4b97046116100c3578063ee27c68911610087578063ee27c689146104e1578063f6b06e70146104e9578063f811d692146104f1578063fd1ed7e9146104f9578063fe24cb7f14610514578063fff6cae91461051c57610269565b8063d4b9704614610498578063d505accf146104a0578063dd62ed3e146104b3578063dd93f59a146104c6578063ec2fd46d146104d957610269565b8063a9059cbb11610115578063a9059cbb1461043c578063ab44a7a31461044f578063b56ceaa614610457578063bbf5ce781461046a578063bd6015b414610472578063d0a494e41461048557610269565b80637d721504146103e25780637ecebe00146103f7578063880a4d871461040a57806395d89b411461041f578063a382d1b91461042757610269565b80634322ec83116101ea57806354fd4d50116101ae57806354fd4d501461039157806365f6fcbb1461039957806366410a21146103a157806370a08231146103b457806371f9100c146103c757806379a04876146103cf57610269565b80634322ec831461032a578063440966091461033f5780634a248d2a146103525780634c85b4251461035a5780635039972a1461037c57610269565b80632df6cb48116102315780632df6cb48146102e757806330adf81f146102ef578063313ce567146102f757806336223ce91461030c5780633644e5151461032257610269565b806306fdde031461026e578063095ea7b31461028c57806317101940146102ac57806318160ddd146102bf57806323b872dd146102d4575b600080fd5b610276610524565b604051610283919061396d565b60405180910390f35b61029f61029a366004613540565b6105b2565b60405161028391906138db565b6102766102ba3660046133ba565b6105c9565b6102c76106f3565b60405161028391906138e6565b61029f6102e2366004613492565b6106f9565b61029f61087d565b6102c761088b565b6102ff6108af565b6040516102839190613e98565b6103146108b8565b604051610283929190613e33565b6102c76108d3565b6103326108d9565b60405161028391906137b1565b61031461034d3660046133ba565b6108ef565b61033261097a565b61036d6103683660046133ba565b610989565b60405161028393929190613e41565b61038f61038a366004613409565b610c79565b005b610276610fb7565b6102c7610fdb565b6103146103af366004613540565b611082565b6102c76103c23660046133ba565b611157565b6102c7611172565b6103146103dd366004613540565b6111be565b6103ea6111d2565b6040516102839190613e1f565b6102c76104053660046133ba565b6111e1565b6104126111f3565b6040516102839190613e87565b610276611206565b61042f611261565b6040516102839190613dc5565b61029f61044a366004613540565b6112b5565b6102c7611384565b61031461046536600461359e565b61138a565b6103ea6116ac565b6102c76104803660046133ba565b6116c2565b61038f610493366004613618565b6118ae565b610332611cdc565b61038f6104ae3660046134d2565b611ceb565b6102c76104c13660046133d5565b611e5a565b6102c76104d43660046133ba565b611e85565b6102c7612055565b6102c761205b565b61033261206d565b6102c761207c565b610501612082565b6040516102839796959493929190613e57565b6102c76120e5565b61038f6120eb565b6007805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105aa5780601f1061057f576101008083540402835291602001916105aa565b820191906000526020600020905b81548152906001019060200180831161058d57829003601f168201915b505050505081565b60006105bf33848461212f565b5060015b92915050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b6020820152815160088082528184019093526060926001600160a01b0385169291849160208201818036833701905050905060005b60048110156106e8578260048583600c016020811061063a57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061065a57fe5b602001015160f81c60f81b82826002028151811061067457fe5b60200101906001600160f81b031916908160001a905350828482600c016020811061069b57fe5b825191901a600f169081106106ac57fe5b602001015160f81c60f81b8282600202600101815181106106c957fe5b60200101906001600160f81b031916908160001a90535060010161061f565b50925050505b919050565b60085481565b6001600160a01b03831660009081526009602052604081205482111561073a5760405162461bcd60e51b815260040161073190613c8a565b60405180910390fd5b6001600160a01b0384166000908152600a6020908152604080832033845290915290205482111561077d5760405162461bcd60e51b8152600401610731906139fb565b6001600160a01b0384166000908152600960205260409020546107a6908363ffffffff61219716565b6001600160a01b0380861660009081526009602052604080822093909355908516815220546107db908363ffffffff6121bf16565b6001600160a01b038085166000908152600960209081526040808320949094559187168152600a8252828120338252909152205461081f908363ffffffff61219716565b6001600160a01b038086166000818152600a60209081526040808320338452909152908190209390935591519085169190600080516020613f058339815191529061086b9086906138e6565b60405180910390a35060019392505050565b600054610100900460ff1681565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b6003546001600160701b0380821692600160701b9092041690565b600b5481565b600054630100000090046001600160a01b031681565b600d54600e54604051638198edbf60e01b81526000916001600160a01b031690638198edbf906109239086906004016137b1565b60206040518083038186803b15801561093b57600080fd5b505afa15801561094f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109739190613586565b9050915091565b6001546001600160a01b031681565b600080548190819060ff16156109b15760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660019081178255546040516370a0823160e01b81526001600160a01b03909116906370a08231906109ee9030906004016137b1565b60206040518083038186803b158015610a0657600080fd5b505afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e9190613586565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190610a749030906004016137b1565b60206040518083038186803b158015610a8c57600080fd5b505afa158015610aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac49190613586565b6003549091506001600160701b0380821691600160701b900416610aee848363ffffffff61219716565b9550610b00838263ffffffff61219716565b945060008611610b225760405162461bcd60e51b815260040161073190613b0f565b600854610b66578396506107d18711610b4d5760405162461bcd60e51b8152600401610731906139cb565b610b5a60006103e96121eb565b6103e987039650610bfb565b600082118015610b74575080155b15610ba557610b9e82610b92600854896122e590919063ffffffff16565b9063ffffffff61231f16565b9650610bfb565b600082118015610bb55750600081115b15610bfb576000610bc68784612351565b90506000610bd48784612351565b90506000828210610be55782610be7565b815b9050610bf56008548261236f565b99505050505b610c0588886121eb565b610c0f8484612391565b6001600160a01b038816600090815260096020526040908190205490517f1c172440bdebb59cd92a7f08f4227903a3305ab6f880cb25f93eddb66843a10291610c5b918b918b916138ba565b60405180910390a150506000805460ff191690555092949193509150565b60005462010000900460ff1615610ca25760405162461bcd60e51b815260040161073190613b5e565b6000805462ff00001916620100001790556001600160a01b038781169087161415610cdf5760405162461bcd60e51b815260040161073190613aa3565b600180546001600160a01b03808a166001600160a01b03199283161790925560028054928916929091169190911790558215801590610d2d57506ec097ce7bc90715b34b9f10000000008311155b610d3657600080fd5b6010839055670de0b6b3a7640000821115610d5057600080fd5b600f829055600d859055600e80546001600160a01b038087166001600160a01b03199092169190911790915560008054831580156101000261ff0019948d166301000000026301000000600160b81b03199093169290921793909316179055610dd157600380546001600160e01b03164263ffffffff16600160e01b021790555b60408051808201825260018152605f60f81b602080830191909152825180840190935260038352620444c560ec1b90830152908082610e0f306105c9565b604051602001610e2193929190613751565b60405160208183030381529060405260079080519060200190610e45929190613284565b50604080518082019091526003808252620444c560ec1b6020909201918252610e7091600591613284565b50600160009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610ebf57600080fd5b505afa158015610ed3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef7919061367f565b6006805460ff191660ff9290921691909117905560405146907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90610f3e906007906136e1565b60408051918290038220828201825260018352603160f81b6020938401529051610f8f93927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6918691309101613941565b60408051601f198184030181529190528051602090910120600b555050505050505050505050565b60408051808201909152600981526844564d20312e302e3360b81b60208201525b90565b6003546001546040516370a0823160e01b815260009261107d926001600160701b03909116916001600160a01b03909116906370a08231906110219030906004016137b1565b60206040518083038186803b15801561103957600080fd5b505afa15801561104d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110719190613586565b9063ffffffff61219716565b905090565b600080611096611090611261565b84612420565b50600d54600e54604051638198edbf60e01b815292945090916000916001600160a01b031690638198edbf906110d09089906004016137b1565b60206040518083038186803b1580156110e857600080fd5b505afa1580156110fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111209190613586565b905061112c848261236f565b925061114c8361107161113f878661236f565b879063ffffffff61219716565b935050509250929050565b6001600160a01b031660009081526009602052604090205490565b6003546002546040516370a0823160e01b815260009261107d92600160701b9091046001600160701b0316916001600160a01b03909116906370a08231906110219030906004016137b1565b6000806110966111cc611261565b84612526565b6003546001600160701b031681565b600c6020526000908152604090205481565b600354600160e01b900463ffffffff1681565b6005805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105aa5780601f1061057f576101008083540402835291602001916105aa565b611269613302565b6010548152600f5460208201526003546001600160701b038082166040840152600160701b90910416606082015260006080820181905260a0820152600160c0820152610fd881612627565b336000908152600960205260408120548211156112e45760405162461bcd60e51b815260040161073190613c8a565b33600090815260096020526040902054611304908363ffffffff61219716565b33600090815260096020526040808220929092556001600160a01b03851681522054611336908363ffffffff6121bf16565b6001600160a01b038416600081815260096020526040908190209290925590513390600080516020613f05833981519152906113739086906138e6565b60405180910390a350600192915050565b600d5481565b60008054819060ff16156113b05760405162461bcd60e51b815260040161073190613a51565b6000805460ff19166001179055428310156113dd5760405162461bcd60e51b815260040161073190613d7c565b3360009081526009602052604090205489111561140c5760405162461bcd60e51b815260040161073190613c62565b6001600160a01b0388163014156114355760405162461bcd60e51b815260040161073190613a74565b6001546040516370a0823160e01b81526000916001600160a01b0316906370a08231906114669030906004016137b1565b60206040518083038186803b15801561147e57600080fd5b505afa158015611492573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b69190613586565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906114ec9030906004016137b1565b60206040518083038186803b15801561150457600080fd5b505afa158015611518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153c9190613586565b60085490915061155681610b92858f63ffffffff6122e516565b945061156c81610b92848f63ffffffff6122e516565b935089851015801561157e5750888410155b61159a5760405162461bcd60e51b815260040161073190613c35565b6115a4338d6126d1565b6115ae8b8661279e565b6115b88b856127c1565b6115c06127e4565b861561162f578a6001600160a01b0316632411d338338e88888d8d6040518763ffffffff1660e01b81526004016115fc96959493929190613827565b600060405180830381600087803b15801561161657600080fd5b505af115801561162a573d6000803e3d6000fd5b505050505b7f55caccde83781f39bfc1296eff45655b6496729443a7d48958b18b3b685600a5338c8e60096000336001600160a01b03166001600160a01b031681526020019081526020016000205460405161168994939291906137c5565b60405180910390a150506000805460ff1916905550909890975095505050505050565b600354600160701b90046001600160701b031681565b6000805460ff16156116e65760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660019081178255546040516370a0823160e01b81526001600160a01b03909116906370a08231906117239030906004016137b1565b60206040518083038186803b15801561173b57600080fd5b505afa15801561174f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117739190613586565b6003549091506000906117969083906001600160701b031663ffffffff61219716565b905060006117a432836111be565b90945090506117b385856127c1565b6000546117d090630100000090046001600160a01b0316826127c1565b6002546040516370a0823160e01b815261185b9185916001600160a01b03909116906370a08231906118069030906004016137b1565b60206040518083038186803b15801561181e57600080fd5b505afa158015611832573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118569190613586565b612391565b600154600254604051600080516020613f2583398151915292611894926001600160a01b03918216929116908690899033908c90613867565b60405180910390a150506000805460ff1916905550919050565b60005460ff16156118d15760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660011790556118e8838661279e565b6118f283856127c1565b801561195f5760405163eb2021c360e01b81526001600160a01b0384169063eb2021c39061192c90339089908990889088906004016137ee565b600060405180830381600087803b15801561194657600080fd5b505af115801561195a573d6000803e3d6000fd5b505050505b6001546040516370a0823160e01b81526000916001600160a01b0316906370a08231906119909030906004016137b1565b60206040518083038186803b1580156119a857600080fd5b505afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e09190613586565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190611a169030906004016137b1565b60206040518083038186803b158015611a2e57600080fd5b505afa158015611a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a669190613586565b6003549091506001600160701b031682101580611a955750600354600160701b90046001600160701b03168110155b611ab15760405162461bcd60e51b8152600401610731906139a0565b6003546001600160701b0316821015611b9757600354600090611ae5908390600160701b90046001600160701b0316612197565b9050600080611af43284611082565b60035491935091508290611b17906001600160701b03168763ffffffff61219716565b1115611b355760405162461bcd60e51b8152600401610731906139a0565b600054611b5290630100000090046001600160a01b03168261279e565b600254600154604051600080516020613f2583398151915292611b8b926001600160a01b03918216929116908790879033908f90613867565b60405180910390a15050505b600354600160701b90046001600160701b0316811015611c8457600354600090611bd19084906001600160701b031663ffffffff61219716565b9050600080611be032846111be565b60035491935091508290611c0490600160701b90046001600160701b031686612197565b1115611c225760405162461bcd60e51b8152600401610731906139a0565b600054611c3f90630100000090046001600160a01b0316826127c1565b600154600254604051600080516020613f2583398151915292611c78926001600160a01b03918216929116908790879033908f90613867565b60405180910390a15050505b611c8c6127e4565b7f0b82e93068db15abd9fbb2682c65462ea8a0a10582dce93a5664818e296f54eb33868989604051611cc194939291906137c5565b60405180910390a150506000805460ff191690555050505050565b6002546001600160a01b031681565b42841015611d0b5760405162461bcd60e51b815260040161073190613c07565b600b546001600160a01b0388166000908152600c602090815260408083208054600181019091559051929392611d6c927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d92918d91016138ef565b60405160208183030381529060405280519060200120604051602001611d93929190613796565b604051602081830303815290604052805190602001209050600060018286868660405160008152602001604052604051611dd09493929190613923565b6020604051602081039080840390855afa158015611df2573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611e285750886001600160a01b0316816001600160a01b0316145b611e445760405162461bcd60e51b815260040161073190613d45565b611e4f89898961212f565b505050505050505050565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b6000805460ff1615611ea95760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660011781556002546040516370a0823160e01b81526001600160a01b03909116906370a0823190611ee69030906004016137b1565b60206040518083038186803b158015611efe57600080fd5b505afa158015611f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f369190613586565b600354909150600090611f5a908390600160701b90046001600160701b0316612197565b90506000611f683283611082565b9094509050611f77858561279e565b600054611f9490630100000090046001600160a01b03168261279e565b6001546040516370a0823160e01b815261201c916001600160a01b0316906370a0823190611fc69030906004016137b1565b60206040518083038186803b158015611fde57600080fd5b505afa158015611ff2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120169190613586565b84612391565b600254600154604051600080516020613f2583398151915292611894926001600160a01b03918216929116908690899033908c90613867565b600f5481565b600061107d612068611261565b6129ab565b600e546001600160a01b031681565b60105481565b6000806000806000806000612095613302565b61209d611261565b905080600001519750806020015196508060400151955080606001519450806080015193508060a0015192508060c0015160028111156120d957fe5b91505090919293949596565b60045481565b60005460ff161561210e5760405162461bcd60e51b815260040161073190613a51565b6000805460ff191660011790556121236127e4565b6000805460ff19169055565b6001600160a01b038084166000818152600a602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061218a9085906138e6565b60405180910390a3505050565b6000828211156121b95760405162461bcd60e51b815260040161073190613be4565b50900390565b6000828201838110156121e45760405162461bcd60e51b815260040161073190613cd8565b9392505050565b6103e8811161220c5760405162461bcd60e51b815260040161073190613bbe565b6001600160a01b038216600090815260096020526040902054612235908263ffffffff6121bf16565b6001600160a01b038316600090815260096020526040902055600854612261908263ffffffff6121bf16565b6008556040516001600160a01b038316907f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968859061229f9084906138e6565b60405180910390a2816001600160a01b031660006001600160a01b0316600080516020613f05833981519152836040516122d991906138e6565b60405180910390a35050565b6000826122f4575060006105c3565b8282028284828161230157fe5b04146121e45760405162461bcd60e51b815260040161073190613da2565b60008082116123405760405162461bcd60e51b815260040161073190613b36565b81838161234957fe5b049392505050565b60006121e482610b9285670de0b6b3a764000063ffffffff6122e516565b6000670de0b6b3a764000061238a848463ffffffff6122e516565b8161234957fe5b6001600160701b0382118015906123af57506001600160701b038111155b6123cb5760405162461bcd60e51b815260040161073190613cb6565b600380546001600160701b03838116600160701b02600160701b600160e01b03199186166001600160701b0319909316929092171617905560005460ff610100909104161561241c5761241c612a9d565b5050565b600080808460c00151600281111561243457fe5b141561244f576124448484612b32565b91506001905061251f565b60018460c00151600281111561246157fe5b1415612471576124448484612b59565b600061248e85606001518660a0015161219790919063ffffffff16565b905060006124ad8660800151876040015161219790919063ffffffff16565b9050818510156124d8576124c18686612b76565b935060029250808411156124d3578093505b61251c565b818514156124ec578093506000925061251c565b61251561250887612503888663ffffffff61219716565b612b32565b829063ffffffff6121bf16565b9350600192505b50505b9250929050565b600080808460c00151600281111561253a57fe5b14156125555761254a8484612bb1565b91506002905061251f565b60018460c00151600281111561256757fe5b141561261257600061258a8560400151866080015161219790919063ffffffff16565b905060006125a98660a00151876060015161219790919063ffffffff16565b9050818510156125d4576125bd8686612bd0565b935060019250808411156125cf578093505b61260b565b818514156125e8578093506000925061260b565b612604612508876125ff888663ffffffff61219716565b612bb1565b9350600292505b505061251f565b61261c8484612c02565b946002945092505050565b60028160c00151600281111561263957fe5b14156126785761266e81606001516126628360800151846040015161219790919063ffffffff16565b83516020850151612c21565b60a08201526126ce565b60018160c00151600281111561268a57fe5b14156126ce576126c881604001516126b38360a00151846060015161219790919063ffffffff16565b83516126be90612d47565b8460200151612c21565b60808201525b50565b6001600160a01b0382166000908152600960205260409020546126fa908263ffffffff61219716565b6001600160a01b038316600090815260096020526040902055600854612726908263ffffffff61219716565b6008556040516001600160a01b038316907fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5906127649084906138e6565b60405180910390a260006001600160a01b0316826001600160a01b0316600080516020613f05833981519152836040516122d991906138e6565b801561241c5760015461241c906001600160a01b0316838363ffffffff612d6816565b801561241c5760025461241c906001600160a01b0316838363ffffffff612d6816565b6001546040516370a0823160e01b81526000916001600160a01b0316906370a08231906128159030906004016137b1565b60206040518083038186803b15801561282d57600080fd5b505afa158015612841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128659190613586565b6002546040516370a0823160e01b81529192506000916001600160a01b03909116906370a082319061289b9030906004016137b1565b60206040518083038186803b1580156128b357600080fd5b505afa1580156128c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128eb9190613586565b90506001600160701b03821180159061290b57506001600160701b038111155b6129275760405162461bcd60e51b815260040161073190613cb6565b6003546001600160701b0316821461295557600380546001600160701b0319166001600160701b0384161790555b600354600160701b90046001600160701b031681146129935760038054600160701b600160e01b031916600160701b6001600160701b038416021790555b600054610100900460ff161561241c5761241c612a9d565b600060028260c0015160028111156129bf57fe5b1415612a4a57606082015160a08301516000916129f5916129eb9190610b92908063ffffffff6122e516565b8460600151612351565b9050612a32612a0884602001518361236f565b6020850151612a2690670de0b6b3a76400009063ffffffff61219716565b9063ffffffff6121bf16565b9050612a42836000015182612351565b9150506106ee565b60408201516080830151600091612a7a91612a709190610b92908063ffffffff6122e516565b8460400151612351565b9050612a8d612a0884602001518361236f565b9050612a4283600001518261236f565b60035463ffffffff42811691600160e01b90048116820390811615801590612acf57506003546001600160701b031615155b8015612aec5750600354600160701b90046001600160701b031615155b15612b0c578063ffffffff16612b0061205b565b60048054919092020190555b506003805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b60006121e48360800151846080015184612b4f8760000151612d47565b8760200151612dc3565b60006121e48360800151846040015184612b4f8760000151612d47565b60006121e48360a00151612b978486606001516121bf90919063ffffffff16565b60608601518651612ba790612d47565b8760200151613060565b60006121e48360a001518460a001518486600001518760200151612dc3565b60006121e48360800151612bf18486604001516121bf90919063ffffffff16565b604086015186516020880151613060565b60006121e48360a0015184606001518486600001518760200151612dc3565b600081612c4957612c42612c35848661236f565b869063ffffffff6121bf16565b9050612d3f565b84612c5657506000612d3f565b600080612c6c600485028663ffffffff6122e516565b905080612c8357670de0b6b3a76400009150612d03565b858187830281612c8f57fe5b041415612cca57612cc3612cbe6ec097ce7bc90715b34b9f1000000000612a26848a028b63ffffffff61231f16565b613139565b9150612d03565b612d00612cbe6ec097ce7bc90715b34b9f1000000000612a2689612cf4868d63ffffffff61231f16565b9063ffffffff6122e516565b91505b6000612d2d670de0b6b3a7640000612a26612d24868363ffffffff61219716565b88600202612351565b9050612d39888261236f565b93505050505b949350505050565b60006105c36ec097ce7bc90715b34b9f10000000008363ffffffff61231f16565b612dbe8363a9059cbb60e01b8484604051602401612d879291906138a1565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613170565b505050565b6000808611612de45760405162461bcd60e51b815260040161073190613a29565b83612df157506000613057565b81612e1e5784612e01848661236f565b11612e1557612e10838561236f565b612e17565b845b9050613057565b670de0b6b3a7640000821415612ede57600080612e41858763ffffffff6122e516565b905080612e515760009150612eaa565b868188830281612e5d57fe5b041415612e8d57612e86612e77898063ffffffff6122e516565b8289029063ffffffff61231f16565b9150612eaa565b612ea788610b9287612cf483838c8e63ffffffff6122e516565b91505b612ed5612ec583670de0b6b3a764000063ffffffff6121bf16565b610b92898563ffffffff6122e516565b92505050613057565b6000612f0b612ef3858763ffffffff6122e516565b612a2689612cf48a610b92898463ffffffff6122e516565b90506000612f2b87612cf4670de0b6b3a76400008763ffffffff61219716565b90506000828210612f4157508190036000612f47565b50810360015b612f5f82670de0b6b3a764000063ffffffff61231f16565b91506000612f96612f836004612cf4670de0b6b3a76400008a63ffffffff61219716565b612f918c612cf48a8f61236f565b61236f565b9050612faf612cbe82612a26868063ffffffff6122e516565b90506000612fd06002612cf4670de0b6b3a76400008a63ffffffff61219716565b90506000831561300e57612fea838663ffffffff61219716565b9050806130095760405162461bcd60e51b815260040161073190613b87565b613021565b61301e858463ffffffff6121bf16565b90505b600061302d828461322d565b90508b811115613047576000975050505050505050613057565b8b03965061305795505050505050565b95945050505050565b60008086116130815760405162461bcd60e51b815260040161073190613a29565b60006130a3613096878763ffffffff61219716565b859063ffffffff6122e516565b9050826130ca576130c281670de0b6b3a764000063ffffffff61231f16565b915050613057565b60006130e96130e388610b928b8063ffffffff6122e516565b87612351565b905060006130f7858361236f565b905061312c6ec097ce7bc90715b34b9f1000000000610b9285612cf485612a26670de0b6b3a76400008c63ffffffff61219716565b9998505050505050505050565b80600160028204015b8181101561316a5780915060028182858161315957fe5b04018161316257fe5b049050613142565b50919050565b60006060836001600160a01b03168360405161318c91906136c5565b6000604051808303816000865af19150503d80600081146131c9576040519150601f19603f3d011682016040523d82523d6000602084013e6131ce565b606091505b5091509150816131f05760405162461bcd60e51b815260040161073190613ada565b805115613227578080602001905181019061320b919061356a565b6132275760405162461bcd60e51b815260040161073190613cfb565b50505050565b60006121e48261324b85670de0b6b3a764000063ffffffff6122e516565b9063ffffffff61325716565b600080613264848461231f565b90508281028403801561327c575060010190506105c3565b5090506105c3565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106132c557805160ff19168380011785556132f2565b828001600101855582156132f2579182015b828111156132f25782518255916020019190600101906132d7565b506132fe929150613349565b5090565b6040518060e001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000600281111561334457fe5b905290565b610fd891905b808211156132fe576000815560010161334f565b80356001600160a01b03811681146105c357600080fd5b60008083601f84011261338b578182fd5b50813567ffffffffffffffff8111156133a2578182fd5b60208301915083602082850101111561251f57600080fd5b6000602082840312156133cb578081fd5b6121e48383613363565b600080604083850312156133e7578081fd5b6133f18484613363565b91506134008460208501613363565b90509250929050565b600080600080600080600080610100898b031215613425578384fd5b61342f8a8a613363565b975061343e8a60208b01613363565b965061344d8a60408b01613363565b9550606089013594506134638a60808b01613363565b935060a0890135925060c0890135915060e089013561348181613ee7565b809150509295985092959890939650565b6000806000606084860312156134a6578283fd5b83356134b181613ed2565b925060208401356134c181613ed2565b929592945050506040919091013590565b600080600080600080600060e0888a0312156134ec578283fd5b6134f68989613363565b96506135058960208a01613363565b95506040880135945060608801359350608088013561352381613ef5565b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215613552578182fd5b61355c8484613363565b946020939093013593505050565b60006020828403121561357b578081fd5b81516121e481613ee7565b600060208284031215613597578081fd5b5051919050565b600080600080600080600060c0888a0312156135b8578283fd5b8735965060208801356135ca81613ed2565b95506040880135945060608801359350608088013567ffffffffffffffff8111156135f3578384fd5b6135ff8a828b0161337a565b989b979a5095989497959660a090950135949350505050565b60008060008060006080868803121561362f578081fd5b85359450602086013593506136478760408801613363565b9250606086013567ffffffffffffffff811115613662578182fd5b61366e8882890161337a565b969995985093965092949392505050565b600060208284031215613690578081fd5b81516121e481613ef5565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600082516136d7818460208701613ea6565b9190910192915050565b6000808354600180821660008114613700576001811461371757613746565b60ff198316865260028304607f1686019350613746565b600283048786526020808720875b8381101561373e5781548a820152908501908201613725565b505050860193505b509195945050505050565b60008451613763818460208901613ea6565b8451908301613776828260208901613ea6565b8451918101613789838260208901613ea6565b9091019695505050505050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b600060018060a01b03871682528560208301528460408301526080606083015261381c60808301848661369b565b979650505050505050565b600060018060a01b038816825286602083015285604083015284606083015260a0608083015261385b60a08301848661369b565b98975050505050505050565b6001600160a01b0396871681529486166020860152604085019390935260608401919091528316608083015290911660a082015260c00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b93845260ff9290921660208401526040830152606082015260800190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b600060208252825180602084015261398c816040850160208701613ea6565b601f01601f19169190910160400192915050565b60208082526011908201527011931054d217d313d05397d19052531151607a1b604082015260600190565b60208082526016908201527509a929ca8be829a9eaa9ca8be9c9ea8be8a9c9eaa8e960531b604082015260600190565b60208082526014908201527308298989eae829c868abe9c9ea8be8a9c9eaa8e960631b604082015260600190565b6020808252600e908201526d5441524745545f49535f5a45524f60901b604082015260600190565b60208082526009908201526814915153951490539560ba1b604082015260600190565b60208082526015908201527414d1531317d09050d2d7d393d517d0531313d5d151605a1b604082015260600190565b6020808252601a908201527f424153455f51554f54455f43414e5f4e4f545f42455f53414d45000000000000604082015260600190565b6020808252818101527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604082015260600190565b6020808252600d908201526c1393d7d09054d157d253941555609a1b604082015260600190565b6020808252600e908201526d2224ab24a224a723afa2a92927a960911b604082015260600190565b6020808252600f908201526e11159357d253925512505312569151608a1b604082015260600190565b6020808252601c908201527f444f444f4d6174683a2073686f756c64206e6f74206265207a65726f00000000604082015260600190565b6020808252600c908201526b1352539517d253959053125160a21b604082015260600190565b60208082526009908201526829aaa12fa2a92927a960b91b604082015260600190565b6020808252601490820152731113d113d7d1159357d3140e881156141254915160621b604082015260600190565b6020808252601390820152720ae92a89088a482aebe9c9ea8be8a9c9eaa8e9606b1b604082015260600190565b6020808252600e908201526d08898a0be9c9ea8be8a9c9eaa8e960931b604082015260600190565b6020808252601290820152710848298829c868abe9c9ea8be8a9c9eaa8e960731b604082015260600190565b6020808252600890820152674f564552464c4f5760c01b604082015260600190565b60208082526009908201526820a2222fa2a92927a960b91b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601e908201527f444f444f5f44564d5f4c503a20494e56414c49445f5349474e41545552450000604082015260600190565b6020808252600c908201526b1512535157d156141254915160a21b604082015260600190565b60208082526009908201526826aaa62fa2a92927a960b91b604082015260600190565b600060e082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160038110613e1257fe5b8060c08401525092915050565b6001600160701b0391909116815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b968752602087019590955260408601939093526060850191909152608084015260a083015260c082015260e00190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b60005b83811015613ec1578181015183820152602001613ea9565b838111156132275750506000910152565b6001600160a01b03811681146126ce57600080fd5b80151581146126ce57600080fd5b60ff811681146126ce57600080fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc2c0245e056d5fb095f04cd6373bc770802ebd1e6c918eb78fdef843cdb37b0fa26469706673582212208dc1e53cd0f7ddf502addf70542602e79231d0fe593256d661abf502be47314364736f6c63430006090033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.