My Name Tag:
Not Available, login to update
Txn Hash |
Method
|
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xbfcc2328d647da2d7cbff17cae85065b20720b5cf7e1f76a508911d02c517839 | Query Sell Quote... | 25536268 | 456 days 21 hrs ago | 0x6c9244d2f9febf230f7be9de2d185b330e431261 | IN | DODO: Pool Helper V1 | 0 MATIC | 0.002947328761 | |
0x914b1eb802ae49b95f34ae9f66187661aba0d3ae33bf7c6c463b8c3db57f2b49 | 0x60806040 | 14349170 | 753 days 9 hrs ago | 0x16cc37d06fe5061cd0023fb8d142abaabb396a2b | IN | Create: DODOSellHelper | 0 MATIC | 0.000727105 |
[ Download CSV Export ]
Contract Name:
DODOSellHelper
Compiler Version
v0.6.9+commit.3e3065ac
Contract Source Code (Solidity)
/** *Submitted for verification at polygonscan.com on 2021-06-30 */ // File: contracts/SmartRoute/intf/IDODOV1.sol /* Copyright 2020 DODO ZOO. SPDX-License-Identifier: Apache-2.0 */ pragma solidity 0.6.9; pragma experimental ABIEncoderV2; interface IDODOV1 { function init( address owner, address supervisor, address maintainer, address baseToken, address quoteToken, address oracle, uint256 lpFeeRate, uint256 mtFeeRate, uint256 k, uint256 gasPriceLimit ) external; function transferOwnership(address newOwner) external; function claimOwnership() external; function sellBaseToken( uint256 amount, uint256 minReceiveQuote, bytes calldata data ) external returns (uint256); function buyBaseToken( uint256 amount, uint256 maxPayQuote, bytes calldata data ) external returns (uint256); function querySellBaseToken(uint256 amount) external view returns (uint256 receiveQuote); function queryBuyBaseToken(uint256 amount) external view returns (uint256 payQuote); function depositBaseTo(address to, uint256 amount) external returns (uint256); function withdrawBase(uint256 amount) external returns (uint256); function withdrawAllBase() external returns (uint256); function depositQuoteTo(address to, uint256 amount) external returns (uint256); function withdrawQuote(uint256 amount) external returns (uint256); function withdrawAllQuote() external returns (uint256); function _BASE_CAPITAL_TOKEN_() external returns (address); function _QUOTE_CAPITAL_TOKEN_() external returns (address); function _BASE_TOKEN_() external view returns (address); function _QUOTE_TOKEN_() external view returns (address); function _R_STATUS_() external view returns (uint8); function _QUOTE_BALANCE_() external view returns (uint256); function _BASE_BALANCE_() external view returns (uint256); function _K_() external view returns (uint256); function _MT_FEE_RATE_() external view returns (uint256); function _LP_FEE_RATE_() external view returns (uint256); function getExpectedTarget() external view returns (uint256 baseTarget, uint256 quoteTarget); function getOraclePrice() external view returns (uint256); function getMidPrice() external view returns (uint256 midPrice); } // 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); } } // File: contracts/SmartRoute/helper/DODOSellHelper.sol // import {DODOMath} from "../lib/DODOMath.sol"; interface IDODOSellHelper { function querySellQuoteToken(address dodo, uint256 amount) external view returns (uint256); function querySellBaseToken(address dodo, uint256 amount) external view returns (uint256); } library DODOMath { using SafeMath for uint256; /* Integrate dodo curve fron 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)) */ function _GeneralIntegrate( uint256 V0, uint256 V1, uint256 V2, uint256 i, uint256 k ) internal pure returns (uint256) { uint256 fairAmount = DecimalMath.mulFloor(i, V1.sub(V2)); // i*delta uint256 V0V0V1V2 = DecimalMath.divCeil(V0.mul(V0).div(V1), V2); uint256 penalty = DecimalMath.mulFloor(k, V0V0V1V2); // k(V0^2/V1/V2) return DecimalMath.mulFloor(fairAmount, DecimalMath.ONE.sub(k).add(penalty)); } /* The same with 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 if deltaBSig=false, then Q2<Q1 */ function _SolveQuadraticFunctionForTrade( uint256 Q0, uint256 Q1, uint256 ideltaB, bool deltaBSig, uint256 k ) internal pure returns (uint256) { // calculate -b value and sig // -b = (1-k)Q1-kQ0^2/Q1+i*deltaB uint256 kQ02Q1 = DecimalMath.mulFloor(k, Q0).mul(Q0).div(Q1); // kQ0^2/Q1 uint256 b = DecimalMath.mulFloor(DecimalMath.ONE.sub(k), Q1); // (1-k)Q1 bool minusbSig = true; if (deltaBSig) { b = b.add(ideltaB); // (1-k)Q1+i*deltaB } else { kQ02Q1 = kQ02Q1.add(ideltaB); // i*deltaB+kQ0^2/Q1 } if (b >= kQ02Q1) { b = b.sub(kQ02Q1); minusbSig = true; } else { b = kQ02Q1.sub(b); minusbSig = false; } // calculate sqrt uint256 squareRoot = DecimalMath.mulFloor( DecimalMath.ONE.sub(k).mul(4), DecimalMath.mulFloor(k, Q0).mul(Q0) ); // 4(1-k)kQ0^2 squareRoot = b.mul(b).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 (minusbSig) { numerator = b.add(squareRoot); } else { numerator = squareRoot.sub(b); } if (deltaBSig) { return DecimalMath.divFloor(numerator, denominator); } else { return DecimalMath.divCeil(numerator, denominator); } } /* Start from the integration function i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2) Assume Q2=Q0, Given Q1 and deltaB, solve Q0 let fairAmount = i*deltaB */ function _SolveQuadraticFunctionForTarget( uint256 V1, uint256 k, uint256 fairAmount ) internal pure returns (uint256 V0) { // V0 = V1+V1*(sqrt-1)/2k uint256 sqrt = DecimalMath.divCeil(DecimalMath.mulFloor(k, fairAmount).mul(4), V1); sqrt = sqrt.add(DecimalMath.ONE).mul(DecimalMath.ONE).sqrt(); uint256 premium = DecimalMath.divCeil(sqrt.sub(DecimalMath.ONE), k.mul(2)); // V0 is greater than or equal to V1 according to the solution return DecimalMath.mulFloor(V1, DecimalMath.ONE.add(premium)); } } contract DODOSellHelper { using SafeMath for uint256; enum RStatus {ONE, ABOVE_ONE, BELOW_ONE} uint256 constant ONE = 10**18; struct DODOState { uint256 oraclePrice; uint256 K; uint256 B; uint256 Q; uint256 baseTarget; uint256 quoteTarget; RStatus rStatus; } function querySellBaseToken(address dodo, uint256 amount) public view returns (uint256) { return IDODOV1(dodo).querySellBaseToken(amount); } function querySellQuoteToken(address dodo, uint256 amount) public view returns (uint256) { DODOState memory state; (state.baseTarget, state.quoteTarget) = IDODOV1(dodo).getExpectedTarget(); state.rStatus = RStatus(IDODOV1(dodo)._R_STATUS_()); state.oraclePrice = IDODOV1(dodo).getOraclePrice(); state.Q = IDODOV1(dodo)._QUOTE_BALANCE_(); state.B = IDODOV1(dodo)._BASE_BALANCE_(); state.K = IDODOV1(dodo)._K_(); uint256 boughtAmount; // Determine the status (RStatus) and calculate the amount // based on the state if (state.rStatus == RStatus.ONE) { boughtAmount = _ROneSellQuoteToken(amount, state); } else if (state.rStatus == RStatus.ABOVE_ONE) { boughtAmount = _RAboveSellQuoteToken(amount, state); } else { uint256 backOneBase = state.B.sub(state.baseTarget); uint256 backOneQuote = state.quoteTarget.sub(state.Q); if (amount <= backOneQuote) { boughtAmount = _RBelowSellQuoteToken(amount, state); } else { boughtAmount = backOneBase.add( _ROneSellQuoteToken(amount.sub(backOneQuote), state) ); } } // Calculate fees return DecimalMath.divFloor( boughtAmount, DecimalMath.ONE.add(IDODOV1(dodo)._MT_FEE_RATE_()).add( IDODOV1(dodo)._LP_FEE_RATE_() ) ); } function _ROneSellQuoteToken(uint256 amount, DODOState memory state) internal pure returns (uint256 receiveBaseToken) { uint256 i = DecimalMath.divFloor(ONE, state.oraclePrice); uint256 B2 = DODOMath._SolveQuadraticFunctionForTrade( state.baseTarget, state.baseTarget, DecimalMath.mulFloor(i, amount), false, state.K ); return state.baseTarget.sub(B2); } function _RAboveSellQuoteToken(uint256 amount, DODOState memory state) internal pure returns (uint256 receieBaseToken) { uint256 i = DecimalMath.divFloor(ONE, state.oraclePrice); uint256 B2 = DODOMath._SolveQuadraticFunctionForTrade( state.baseTarget, state.B, DecimalMath.mulFloor(i, amount), false, state.K ); return state.B.sub(B2); } function _RBelowSellQuoteToken(uint256 amount, DODOState memory state) internal pure returns (uint256 receiveBaseToken) { uint256 Q1 = state.Q.add(amount); uint256 i = DecimalMath.divFloor(ONE, state.oraclePrice); return DODOMath._GeneralIntegrate(state.quoteTarget, Q1, state.Q, i, state.K); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"dodo","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"querySellBaseToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dodo","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"querySellQuoteToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50610c32806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063ca19ebd91461003b578063ef4a83f814610064575b600080fd5b61004e610049366004610ad0565b610077565b60405161005b9190610bf3565b60405180910390f35b61004e610072366004610ad0565b610574565b6000610081610a89565b836001600160a01b031663ffa642256040518163ffffffff1660e01b8152600401604080518083038186803b1580156100b957600080fd5b505afa1580156100cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f19190610b1e565b60a0830152608082015260408051630bdf4a9760e11b815290516001600160a01b038616916317be952e916004808301926020929190829003018186803b15801561013b57600080fd5b505afa15801561014f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101739190610b41565b60ff16600281111561018157fe5b8160c00190600281111561019157fe5b9081600281111561019e57fe5b81525050836001600160a01b031663796da7af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101db57600080fd5b505afa1580156101ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102139190610b06565b816000018181525050836001600160a01b0316637c9b8e896040518163ffffffff1660e01b815260040160206040518083038186803b15801561025557600080fd5b505afa158015610269573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028d9190610b06565b816060018181525050836001600160a01b031663eab5d20e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102cf57600080fd5b505afa1580156102e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103079190610b06565b816040018181525050836001600160a01b031663ec2fd46d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561034957600080fd5b505afa15801561035d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103819190610b06565b60208201526000808260c00151600281111561039957fe5b14156103b0576103a984836105fa565b9050610457565b60018260c0015160028111156103c257fe5b14156103d2576103a98483610652565b60006103ef8360800151846040015161069e90919063ffffffff16565b9050600061040e84606001518560a0015161069e90919063ffffffff16565b90508086116104285761042186856106cf565b9250610454565b61045161044461043e888463ffffffff61069e16565b866105fa565b839063ffffffff61071e16565b92505b50505b61056981610564876001600160a01b031663ab44a7a36040518163ffffffff1660e01b815260040160206040518083038186803b15801561049757600080fd5b505afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190610b06565b610558896001600160a01b031663c0ffa1786040518163ffffffff1660e01b815260040160206040518083038186803b15801561050b57600080fd5b505afa15801561051f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105439190610b06565b670de0b6b3a76400009063ffffffff61071e16565b9063ffffffff61071e16565b610743565b925050505b92915050565b6040516351400f0b60e11b81526000906001600160a01b0384169063a2801e16906105a3908590600401610bf3565b60206040518083038186803b1580156105bb57600080fd5b505afa1580156105cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f39190610b06565b9392505050565b600080610613670de0b6b3a76400008460000151610743565b9050600061063a8460800151856080015161062e858961076d565b60008860200151610797565b6080850151909150610569908263ffffffff61069e16565b60008061066b670de0b6b3a76400008460000151610743565b905060006106868460800151856040015161062e858961076d565b6040850151909150610569908263ffffffff61069e16565b6000828211156106c95760405162461bcd60e51b81526004016106c090610b8a565b60405180910390fd5b50900390565b6000806106e984846060015161071e90919063ffffffff16565b90506000610703670de0b6b3a76400008560000151610743565b90506105698460a00151838660600151848860200151610922565b6000828201838110156105f35760405162461bcd60e51b81526004016106c090610bad565b60006105f38261076185670de0b6b3a764000063ffffffff61099716565b9063ffffffff6109d116565b6000670de0b6b3a7640000610788848463ffffffff61099716565b8161078f57fe5b049392505050565b6000806107b886610761896107ac878c61076d565b9063ffffffff61099716565b905060006107dd6107d7670de0b6b3a76400008663ffffffff61069e16565b8861076d565b9050600185156107fe576107f7828863ffffffff61071e16565b9150610811565b61080e838863ffffffff61071e16565b92505b82821061083357610828828463ffffffff61069e16565b91506001905061084a565b610843838363ffffffff61069e16565b9150600090505b600061087f61086c60046107ac670de0b6b3a76400008a63ffffffff61069e16565b61087a8c6107ac8a8f61076d565b61076d565b905061089d61089882610558868063ffffffff61099716565b6109fb565b905060006108be60026107ac670de0b6b3a76400008a63ffffffff61069e16565b9050600083156108df576108d8858463ffffffff61071e16565b90506108f2565b6108ef838663ffffffff61069e16565b90505b881561090f576109028183610743565b9650505050505050610919565b6109028183610a32565b95945050505050565b6000806109398461087a888863ffffffff61069e16565b9050600061095a610954886107618b8063ffffffff61099716565b87610a32565b90506000610968858361076d565b905061098a8361087a83610558670de0b6b3a76400008a63ffffffff61069e16565b9998505050505050505050565b6000826109a65750600061056e565b828202828482816109b357fe5b04146105f35760405162461bcd60e51b81526004016106c090610bd0565b60008082116109f25760405162461bcd60e51b81526004016106c090610b62565b81838161078f57fe5b80600160028204015b81811015610a2c57809150600281828581610a1b57fe5b040181610a2457fe5b049050610a04565b50919050565b60006105f382610a5085670de0b6b3a764000063ffffffff61099716565b9063ffffffff610a5c16565b600080610a6984846109d1565b905082810284038015610a815750600101905061056e565b50905061056e565b6040518060e0016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160006002811115610acb57fe5b905290565b60008060408385031215610ae2578182fd5b82356001600160a01b0381168114610af8578283fd5b946020939093013593505050565b600060208284031215610b17578081fd5b5051919050565b60008060408385031215610b30578182fd5b505080516020909101519092909150565b600060208284031215610b52578081fd5b815160ff811681146105f3578182fd5b6020808252600e908201526d2224ab24a224a723afa2a92927a960911b604082015260600190565b60208082526009908201526829aaa12fa2a92927a960b91b604082015260600190565b60208082526009908201526820a2222fa2a92927a960b91b604082015260600190565b60208082526009908201526826aaa62fa2a92927a960b91b604082015260600190565b9081526020019056fea264697066735822122030b9f502b802c4d49f67c12383d1dd8f917b5f2f0f923a71032b59e00164e2b564736f6c63430006090033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.