More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 55 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Execute | 18618812 | 513 days ago | IN | 0 ETH | 0.00074837 | ||||
Execute | 18568847 | 520 days ago | IN | 0 ETH | 0.0162428 | ||||
Execute | 18518744 | 527 days ago | IN | 0 ETH | 0.02358757 | ||||
Execute | 18468781 | 534 days ago | IN | 0 ETH | 0.01421735 | ||||
Execute | 18418788 | 541 days ago | IN | 0 ETH | 0.01545062 | ||||
Execute | 18368773 | 548 days ago | IN | 0 ETH | 0.00715253 | ||||
Execute | 18318723 | 555 days ago | IN | 0 ETH | 0.0060932 | ||||
Execute | 18268961 | 562 days ago | IN | 0 ETH | 0.0062443 | ||||
Execute | 18224084 | 568 days ago | IN | 0 ETH | 0.01098163 | ||||
Execute | 18218622 | 569 days ago | IN | 0 ETH | 0.00489104 | ||||
Execute | 18168642 | 576 days ago | IN | 0 ETH | 0.01102651 | ||||
Execute | 18118921 | 583 days ago | IN | 0 ETH | 0.01065595 | ||||
Execute | 18068946 | 590 days ago | IN | 0 ETH | 0.01100739 | ||||
Execute | 18018962 | 597 days ago | IN | 0 ETH | 0.01970238 | ||||
Execute | 17968921 | 604 days ago | IN | 0 ETH | 0.02081481 | ||||
Execute | 17918911 | 611 days ago | IN | 0 ETH | 0.01642208 | ||||
Execute | 17868870 | 618 days ago | IN | 0 ETH | 0.02166139 | ||||
Execute | 17818830 | 625 days ago | IN | 0 ETH | 0.02255343 | ||||
Execute | 17768784 | 632 days ago | IN | 0 ETH | 0.02813074 | ||||
Execute | 17721035 | 639 days ago | IN | 0 ETH | 0.04662774 | ||||
Execute | 17669169 | 646 days ago | IN | 0 ETH | 0.01723885 | ||||
Execute | 17619260 | 653 days ago | IN | 0 ETH | 0.01941906 | ||||
Execute | 17569413 | 660 days ago | IN | 0 ETH | 0.01223195 | ||||
Execute | 17519607 | 667 days ago | IN | 0 ETH | 0.01351007 | ||||
Execute | 17469746 | 674 days ago | IN | 0 ETH | 0.01567307 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xc50944C3...9a3028Ef0 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
BuybackPool
Compiler Version
v0.8.2+commit.661d1103
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "../interfaces/IERC20.sol"; import "./interfaces/IBanana.sol"; import "./interfaces/IBananaDistributor.sol"; import "./interfaces/ITWAMM.sol"; import "./interfaces/ITWAMMPair.sol"; import "../utils/Ownable.sol"; import "../utils/AnalyticMath.sol"; import "../libraries/FullMath.sol"; import "../libraries/TransferHelper.sol"; contract BuybackPool is Ownable, AnalyticMath { using FullMath for uint256; event BuybackExecuted(uint256 orderId, uint256 amountIn, uint256 buyingRate, uint256 burned); event WithdrawAndBurn(uint256 orderId, uint256 burnAmount); address public immutable banana; address public immutable usdc; address public immutable twamm; address public immutable bananaDistributor; address public keeper; uint256 public lastBuyingRate; uint256 public priceT1; uint256 public priceT2; uint256 public rewardT1; uint256 public rewardT2; uint256 public priceIndex = 100; uint256 public rewardIndex = 50; uint256 public secondsPerBlock = 12; uint256 public secondsOfEpoch; uint256 public lastOrderId = type(uint256).max; uint256 public lastExecuteTime; uint256 public endTime; bool public initialized; bool public isStop; constructor( address banana_, address usdc_, address twamm_, address bananaDistributor_, address keeper_, uint256 secondsOfEpoch_, uint256 initPrice, uint256 initReward, uint256 startTime, uint256 endTime_ ) { owner = msg.sender; banana = banana_; usdc = usdc_; twamm = twamm_; bananaDistributor = bananaDistributor_; keeper = keeper_; secondsOfEpoch = secondsOfEpoch_; priceT2 = initPrice; rewardT2 = initReward; lastExecuteTime = startTime; endTime = endTime_; } // function initBuyingRate(uint256 amountIn) external onlyOwner { // require(!initialized, "already initialized"); // initialized = true; // lastBuyingRate = amountIn / secondsOfEpoch; // } function updatePriceIndex(uint256 newPriceIndex) external onlyOwner { priceIndex = newPriceIndex; } function updateRewardIndex(uint256 newRewardIndex) external onlyOwner { rewardIndex = newRewardIndex; } function updateSecondsPerBlock(uint256 newSecondsPerBlock) external onlyOwner { secondsPerBlock = newSecondsPerBlock; } function updateSecondsOfEpoch(uint256 newSecondsOfEpoch) external onlyOwner { secondsOfEpoch = newSecondsOfEpoch; } function updateLastExecuteTime(uint256 newExecuteTime) external onlyOwner { lastExecuteTime = newExecuteTime; } function updateEndTime(uint256 endTime_) external onlyOwner { endTime = endTime_; } function updateStatus(bool isStop_) external onlyOwner { isStop = isStop_; } function updateKeeper(address keeper_) external onlyOwner { keeper = keeper_; } function resetPrice(uint256 newPriceT1, uint256 newPriceT2) external onlyOwner { priceT1 = newPriceT1; priceT2 = newPriceT2; } function resetReward(uint256 newRewardT1, uint256 newRewardT2) external onlyOwner { rewardT1 = newRewardT1; rewardT2 = newRewardT2; } function withdrawUsdc(address to) external onlyOwner { require(isStop, "not stop"); uint256 usdcBalance = IERC20(usdc).balanceOf(address(this)); TransferHelper.safeTransfer(usdc, to, usdcBalance); } function withdrawAndBurn(uint256 orderId) external onlyOwner { require(isStop, "not stop"); address pair = ITWAMM(twamm).obtainPairAddress(usdc, banana); ITWAMMPair.Order memory order = ITWAMMPair(pair).getOrderDetails(orderId); require(block.number > order.expirationBlock, "not reach withdrawable block"); ITWAMM(twamm).withdrawProceedsFromTermSwapTokenToToken(usdc, banana, orderId, block.timestamp); uint256 bananaBalance = IERC20(banana).balanceOf(address(this)); require(bananaBalance > 0, "nothing to burn"); IBanana(banana).burn(bananaBalance); emit WithdrawAndBurn(orderId, bananaBalance); } function execute() external { require(!isStop, "is stop"); require(msg.sender == keeper, "only keeper"); require(block.timestamp < endTime, "end"); lastExecuteTime = lastExecuteTime + secondsOfEpoch; require(block.timestamp >= lastExecuteTime, "not reach execute time"); require(lastExecuteTime + secondsOfEpoch > block.timestamp, "over next epoch time"); uint256 burnAmount; if (lastOrderId != type(uint256).max) { address pair = ITWAMM(twamm).obtainPairAddress(usdc, banana); ITWAMMPair.Order memory order = ITWAMMPair(pair).getOrderDetails(lastOrderId); require(block.number > order.expirationBlock, "not reach withdrawable block"); ITWAMM(twamm).withdrawProceedsFromTermSwapTokenToToken(usdc, banana, lastOrderId, block.timestamp); burnAmount = IERC20(banana).balanceOf(address(this)); IBanana(banana).burn(burnAmount); } uint256 lastReward = IBananaDistributor(bananaDistributor).lastReward(); if (rewardT1 > 0) { rewardT2 = rewardT1; } rewardT1 = lastReward; (uint256 reserve0, uint256 reserve1) = ITWAMM(twamm).obtainReserves(usdc, banana); uint256 currentPrice = reserve0.mulDiv(1e30, reserve1); // reserve0/reserve1 * 10**(18+decimalsUSDC-decimalsBANA) if (priceT1 > 0) { priceT2 = priceT1; } priceT1 = currentPrice; uint256 deltaTime = lastExecuteTime + secondsOfEpoch - block.timestamp; uint256 usdcBalance = IERC20(usdc).balanceOf(address(this)); uint256 amountIn; if (!initialized) { amountIn = usdcBalance; lastBuyingRate = amountIn / deltaTime; initialized = true; } else { (uint256 pn, uint256 pd) = pow(priceT2, priceT1, priceIndex, 100); (uint256 rn, uint256 rd) = pow(rewardT1, rewardT2, rewardIndex, 100); lastBuyingRate = lastBuyingRate.mulDiv(pn, pd).mulDiv(rn, rd); amountIn = deltaTime * lastBuyingRate; if (amountIn > usdcBalance) { amountIn = usdcBalance; lastBuyingRate = amountIn / deltaTime; } } require(amountIn > 0, "buying amount is 0"); IERC20(usdc).approve(twamm, amountIn); lastOrderId = ITWAMM(twamm).longTermSwapTokenToToken( usdc, banana, amountIn, deltaTime / (secondsPerBlock * 5), block.timestamp ); emit BuybackExecuted(lastOrderId, amountIn, lastBuyingRate, burnAmount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20 { event Approval(address indexed owner, address indexed spender, uint256 value); event Transfer(address indexed from, address indexed to, uint256 value); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool); function transferFrom( address from, address to, uint256 value ) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external pure returns (uint8); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "../../interfaces/IERC20.sol"; interface IBanana is IERC20 { event RedeemTimeChanged(uint256 oldRedeemTime, uint256 newRedeemTime); event Redeem(address indexed user, uint256 burntAmount, uint256 apeXAmount); function apeXToken() external view returns (address); function redeemTime() external view returns (uint256); function mint(address to, uint256 apeXAmount) external returns (uint256); function burn(uint256 amount) external returns (bool); function burnFrom(address from, uint256 amount) external returns (bool); function redeem(uint256 amount) external returns (uint256); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; interface IBananaDistributor { function lastReward() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; interface ITWAMM { function factory() external view returns (address); function WETH() external view returns (address); function obtainReserves(address token0, address token1) external view returns (uint256 reserve0, uint256 reserve1); function obtainTotalSupply(address token0, address token1) external view returns (uint256); function obtainPairAddress(address token0, address token1) external view returns (address); function createPairWrapper( address token0, address token1, uint256 deadline ) external returns (address pair); function addInitialLiquidity( address token0, address token1, uint256 amount0, uint256 amount1, uint256 deadline ) external returns (uint256 lpTokenAmount); function addInitialLiquidityETH( address token, uint256 amountToken, uint256 amountETH, uint256 deadline ) external payable returns (uint256 lpTokenAmount); function addLiquidity( address token0, address token1, uint256 lpTokenAmount, uint256 amountIn0Max, uint256 amountIn1Max, uint256 deadline ) external returns (uint256 amountIn0, uint256 amountIn1); function addLiquidityETH( address token, uint256 lpTokenAmount, uint256 amountTokenInMax, uint256 amountETHInMax, uint256 deadline ) external payable returns (uint256 amountTokenIn, uint256 amountETHIn); function withdrawLiquidity( address token0, address token1, uint256 lpTokenAmount, uint256 amountOut0Min, uint256 amountOut1Min, uint256 deadline ) external returns (uint256 amountOut0, uint256 amountOut1); function withdrawLiquidityETH( address token, uint256 lpTokenAmount, uint256 amountTokenOutMin, uint256 amountETHOutMin, uint256 deadline ) external returns (uint256 amountTokenOut, uint256 amountETHOut); function instantSwapTokenToToken( address token0, address token1, uint256 amountIn, uint256 amountOutMin, uint256 deadline ) external returns (uint256 amountOut); function instantSwapTokenToETH( address token, uint256 amountTokenIn, uint256 amountETHOutMin, uint256 deadline ) external returns (uint256 amountETHOut); function instantSwapETHToToken( address token, uint256 amountETHIn, uint256 amountTokenOutMin, uint256 deadline ) external payable returns (uint256 amountTokenOut); function longTermSwapTokenToToken( address token0, address token1, uint256 amountIn, uint256 numberOfBlockIntervals, uint256 deadline ) external returns (uint256 orderId); function longTermSwapTokenToETH( address token, uint256 amountTokenIn, uint256 numberOfBlockIntervals, uint256 deadline ) external returns (uint256 orderId); function longTermSwapETHToToken( address token, uint256 amountETHIn, uint256 numberOfBlockIntervals, uint256 deadline ) external payable returns (uint256 orderId); function cancelTermSwapTokenToToken( address token0, address token1, uint256 orderId, uint256 deadline ) external returns (uint256 unsoldAmount, uint256 purchasedAmount); function cancelTermSwapTokenToETH( address token, uint256 orderId, uint256 deadline ) external returns (uint256 unsoldTokenAmount, uint256 purchasedETHAmount); function cancelTermSwapETHToToken( address token, uint256 orderId, uint256 deadline ) external returns (uint256 unsoldETHAmount, uint256 purchasedTokenAmount); function withdrawProceedsFromTermSwapTokenToToken( address token0, address token1, uint256 orderId, uint256 deadline ) external returns (uint256 proceeds); function withdrawProceedsFromTermSwapTokenToETH( address token, uint256 orderId, uint256 deadline ) external returns (uint256 proceedsETH); function withdrawProceedsFromTermSwapETHToToken( address token, uint256 orderId, uint256 deadline ) external returns (uint256 proceedsToken); function executeVirtualOrdersWrapper(address pair, uint256 blockNumber) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; interface ITWAMMPair { struct Order { uint256 id; uint256 expirationBlock; uint256 saleRate; address owner; address sellTokenId; address buyTokenId; } function getOrderDetails(uint256 orderId) external view returns (Order memory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; abstract contract Ownable { address public owner; address public pendingOwner; event NewOwner(address indexed oldOwner, address indexed newOwner); event NewPendingOwner(address indexed oldPendingOwner, address indexed newPendingOwner); modifier onlyOwner() { require(msg.sender == owner, "Ownable: REQUIRE_OWNER"); _; } function setPendingOwner(address newPendingOwner) external onlyOwner { require(pendingOwner != newPendingOwner, "Ownable: ALREADY_SET"); emit NewPendingOwner(pendingOwner, newPendingOwner); pendingOwner = newPendingOwner; } function acceptOwner() external { require(msg.sender == pendingOwner, "Ownable: REQUIRE_PENDING_OWNER"); address oldOwner = owner; address oldPendingOwner = pendingOwner; owner = pendingOwner; pendingOwner = address(0); emit NewOwner(oldOwner, owner); emit NewPendingOwner(oldPendingOwner, pendingOwner); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "../libraries/IntegralMath.sol"; contract AnalyticMath { uint8 internal constant MIN_PRECISION = 32; uint8 internal constant MAX_PRECISION = 127; uint256 internal constant FIXED_1 = 1 << MAX_PRECISION; uint256 internal constant FIXED_2 = 2 << MAX_PRECISION; // Auto-generated via 'PrintLn2ScalingFactors.py' uint256 internal constant LN2_NUMERATOR = 0x3f80fe03f80fe03f80fe03f80fe03f8; uint256 internal constant LN2_DENOMINATOR = 0x5b9de1d10bf4103d647b0955897ba80; // Auto-generated via 'PrintOptimalThresholds.py' uint256 internal constant OPT_LOG_MAX_VAL = 0x15bf0a8b1457695355fb8ac404e7a79e4; uint256 internal constant OPT_EXP_MAX_VAL = 0x800000000000000000000000000000000; uint256[MAX_PRECISION + 1] private maxExpArray; /** * @dev Should be executed either during construction or after construction (if too large for the constructor) */ constructor() { initMaxExpArray(); } /** * @dev Compute (a / b) ^ (c / d) */ function pow(uint256 a, uint256 b, uint256 c, uint256 d) internal view returns (uint256, uint256) { unchecked { if (a >= b) return mulDivExp(mulDivLog(FIXED_1, a, b), c, d); (uint256 q, uint256 p) = mulDivExp(mulDivLog(FIXED_1, b, a), c, d); return (p, q); }} /** * @dev Compute log(a / b) */ function log(uint256 a, uint256 b) internal pure returns (uint256, uint256) { unchecked { require(a >= b, "log: a < b"); return (mulDivLog(FIXED_1, a, b), FIXED_1); }} /** * @dev Compute e ^ (a / b) */ function exp(uint256 a, uint256 b) internal view returns (uint256, uint256) { unchecked { return mulDivExp(FIXED_1, a, b); }} /** * @dev Compute log(x / FIXED_1) * FIXED_1 */ function fixedLog(uint256 x) internal pure returns (uint256) { unchecked { if (x < OPT_LOG_MAX_VAL) { return optimalLog(x); } else { return generalLog(x); } }} /** * @dev Compute e ^ (x / FIXED_1) * FIXED_1 */ function fixedExp(uint256 x) internal view returns (uint256, uint256) { unchecked { if (x < OPT_EXP_MAX_VAL) { return (optimalExp(x), 1 << MAX_PRECISION); } else { uint8 precision = findPosition(x); return (generalExp(x >> (MAX_PRECISION - precision), precision), 1 << precision); } }} /** * @dev Compute log(x / FIXED_1) * FIXED_1 * This functions assumes that x >= FIXED_1, because the output would be negative otherwise */ function generalLog(uint256 x) internal pure returns (uint256) { unchecked { uint256 res = 0; // if x >= 2, then we compute the integer part of log2(x), which is larger than 0 if (x >= FIXED_2) { uint8 count = IntegralMath.floorLog2(x / FIXED_1); x >>= count; // now x < 2 res = count * FIXED_1; } // if x > 1, then we compute the fraction part of log2(x), which is larger than 0 if (x > FIXED_1) { for (uint8 i = MAX_PRECISION; i > 0; --i) { x = (x * x) / FIXED_1; // now 1 < x < 4 if (x >= FIXED_2) { x >>= 1; // now 1 < x < 2 res += 1 << (i - 1); } } } return res * LN2_NUMERATOR / LN2_DENOMINATOR; }} /** * @dev Approximate e ^ x as (x ^ 0) / 0! + (x ^ 1) / 1! + ... + (x ^ n) / n! * Auto-generated via 'PrintFunctionGeneralExp.py' * Detailed description: * - This function returns "e ^ (x / 2 ^ precision) * 2 ^ precision", that is, the result is upshifted for accuracy * - The global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX_PRECISION - precision)) - 1" * - The maximum permitted value for "x" is therefore given by "maxExpArray[precision] >> (MAX_PRECISION - precision)" */ function generalExp(uint256 x, uint8 precision) internal pure returns (uint256) { unchecked { uint256 xi = x; uint256 res = 0; xi = (xi * x) >> precision; res += xi * 0x3442c4e6074a82f1797f72ac0000000; // add x^02 * (33! / 02!) xi = (xi * x) >> precision; res += xi * 0x116b96f757c380fb287fd0e40000000; // add x^03 * (33! / 03!) xi = (xi * x) >> precision; res += xi * 0x045ae5bdd5f0e03eca1ff4390000000; // add x^04 * (33! / 04!) xi = (xi * x) >> precision; res += xi * 0x00defabf91302cd95b9ffda50000000; // add x^05 * (33! / 05!) xi = (xi * x) >> precision; res += xi * 0x002529ca9832b22439efff9b8000000; // add x^06 * (33! / 06!) xi = (xi * x) >> precision; res += xi * 0x00054f1cf12bd04e516b6da88000000; // add x^07 * (33! / 07!) xi = (xi * x) >> precision; res += xi * 0x0000a9e39e257a09ca2d6db51000000; // add x^08 * (33! / 08!) xi = (xi * x) >> precision; res += xi * 0x000012e066e7b839fa050c309000000; // add x^09 * (33! / 09!) xi = (xi * x) >> precision; res += xi * 0x000001e33d7d926c329a1ad1a800000; // add x^10 * (33! / 10!) xi = (xi * x) >> precision; res += xi * 0x0000002bee513bdb4a6b19b5f800000; // add x^11 * (33! / 11!) xi = (xi * x) >> precision; res += xi * 0x00000003a9316fa79b88eccf2a00000; // add x^12 * (33! / 12!) xi = (xi * x) >> precision; res += xi * 0x0000000048177ebe1fa812375200000; // add x^13 * (33! / 13!) xi = (xi * x) >> precision; res += xi * 0x0000000005263fe90242dcbacf00000; // add x^14 * (33! / 14!) xi = (xi * x) >> precision; res += xi * 0x000000000057e22099c030d94100000; // add x^15 * (33! / 15!) xi = (xi * x) >> precision; res += xi * 0x0000000000057e22099c030d9410000; // add x^16 * (33! / 16!) xi = (xi * x) >> precision; res += xi * 0x00000000000052b6b54569976310000; // add x^17 * (33! / 17!) xi = (xi * x) >> precision; res += xi * 0x00000000000004985f67696bf748000; // add x^18 * (33! / 18!) xi = (xi * x) >> precision; res += xi * 0x000000000000003dea12ea99e498000; // add x^19 * (33! / 19!) xi = (xi * x) >> precision; res += xi * 0x00000000000000031880f2214b6e000; // add x^20 * (33! / 20!) xi = (xi * x) >> precision; res += xi * 0x000000000000000025bcff56eb36000; // add x^21 * (33! / 21!) xi = (xi * x) >> precision; res += xi * 0x000000000000000001b722e10ab1000; // add x^22 * (33! / 22!) xi = (xi * x) >> precision; res += xi * 0x0000000000000000001317c70077000; // add x^23 * (33! / 23!) xi = (xi * x) >> precision; res += xi * 0x00000000000000000000cba84aafa00; // add x^24 * (33! / 24!) xi = (xi * x) >> precision; res += xi * 0x00000000000000000000082573a0a00; // add x^25 * (33! / 25!) xi = (xi * x) >> precision; res += xi * 0x00000000000000000000005035ad900; // add x^26 * (33! / 26!) xi = (xi * x) >> precision; res += xi * 0x000000000000000000000002f881b00; // add x^27 * (33! / 27!) xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000001b29340; // add x^28 * (33! / 28!) xi = (xi * x) >> precision; res += xi * 0x00000000000000000000000000efc40; // add x^29 * (33! / 29!) xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000000007fe0; // add x^30 * (33! / 30!) xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000000000420; // add x^31 * (33! / 31!) xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000000000021; // add x^32 * (33! / 32!) xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000000000001; // add x^33 * (33! / 33!) return res / 0x688589cc0e9505e2f2fee5580000000 + x + (1 << precision); // divide by 33! and then add x^1 / 1! + x^0 / 0! }} /** * @dev Compute log(x / FIXED_1) * FIXED_1 * Input range: FIXED_1 <= x <= OPT_LOG_MAX_VAL - 1 * Auto-generated via 'PrintFunctionOptimalLog.py' * Detailed description: * - Rewrite the input as a product of natural exponents and a single residual r, such that 1 < r < 2 * - The natural logarithm of each (pre-calculated) exponent is the degree of the exponent * - The natural logarithm of r is calculated via Taylor series for log(1 + x), where x = r - 1 * - The natural logarithm of the input is calculated by summing up the intermediate results above * - For example: log(250) = log(e^4 * e^1 * e^0.5 * 1.021692859) = 4 + 1 + 0.5 + log(1 + 0.021692859) */ function optimalLog(uint256 x) internal pure returns (uint256) { unchecked { uint256 res = 0; uint256 y; uint256 z; uint256 w; if (x >= 0xd3094c70f034de4b96ff7d5b6f99fcd9) {res += 0x40000000000000000000000000000000; x = x * FIXED_1 / 0xd3094c70f034de4b96ff7d5b6f99fcd9;} // add 1 / 2^1 if (x >= 0xa45af1e1f40c333b3de1db4dd55f29a8) {res += 0x20000000000000000000000000000000; x = x * FIXED_1 / 0xa45af1e1f40c333b3de1db4dd55f29a8;} // add 1 / 2^2 if (x >= 0x910b022db7ae67ce76b441c27035c6a2) {res += 0x10000000000000000000000000000000; x = x * FIXED_1 / 0x910b022db7ae67ce76b441c27035c6a2;} // add 1 / 2^3 if (x >= 0x88415abbe9a76bead8d00cf112e4d4a9) {res += 0x08000000000000000000000000000000; x = x * FIXED_1 / 0x88415abbe9a76bead8d00cf112e4d4a9;} // add 1 / 2^4 if (x >= 0x84102b00893f64c705e841d5d4064bd4) {res += 0x04000000000000000000000000000000; x = x * FIXED_1 / 0x84102b00893f64c705e841d5d4064bd4;} // add 1 / 2^5 if (x >= 0x8204055aaef1c8bd5c3259f4822735a3) {res += 0x02000000000000000000000000000000; x = x * FIXED_1 / 0x8204055aaef1c8bd5c3259f4822735a3;} // add 1 / 2^6 if (x >= 0x810100ab00222d861931c15e39b44e9a) {res += 0x01000000000000000000000000000000; x = x * FIXED_1 / 0x810100ab00222d861931c15e39b44e9a;} // add 1 / 2^7 if (x >= 0x808040155aabbbe9451521693554f734) {res += 0x00800000000000000000000000000000; x = x * FIXED_1 / 0x808040155aabbbe9451521693554f734;} // add 1 / 2^8 z = y = x - FIXED_1; w = y * y / FIXED_1; res += z * (0x100000000000000000000000000000000 - y) / 0x100000000000000000000000000000000; z = z * w / FIXED_1; // add y^01 / 01 - y^02 / 02 res += z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y) / 0x200000000000000000000000000000000; z = z * w / FIXED_1; // add y^03 / 03 - y^04 / 04 res += z * (0x099999999999999999999999999999999 - y) / 0x300000000000000000000000000000000; z = z * w / FIXED_1; // add y^05 / 05 - y^06 / 06 res += z * (0x092492492492492492492492492492492 - y) / 0x400000000000000000000000000000000; z = z * w / FIXED_1; // add y^07 / 07 - y^08 / 08 res += z * (0x08e38e38e38e38e38e38e38e38e38e38e - y) / 0x500000000000000000000000000000000; z = z * w / FIXED_1; // add y^09 / 09 - y^10 / 10 res += z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y) / 0x600000000000000000000000000000000; z = z * w / FIXED_1; // add y^11 / 11 - y^12 / 12 res += z * (0x089d89d89d89d89d89d89d89d89d89d89 - y) / 0x700000000000000000000000000000000; z = z * w / FIXED_1; // add y^13 / 13 - y^14 / 14 res += z * (0x088888888888888888888888888888888 - y) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16 return res; }} /** * @dev Compute e ^ (x / FIXED_1) * FIXED_1 * Input range: 0 <= x <= OPT_EXP_MAX_VAL - 1 * Auto-generated via 'PrintFunctionOptimalExp.py' * Detailed description: * - Rewrite the input as a sum of binary exponents and a single residual r, as small as possible * - The exponentiation of each binary exponent is given (pre-calculated) * - The exponentiation of r is calculated via Taylor series for e^x, where x = r * - The exponentiation of the input is calculated by multiplying the intermediate results above * - For example: e^5.521692859 = e^(4 + 1 + 0.5 + 0.021692859) = e^4 * e^1 * e^0.5 * e^0.021692859 */ function optimalExp(uint256 x) internal pure returns (uint256) { unchecked { uint256 res = 0; uint256 y; uint256 z; z = y = x % 0x10000000000000000000000000000000; // get the input modulo 2^(-3) z = z * y / FIXED_1; res += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!) z = z * y / FIXED_1; res += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!) z = z * y / FIXED_1; res += z * 0x0168244fdac78000; // add y^04 * (20! / 04!) z = z * y / FIXED_1; res += z * 0x004807432bc18000; // add y^05 * (20! / 05!) z = z * y / FIXED_1; res += z * 0x000c0135dca04000; // add y^06 * (20! / 06!) z = z * y / FIXED_1; res += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!) z = z * y / FIXED_1; res += z * 0x000036e0f639b800; // add y^08 * (20! / 08!) z = z * y / FIXED_1; res += z * 0x00000618fee9f800; // add y^09 * (20! / 09!) z = z * y / FIXED_1; res += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!) z = z * y / FIXED_1; res += z * 0x0000000e30dce400; // add y^11 * (20! / 11!) z = z * y / FIXED_1; res += z * 0x000000012ebd1300; // add y^12 * (20! / 12!) z = z * y / FIXED_1; res += z * 0x0000000017499f00; // add y^13 * (20! / 13!) z = z * y / FIXED_1; res += z * 0x0000000001a9d480; // add y^14 * (20! / 14!) z = z * y / FIXED_1; res += z * 0x00000000001c6380; // add y^15 * (20! / 15!) z = z * y / FIXED_1; res += z * 0x000000000001c638; // add y^16 * (20! / 16!) z = z * y / FIXED_1; res += z * 0x0000000000001ab8; // add y^17 * (20! / 17!) z = z * y / FIXED_1; res += z * 0x000000000000017c; // add y^18 * (20! / 18!) z = z * y / FIXED_1; res += z * 0x0000000000000014; // add y^19 * (20! / 19!) z = z * y / FIXED_1; res += z * 0x0000000000000001; // add y^20 * (20! / 20!) res = res / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0! if ((x & 0x010000000000000000000000000000000) != 0) res = res * 0x1c3d6a24ed82218787d624d3e5eba95f9 / 0x18ebef9eac820ae8682b9793ac6d1e776; // multiply by e^2^(-3) if ((x & 0x020000000000000000000000000000000) != 0) res = res * 0x18ebef9eac820ae8682b9793ac6d1e778 / 0x1368b2fc6f9609fe7aceb46aa619baed4; // multiply by e^2^(-2) if ((x & 0x040000000000000000000000000000000) != 0) res = res * 0x1368b2fc6f9609fe7aceb46aa619baed5 / 0x0bc5ab1b16779be3575bd8f0520a9f21f; // multiply by e^2^(-1) if ((x & 0x080000000000000000000000000000000) != 0) res = res * 0x0bc5ab1b16779be3575bd8f0520a9f21e / 0x0454aaa8efe072e7f6ddbab84b40a55c9; // multiply by e^2^(+0) if ((x & 0x100000000000000000000000000000000) != 0) res = res * 0x0454aaa8efe072e7f6ddbab84b40a55c5 / 0x00960aadc109e7a3bf4578099615711ea; // multiply by e^2^(+1) if ((x & 0x200000000000000000000000000000000) != 0) res = res * 0x00960aadc109e7a3bf4578099615711d7 / 0x0002bf84208204f5977f9a8cf01fdce3d; // multiply by e^2^(+2) if ((x & 0x400000000000000000000000000000000) != 0) res = res * 0x0002bf84208204f5977f9a8cf01fdc307 / 0x0000003c6ab775dd0b95b4cbee7e65d11; // multiply by e^2^(+3) return res; }} /** * @dev The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent: * - This function finds the position of [the smallest value in "maxExpArray" larger than or equal to "x"] * - This function finds the highest position of [a value in "maxExpArray" larger than or equal to "x"] * This function supports the rational approximation of "(a / b) ^ (c / d)" via "e ^ (log(a / b) * c / d)". * The value of "log(a / b)" is represented with an integer slightly smaller than "log(a / b) * 2 ^ precision". * The larger "precision" is, the more accurately this value represents the real value. * However, the larger "precision" is, the more bits are required in order to store this value. * And the exponentiation function, which takes "x" and calculates "e ^ x", is limited to a maximum exponent (a maximum value of "x"). * This maximum exponent depends on the "precision" used, and it is given by "maxExpArray[precision] >> (MAX_PRECISION - precision)". * Hence we need to determine the highest precision which can be used for the given input, before calling the exponentiation function. * This allows us to compute the result with maximum accuracy and without exceeding 256 bits in any of the intermediate computations. */ function findPosition(uint256 x) internal view returns (uint8) { unchecked { uint8 lo = MIN_PRECISION; uint8 hi = MAX_PRECISION; while (lo + 1 < hi) { uint8 mid = (lo + hi) / 2; if (maxExpArray[mid] >= x) lo = mid; else hi = mid; } if (maxExpArray[hi] >= x) return hi; if (maxExpArray[lo] >= x) return lo; revert("findPosition: x > max"); }} /** * @dev Initialize internal data structure * Auto-generated via 'PrintMaxExpArray.py' */ function initMaxExpArray() internal { // maxExpArray[ 0] = 0x6bffffffffffffffffffffffffffffffff; // maxExpArray[ 1] = 0x67ffffffffffffffffffffffffffffffff; // maxExpArray[ 2] = 0x637fffffffffffffffffffffffffffffff; // maxExpArray[ 3] = 0x5f6fffffffffffffffffffffffffffffff; // maxExpArray[ 4] = 0x5b77ffffffffffffffffffffffffffffff; // maxExpArray[ 5] = 0x57b3ffffffffffffffffffffffffffffff; // maxExpArray[ 6] = 0x5419ffffffffffffffffffffffffffffff; // maxExpArray[ 7] = 0x50a2ffffffffffffffffffffffffffffff; // maxExpArray[ 8] = 0x4d517fffffffffffffffffffffffffffff; // maxExpArray[ 9] = 0x4a233fffffffffffffffffffffffffffff; // maxExpArray[ 10] = 0x47165fffffffffffffffffffffffffffff; // maxExpArray[ 11] = 0x4429afffffffffffffffffffffffffffff; // maxExpArray[ 12] = 0x415bc7ffffffffffffffffffffffffffff; // maxExpArray[ 13] = 0x3eab73ffffffffffffffffffffffffffff; // maxExpArray[ 14] = 0x3c1771ffffffffffffffffffffffffffff; // maxExpArray[ 15] = 0x399e96ffffffffffffffffffffffffffff; // maxExpArray[ 16] = 0x373fc47fffffffffffffffffffffffffff; // maxExpArray[ 17] = 0x34f9e8ffffffffffffffffffffffffffff; // maxExpArray[ 18] = 0x32cbfd5fffffffffffffffffffffffffff; // maxExpArray[ 19] = 0x30b5057fffffffffffffffffffffffffff; // maxExpArray[ 20] = 0x2eb40f9fffffffffffffffffffffffffff; // maxExpArray[ 21] = 0x2cc8340fffffffffffffffffffffffffff; // maxExpArray[ 22] = 0x2af09481ffffffffffffffffffffffffff; // maxExpArray[ 23] = 0x292c5bddffffffffffffffffffffffffff; // maxExpArray[ 24] = 0x277abdcdffffffffffffffffffffffffff; // maxExpArray[ 25] = 0x25daf6657fffffffffffffffffffffffff; // maxExpArray[ 26] = 0x244c49c65fffffffffffffffffffffffff; // maxExpArray[ 27] = 0x22ce03cd5fffffffffffffffffffffffff; // maxExpArray[ 28] = 0x215f77c047ffffffffffffffffffffffff; // maxExpArray[ 29] = 0x1fffffffffffffffffffffffffffffffff; // maxExpArray[ 30] = 0x1eaefdbdabffffffffffffffffffffffff; // maxExpArray[ 31] = 0x1d6bd8b2ebffffffffffffffffffffffff; maxExpArray[ 32] = 0x1c35fedd14ffffffffffffffffffffffff; maxExpArray[ 33] = 0x1b0ce43b323fffffffffffffffffffffff; maxExpArray[ 34] = 0x19f0028ec1ffffffffffffffffffffffff; maxExpArray[ 35] = 0x18ded91f0e7fffffffffffffffffffffff; maxExpArray[ 36] = 0x17d8ec7f0417ffffffffffffffffffffff; maxExpArray[ 37] = 0x16ddc6556cdbffffffffffffffffffffff; maxExpArray[ 38] = 0x15ecf52776a1ffffffffffffffffffffff; maxExpArray[ 39] = 0x15060c256cb2ffffffffffffffffffffff; maxExpArray[ 40] = 0x1428a2f98d72ffffffffffffffffffffff; maxExpArray[ 41] = 0x13545598e5c23fffffffffffffffffffff; maxExpArray[ 42] = 0x1288c4161ce1dfffffffffffffffffffff; maxExpArray[ 43] = 0x11c592761c666fffffffffffffffffffff; maxExpArray[ 44] = 0x110a688680a757ffffffffffffffffffff; maxExpArray[ 45] = 0x1056f1b5bedf77ffffffffffffffffffff; maxExpArray[ 46] = 0x0faadceceeff8bffffffffffffffffffff; maxExpArray[ 47] = 0x0f05dc6b27edadffffffffffffffffffff; maxExpArray[ 48] = 0x0e67a5a25da4107fffffffffffffffffff; maxExpArray[ 49] = 0x0dcff115b14eedffffffffffffffffffff; maxExpArray[ 50] = 0x0d3e7a392431239fffffffffffffffffff; maxExpArray[ 51] = 0x0cb2ff529eb71e4fffffffffffffffffff; maxExpArray[ 52] = 0x0c2d415c3db974afffffffffffffffffff; maxExpArray[ 53] = 0x0bad03e7d883f69bffffffffffffffffff; maxExpArray[ 54] = 0x0b320d03b2c343d5ffffffffffffffffff; maxExpArray[ 55] = 0x0abc25204e02828dffffffffffffffffff; maxExpArray[ 56] = 0x0a4b16f74ee4bb207fffffffffffffffff; maxExpArray[ 57] = 0x09deaf736ac1f569ffffffffffffffffff; maxExpArray[ 58] = 0x0976bd9952c7aa957fffffffffffffffff; maxExpArray[ 59] = 0x09131271922eaa606fffffffffffffffff; maxExpArray[ 60] = 0x08b380f3558668c46fffffffffffffffff; maxExpArray[ 61] = 0x0857ddf0117efa215bffffffffffffffff; maxExpArray[ 62] = 0x07ffffffffffffffffffffffffffffffff; maxExpArray[ 63] = 0x07abbf6f6abb9d087fffffffffffffffff; maxExpArray[ 64] = 0x075af62cbac95f7dfa7fffffffffffffff; maxExpArray[ 65] = 0x070d7fb7452e187ac13fffffffffffffff; maxExpArray[ 66] = 0x06c3390ecc8af379295fffffffffffffff; maxExpArray[ 67] = 0x067c00a3b07ffc01fd6fffffffffffffff; maxExpArray[ 68] = 0x0637b647c39cbb9d3d27ffffffffffffff; maxExpArray[ 69] = 0x05f63b1fc104dbd39587ffffffffffffff; maxExpArray[ 70] = 0x05b771955b36e12f7235ffffffffffffff; maxExpArray[ 71] = 0x057b3d49dda84556d6f6ffffffffffffff; maxExpArray[ 72] = 0x054183095b2c8ececf30ffffffffffffff; maxExpArray[ 73] = 0x050a28be635ca2b888f77fffffffffffff; maxExpArray[ 74] = 0x04d5156639708c9db33c3fffffffffffff; maxExpArray[ 75] = 0x04a23105873875bd52dfdfffffffffffff; maxExpArray[ 76] = 0x0471649d87199aa990756fffffffffffff; maxExpArray[ 77] = 0x04429a21a029d4c1457cfbffffffffffff; maxExpArray[ 78] = 0x0415bc6d6fb7dd71af2cb3ffffffffffff; maxExpArray[ 79] = 0x03eab73b3bbfe282243ce1ffffffffffff; maxExpArray[ 80] = 0x03c1771ac9fb6b4c18e229ffffffffffff; maxExpArray[ 81] = 0x0399e96897690418f785257fffffffffff; maxExpArray[ 82] = 0x0373fc456c53bb779bf0ea9fffffffffff; maxExpArray[ 83] = 0x034f9e8e490c48e67e6ab8bfffffffffff; maxExpArray[ 84] = 0x032cbfd4a7adc790560b3337ffffffffff; maxExpArray[ 85] = 0x030b50570f6e5d2acca94613ffffffffff; maxExpArray[ 86] = 0x02eb40f9f620fda6b56c2861ffffffffff; maxExpArray[ 87] = 0x02cc8340ecb0d0f520a6af58ffffffffff; maxExpArray[ 88] = 0x02af09481380a0a35cf1ba02ffffffffff; maxExpArray[ 89] = 0x0292c5bdd3b92ec810287b1b3fffffffff; maxExpArray[ 90] = 0x0277abdcdab07d5a77ac6d6b9fffffffff; maxExpArray[ 91] = 0x025daf6654b1eaa55fd64df5efffffffff; maxExpArray[ 92] = 0x0244c49c648baa98192dce88b7ffffffff; maxExpArray[ 93] = 0x022ce03cd5619a311b2471268bffffffff; maxExpArray[ 94] = 0x0215f77c045fbe885654a44a0fffffffff; maxExpArray[ 95] = 0x01ffffffffffffffffffffffffffffffff; maxExpArray[ 96] = 0x01eaefdbdaaee7421fc4d3ede5ffffffff; maxExpArray[ 97] = 0x01d6bd8b2eb257df7e8ca57b09bfffffff; maxExpArray[ 98] = 0x01c35fedd14b861eb0443f7f133fffffff; maxExpArray[ 99] = 0x01b0ce43b322bcde4a56e8ada5afffffff; maxExpArray[100] = 0x019f0028ec1fff007f5a195a39dfffffff; maxExpArray[101] = 0x018ded91f0e72ee74f49b15ba527ffffff; maxExpArray[102] = 0x017d8ec7f04136f4e5615fd41a63ffffff; maxExpArray[103] = 0x016ddc6556cdb84bdc8d12d22e6fffffff; maxExpArray[104] = 0x015ecf52776a1155b5bd8395814f7fffff; maxExpArray[105] = 0x015060c256cb23b3b3cc3754cf40ffffff; maxExpArray[106] = 0x01428a2f98d728ae223ddab715be3fffff; maxExpArray[107] = 0x013545598e5c23276ccf0ede68034fffff; maxExpArray[108] = 0x01288c4161ce1d6f54b7f61081194fffff; maxExpArray[109] = 0x011c592761c666aa641d5a01a40f17ffff; maxExpArray[110] = 0x0110a688680a7530515f3e6e6cfdcdffff; maxExpArray[111] = 0x01056f1b5bedf75c6bcb2ce8aed428ffff; maxExpArray[112] = 0x00faadceceeff8a0890f3875f008277fff; maxExpArray[113] = 0x00f05dc6b27edad306388a600f6ba0bfff; maxExpArray[114] = 0x00e67a5a25da41063de1495d5b18cdbfff; maxExpArray[115] = 0x00dcff115b14eedde6fc3aa5353f2e4fff; maxExpArray[116] = 0x00d3e7a3924312399f9aae2e0f868f8fff; maxExpArray[117] = 0x00cb2ff529eb71e41582cccd5a1ee26fff; maxExpArray[118] = 0x00c2d415c3db974ab32a51840c0b67edff; maxExpArray[119] = 0x00bad03e7d883f69ad5b0a186184e06bff; maxExpArray[120] = 0x00b320d03b2c343d4829abd6075f0cc5ff; maxExpArray[121] = 0x00abc25204e02828d73c6e80bcdb1a95bf; maxExpArray[122] = 0x00a4b16f74ee4bb2040a1ec6c15fbbf2df; maxExpArray[123] = 0x009deaf736ac1f569deb1b5ae3f36c130f; maxExpArray[124] = 0x00976bd9952c7aa957f5937d790ef65037; maxExpArray[125] = 0x009131271922eaa6064b73a22d0bd4f2bf; maxExpArray[126] = 0x008b380f3558668c46c91c49a2f8e967b9; maxExpArray[127] = 0x00857ddf0117efa215952912839f6473e6; } // auxiliary function function mulDivLog(uint256 x, uint256 y, uint256 z) private pure returns (uint256) { return fixedLog(IntegralMath.mulDivF(x, y, z)); } // auxiliary function function mulDivExp(uint256 x, uint256 y, uint256 z) private view returns (uint256, uint256) { return fixedExp(IntegralMath.mulDivF(x, y, z)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product // todo unchecked unchecked { assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = (~denominator + 1) & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeApprove: approve failed" ); } function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeTransfer: transfer failed" ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::transferFrom: transferFrom failed" ); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, "TransferHelper::safeTransferETH: ETH transfer failed"); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; library IntegralMath { uint256 constant MAX_VAL = type(uint256).max; // reverts on overflow function safeAdd(uint256 x, uint256 y) internal pure returns (uint256) { return x + y; } // does not revert on overflow function unsafeAdd(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { return x + y; }} // does not revert on overflow function unsafeSub(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { return x - y; }} // does not revert on overflow function unsafeMul(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { return x * y; }} // does not overflow function mulModMax(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { return mulmod(x, y, MAX_VAL); }} // does not overflow function mulMod(uint256 x, uint256 y, uint256 z) internal pure returns (uint256) { unchecked { return mulmod(x, y, z); }} /** * @dev Compute the largest integer smaller than or equal to the binary logarithm of `n` */ function floorLog2(uint256 n) internal pure returns (uint8) { unchecked { uint8 res = 0; if (n < 256) { // at most 8 iterations while (n > 1) { n >>= 1; res += 1; } } else { // exactly 8 iterations for (uint8 s = 128; s > 0; s >>= 1) { if (n >= 1 << s) { n >>= s; res |= s; } } } return res; }} /** * @dev Compute the largest integer smaller than or equal to the square root of `n` */ function floorSqrt(uint256 n) internal pure returns (uint256) { unchecked { if (n > 0) { uint256 x = n / 2 + 1; uint256 y = (x + n / x) / 2; while (x > y) { x = y; y = (x + n / x) / 2; } return x; } return 0; }} /** * @dev Compute the smallest integer larger than or equal to the square root of `n` */ function ceilSqrt(uint256 n) internal pure returns (uint256) { unchecked { uint256 x = floorSqrt(n); return x ** 2 == n ? x : x + 1; }} /** * @dev Compute the largest integer smaller than or equal to the cubic root of `n` */ function floorCbrt(uint256 n) internal pure returns (uint256) { unchecked { uint256 x = 0; for (uint256 y = 1 << 255; y > 0; y >>= 3) { x <<= 1; uint256 z = 3 * x * (x + 1) + 1; if (n / y >= z) { n -= y * z; x += 1; } } return x; }} /** * @dev Compute the smallest integer larger than or equal to the cubic root of `n` */ function ceilCbrt(uint256 n) internal pure returns (uint256) { unchecked { uint256 x = floorCbrt(n); return x ** 3 == n ? x : x + 1; }} /** * @dev Compute the nearest integer to the quotient of `n` and `d` (or `n / d`) */ function roundDiv(uint256 n, uint256 d) internal pure returns (uint256) { unchecked { return n / d + (n % d) / (d - d / 2); }} /** * @dev Compute the largest integer smaller than or equal to `x * y / z` */ function mulDivF(uint256 x, uint256 y, uint256 z) internal pure returns (uint256) { unchecked { (uint256 xyh, uint256 xyl) = mul512(x, y); if (xyh == 0) { // `x * y < 2 ^ 256` return xyl / z; } if (xyh < z) { // `x * y / z < 2 ^ 256` uint256 m = mulMod(x, y, z); // `m = x * y % z` (uint256 nh, uint256 nl) = sub512(xyh, xyl, m); // `n = x * y - m` hence `n / z = floor(x * y / z)` if (nh == 0) { // `n < 2 ^ 256` return nl / z; } uint256 p = unsafeSub(0, z) & z; // `p` is the largest power of 2 which `z` is divisible by uint256 q = div512(nh, nl, p); // `n` is divisible by `p` because `n` is divisible by `z` and `z` is divisible by `p` uint256 r = inv256(z / p); // `z / p = 1 mod 2` hence `inverse(z / p) = 1 mod 2 ^ 256` return unsafeMul(q, r); // `q * r = (n / p) * inverse(z / p) = n / z` } revert(); // `x * y / z >= 2 ^ 256` }} /** * @dev Compute the smallest integer larger than or equal to `x * y / z` */ function mulDivC(uint256 x, uint256 y, uint256 z) internal pure returns (uint256) { unchecked { uint256 w = mulDivF(x, y, z); if (mulMod(x, y, z) > 0) return safeAdd(w, 1); return w; }} /** * @dev Compute the value of `x * y` */ function mul512(uint256 x, uint256 y) private pure returns (uint256, uint256) { unchecked { uint256 p = mulModMax(x, y); uint256 q = unsafeMul(x, y); if (p >= q) return (p - q, q); return (unsafeSub(p, q) - 1, q); }} /** * @dev Compute the value of `2 ^ 256 * xh + xl - y`, where `2 ^ 256 * xh + xl >= y` */ function sub512(uint256 xh, uint256 xl, uint256 y) private pure returns (uint256, uint256) { unchecked { if (xl >= y) return (xh, xl - y); return (xh - 1, unsafeSub(xl, y)); }} /** * @dev Compute the value of `(2 ^ 256 * xh + xl) / pow2n`, where `xl` is divisible by `pow2n` */ function div512(uint256 xh, uint256 xl, uint256 pow2n) private pure returns (uint256) { unchecked { uint256 pow2nInv = unsafeAdd(unsafeSub(0, pow2n) / pow2n, 1); // `1 << (256 - n)` return unsafeMul(xh, pow2nInv) | (xl / pow2n); // `(xh << (256 - n)) | (xl >> n)` }} /** * @dev Compute the inverse of `d` modulo `2 ^ 256`, where `d` is congruent to `1` modulo `2` */ function inv256(uint256 d) private pure returns (uint256) { unchecked { // approximate the root of `f(x) = 1 / x - d` using the newton–raphson convergence method uint256 x = 1; for (uint256 i = 0; i < 8; ++i) x = unsafeMul(x, unsafeSub(2, unsafeMul(x, d))); // `x = x * (2 - x * d) mod 2 ^ 256` return x; }} }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"banana_","type":"address"},{"internalType":"address","name":"usdc_","type":"address"},{"internalType":"address","name":"twamm_","type":"address"},{"internalType":"address","name":"bananaDistributor_","type":"address"},{"internalType":"address","name":"keeper_","type":"address"},{"internalType":"uint256","name":"secondsOfEpoch_","type":"uint256"},{"internalType":"uint256","name":"initPrice","type":"uint256"},{"internalType":"uint256","name":"initReward","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"buyingRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burned","type":"uint256"}],"name":"BuybackExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPendingOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"WithdrawAndBurn","type":"event"},{"inputs":[],"name":"acceptOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"banana","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bananaDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isStop","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBuyingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastExecuteTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastOrderId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceT1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceT2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPriceT1","type":"uint256"},{"internalType":"uint256","name":"newPriceT2","type":"uint256"}],"name":"resetPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRewardT1","type":"uint256"},{"internalType":"uint256","name":"newRewardT2","type":"uint256"}],"name":"resetReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardT1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardT2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondsOfEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"setPendingOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twamm","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"endTime_","type":"uint256"}],"name":"updateEndTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"keeper_","type":"address"}],"name":"updateKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newExecuteTime","type":"uint256"}],"name":"updateLastExecuteTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPriceIndex","type":"uint256"}],"name":"updatePriceIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRewardIndex","type":"uint256"}],"name":"updateRewardIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSecondsOfEpoch","type":"uint256"}],"name":"updateSecondsOfEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSecondsPerBlock","type":"uint256"}],"name":"updateSecondsPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isStop_","type":"bool"}],"name":"updateStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdc","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"withdrawAndBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"withdrawUsdc","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061021c5760003560e01c80639545022e11610125578063c3cafc6f116100ad578063cfea5d851161007c578063cfea5d8514610485578063e30c39781461048e578063e9ee2fa9146104a1578063ebbc4965146104aa578063f902055a146104b25761021c565b8063c3cafc6f1461042f578063c42069ec14610456578063cc7b326a14610469578063cd97cb451461047c5761021c565b8063aa168c5f116100f4578063aa168c5f146103da578063aced1661146103e3578063b39cc7b1146103f6578063b6a035a414610409578063bab4ce6b1461041c5761021c565b80639545022e1461039957806397779e1b146103ac57806397790217146103be578063a9ea1896146103d15761021c565b80635662ecc7116101a85780636ab3846b116101775780636ab3846b1461035857806377e811721461036b5780637a7d4937146103745780638460c6881461037d5780638da5cb5b146103865761021c565b80635662ecc7146103215780635cdc48f91461032a578063614619541461033d578063698ca7c2146103455761021c565b8063158ef93e116101ef578063158ef93e146102b857806319e072ef146102d55780633197cbb6146102e85780633e413bee146102f157806345f988a4146103185761021c565b80630dcc4b441461022157806310bd7ef614610236578063118f117f1461027a5780631406c88d14610291575b600080fd5b61023461022f366004612d33565b6104c5565b005b61025d7f000000000000000000000000efb66c23f6e0d178d8499744a7fe675ba32c69ca81565b6040516001600160a01b0390911681526020015b60405180910390f35b610283608d5481565b604051908152602001610271565b61025d7f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b881565b608f546102c59060ff1681565b6040519015158152602001610271565b6102346102e3366004612c64565b6104fd565b610283608e5481565b61025d7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b61028360855481565b610283608c5481565b610234610338366004612c2c565b610541565b610234610678565b610234610353366004612d63565b61119a565b610234610366366004612d33565b6111cf565b61028360875481565b610283608a5481565b61028360885481565b60005461025d906001600160a01b031681565b6102346103a7366004612d33565b6111fe565b608f546102c590610100900460ff1681565b6102346103cc366004612c2c565b6116cc565b61028360845481565b61028360865481565b60825461025d906001600160a01b031681565b610234610404366004612d33565b611718565b610234610417366004612d63565b611747565b61023461042a366004612d33565b61177c565b61025d7f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a9081565b610234610464366004612c2c565b6117ab565b610234610477366004612d33565b611886565b610283608b5481565b61028360835481565b60015461025d906001600160a01b031681565b61028360895481565b6102346118b5565b6102346104c0366004612d33565b6119a9565b6000546001600160a01b031633146104f85760405162461bcd60e51b81526004016104ef90612de0565b60405180910390fd5b608955565b6000546001600160a01b031633146105275760405162461bcd60e51b81526004016104ef90612de0565b608f80549115156101000261ff0019909216919091179055565b6000546001600160a01b0316331461056b5760405162461bcd60e51b81526004016104ef90612de0565b608f54610100900460ff166105ad5760405162461bcd60e51b815260206004820152600860248201526706e6f742073746f760c41b60448201526064016104ef565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316906370a082319060240160206040518083038186803b15801561060f57600080fd5b505afa158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190612d4b565b90506106747f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4883836119d8565b5050565b608f54610100900460ff16156106ba5760405162461bcd60e51b8152602060048201526007602482015266069732073746f760cc1b60448201526064016104ef565b6082546001600160a01b031633146107025760405162461bcd60e51b815260206004820152600b60248201526a37b7363c9035b2b2b832b960a91b60448201526064016104ef565b608e5442106107395760405162461bcd60e51b8152602060048201526003602482015262195b9960ea1b60448201526064016104ef565b608b54608d546107499190612e10565b608d8190554210156107965760405162461bcd60e51b81526020600482015260166024820152756e6f7420726561636820657865637574652074696d6560501b60448201526064016104ef565b42608b54608d546107a79190612e10565b116107eb5760405162461bcd60e51b81526020600482015260146024820152736f766572206e6578742065706f63682074696d6560601b60448201526064016104ef565b6000600019608c5414610be657604051633567cb5160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a90811660248301526000917f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b890911690633567cb519060440160206040518083038186803b1580156108a657600080fd5b505afa1580156108ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108de9190612c48565b90506000816001600160a01b031663ec7dd7bb608c546040518263ffffffff1660e01b815260040161091291815260200190565b60c06040518083038186803b15801561092a57600080fd5b505afa15801561093e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109629190612c9c565b9050806020015143116109b75760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420726561636820776974686472617761626c6520626c6f636b0000000060448201526064016104ef565b608c5460405163af6602b160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a908116602483015260448201929092524260648201527f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b89091169063af6602b190608401602060405180830381600087803b158015610a7557600080fd5b505af1158015610a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aad9190612d4b565b506040516370a0823160e01b81523060048201527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a906001600160a01b0316906370a082319060240160206040518083038186803b158015610b0d57600080fd5b505afa158015610b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b459190612d4b565b604051630852cd8d60e31b8152600481018290529093507f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a906001600160a01b0316906342966c6890602401602060405180830381600087803b158015610baa57600080fd5b505af1158015610bbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be29190612c80565b5050505b60007f000000000000000000000000efb66c23f6e0d178d8499744a7fe675ba32c69ca6001600160a01b031663c9b171496040518163ffffffff1660e01b815260040160206040518083038186803b158015610c4157600080fd5b505afa158015610c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c799190612d4b565b60865490915015610c8b576086546087555b6086819055604051638caa017160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a908116602483015260009182917f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b81690638caa017190604401604080518083038186803b158015610d3d57600080fd5b505afa158015610d51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d759190612d84565b90925090506000610d94836c0c9f2c9cd04674edea4000000084611b09565b60845490915015610da6576084546085555b80608481905550600042608b54608d54610dc09190612e10565b610dca9190612e67565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816906370a082319060240160206040518083038186803b158015610e2f57600080fd5b505afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e679190612d4b565b608f5490915060009060ff16610e98575080610e838382612e28565b608355608f805460ff19166001179055610f1e565b600080610eae6085546084546088546064611bbe565b91509150600080610ec86086546087546089546064611bbe565b91509150610eef8282610ee88787608354611b099092919063ffffffff16565b9190611b09565b6083819055610efe9088612e48565b945085851115610f1957859450610f158786612e28565b6083555b505050505b60008111610f635760405162461bcd60e51b81526020600482015260126024820152710627579696e6720616d6f756e7420697320360741b60448201526064016104ef565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b881166004830152602482018390527f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48169063095ea7b390604401602060405180830381600087803b158015610fed57600080fd5b505af1158015611001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110259190612c80565b507f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b86001600160a01b031663cd743e3e7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb487f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a9084608a5460056110a79190612e48565b6110b19089612e28565b6040516001600160e01b031960e087901b1681526001600160a01b0394851660048201529390921660248401526044830152606482015242608482015260a401602060405180830381600087803b15801561110b57600080fd5b505af115801561111f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111439190612d4b565b608c8190556083546040805192835260208301849052820152606081018990527f42659a4aa613c1e350c764f0ff2be36a175ac2a1e4b77b8e1467d1fed32becc89060800160405180910390a15050505050505050565b6000546001600160a01b031633146111c45760405162461bcd60e51b81526004016104ef90612de0565b608491909155608555565b6000546001600160a01b031633146111f95760405162461bcd60e51b81526004016104ef90612de0565b608e55565b6000546001600160a01b031633146112285760405162461bcd60e51b81526004016104ef90612de0565b608f54610100900460ff1661126a5760405162461bcd60e51b815260206004820152600860248201526706e6f742073746f760c41b60448201526064016104ef565b604051633567cb5160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a90811660248301526000917f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b890911690633567cb519060440160206040518083038186803b15801561131857600080fd5b505afa15801561132c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113509190612c48565b60405163ec7dd7bb60e01b8152600481018490529091506000906001600160a01b0383169063ec7dd7bb9060240160c06040518083038186803b15801561139657600080fd5b505afa1580156113aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ce9190612c9c565b9050806020015143116114235760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420726561636820776974686472617761626c6520626c6f636b0000000060448201526064016104ef565b60405163af6602b160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a9081166024830152604482018590524260648301527f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b8169063af6602b190608401602060405180830381600087803b1580156114db57600080fd5b505af11580156114ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115139190612d4b565b506040516370a0823160e01b81523060048201526000907f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a906001600160a01b0316906370a082319060240160206040518083038186803b15801561157657600080fd5b505afa15801561158a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ae9190612d4b565b9050600081116115f25760405162461bcd60e51b815260206004820152600f60248201526e3737ba3434b733903a3790313ab93760891b60448201526064016104ef565b604051630852cd8d60e31b8152600481018290527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a906001600160a01b0316906342966c6890602401602060405180830381600087803b15801561165457600080fd5b505af1158015611668573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168c9190612c80565b5060408051858152602081018390527f321a70b1e7aa7f458835d8a34f15391640fc7007590907c1f65e02de099f2e4f910160405180910390a150505050565b6000546001600160a01b031633146116f65760405162461bcd60e51b81526004016104ef90612de0565b608280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146117425760405162461bcd60e51b81526004016104ef90612de0565b608d55565b6000546001600160a01b031633146117715760405162461bcd60e51b81526004016104ef90612de0565b608691909155608755565b6000546001600160a01b031633146117a65760405162461bcd60e51b81526004016104ef90612de0565b608855565b6000546001600160a01b031633146117d55760405162461bcd60e51b81526004016104ef90612de0565b6001546001600160a01b038281169116141561182a5760405162461bcd60e51b815260206004820152601460248201527313dddb98589b194e881053149150511657d4d15560621b60448201526064016104ef565b6001546040516001600160a01b038084169216907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146118b05760405162461bcd60e51b81526004016104ef90612de0565b608a55565b6001546001600160a01b0316331461190f5760405162461bcd60e51b815260206004820152601e60248201527f4f776e61626c653a20524551554952455f50454e44494e475f4f574e4552000060448201526064016104ef565b60008054600180546001600160a01b038082166001600160a01b03198086168217808855931690935560405193811694929391169184917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b23649190a36001546040516001600160a01b03918216918316907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b6000546001600160a01b031633146119d35760405162461bcd60e51b81526004016104ef90612de0565b608b55565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611a349190612da7565b6000604051808303816000865af19150503d8060008114611a71576040519150601f19603f3d011682016040523d82523d6000602084013e611a76565b606091505b5091509150818015611aa0575080511580611aa0575080806020019051810190611aa09190612c80565b611b025760405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201526c185b9cd9995c8819985a5b1959609a1b60648201526084016104ef565b5050505050565b600080806000198587098587029250828110838203039150508060001415611b435760008411611b3857600080fd5b508290049050611bb7565b808411611b4f57600080fd5b600084868809851960019081018716968790049682860381900495909211909303600082900391909104909201919091029190911760038402600290811880860282030280860282030280860282030280860282030280860282030280860290910302029150505b9392505050565b600080848610611bea57611be1611bda6001607f1b8888611c16565b8585611c33565b91509150611c0d565b600080611c06611bff6001607f1b898b611c16565b8787611c33565b9450925050505b94509492505050565b6000611c2b611c26858585611c56565b611d45565b949350505050565b600080611c49611c44868686611c56565b611d7e565b915091505b935093915050565b6000806000611c658686611dd6565b915091508160001415611c9957838181611c8f57634e487b7160e01b600052601260045260246000fd5b0492505050611bb7565b8382101561021c576000611cae878787611e11565b9050600080611cbe858585611e3a565b915091508160001415611cf557868181611ce857634e487b7160e01b600052601260045260246000fd5b0495505050505050611bb7565b6000878103881690611d08848484611e5d565b90506000611d32838b81611d2c57634e487b7160e01b600052601260045260246000fd5b04611eb6565b919091029750611bb79650505050505050565b600070015bf0a8b1457695355fb8ac404e7a79e4821015611d7057611d6982611ede565b9050611d79565b611d69826122f2565b919050565b600080600160831b831015611da457611d968361239c565b91506001607f1b9050611dd1565b6000611daf846126f8565b9050611dc481607f0360ff1685901c82612804565b9250600160ff9091161b90505b915091565b6000806000611de58585612bb2565b9050848402808210611dfe579081900392509050611e0a565b60018183030393509150505b9250929050565b60008180611e2f57634e487b7160e01b600052601260045260246000fd5b838509949350505050565b600080828410611e505750839050818303611c4e565b6000198501838503611c49565b600080611e898380830381611e8257634e487b7160e01b600052601260045260246000fd5b0460010190565b9050828481611ea857634e487b7160e01b600052601260045260246000fd5b048186021795945050505050565b60006001815b6008811015611ed75783820260020382029150600101611ebc565b5092915050565b6000808080806fd3094c70f034de4b96ff7d5b6f99fcd98610611f21576001607e1b93909301926fd3094c70f034de4b96ff7d5b6f99fcd96001607f1b87020495505b6fa45af1e1f40c333b3de1db4dd55f29a88610611f5e576001607d1b93909301926fa45af1e1f40c333b3de1db4dd55f29a86001607f1b87020495505b6f910b022db7ae67ce76b441c27035c6a28610611f9b576001607c1b93909301926f910b022db7ae67ce76b441c27035c6a26001607f1b87020495505b6f88415abbe9a76bead8d00cf112e4d4a98610611fd8576001607b1b93909301926f88415abbe9a76bead8d00cf112e4d4a96001607f1b87020495505b6f84102b00893f64c705e841d5d4064bd48610612015576001607a1b93909301926f84102b00893f64c705e841d5d4064bd46001607f1b87020495505b6f8204055aaef1c8bd5c3259f4822735a3861061205257600160791b93909301926f8204055aaef1c8bd5c3259f4822735a36001607f1b87020495505b6f810100ab00222d861931c15e39b44e9a861061208f57600160781b93909301926f810100ab00222d861931c15e39b44e9a6001607f1b87020495505b6f808040155aabbbe9451521693554f73486106120cc57600160771b93909301926f808040155aabbbe9451521693554f7346001607f1b87020495505b6f7fffffffffffffffffffffffffffffff19860192508291506001607f1b828002049050600160801b83810383020493909301926001607f1b828202049150600160811b836faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0383028161214057634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600360801b836f999999999999999999999999999999990383028161218657634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600160821b836f92492492492492492492492492492492038302816121cc57634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600560801b836f8e38e38e38e38e38e38e38e38e38e38e0383028161221257634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600360811b836f8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b0383028161225857634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600760801b836f89d89d89d89d89d89d89d89d89d89d890383028161229e57634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600160831b836f88888888888888888888888888888888038302816122e457634e487b7160e01b600052601260045260246000fd5b049390930195945050505050565b600080600160801b83106123225760006123116001607f1b8504612bc1565b60ff1693841c936001607f1b029150505b6001607f1b83111561237057607f5b60ff81161561236e576001607f1b848002049350600160801b841061236557600193841c9360ff6000198301161b91909101905b60001901612331565b505b6f05b9de1d10bf4103d647b0955897ba806f03f80fe03f80fe03f80fe03f80fe03f88202049392505050565b60008080806001607c1b850691508190506001607f1b818002046710e1b3be415a00008102939093019290506001607f1b828202046705a0913f6b1e00008102939093019290506001607f1b82820204670168244fdac780008102939093019290506001607f1b82820204664807432bc180008102939093019290506001607f1b82820204660c0135dca040008102939093019290506001607f1b828202046601b707b1cdc0008102939093019290506001607f1b828202046536e0f639b8008102939093019290506001607f1b82820204650618fee9f8008102939093019290506001607f1b82820204649c197dcc008102939093019290506001607f1b82820204640e30dce4008102939093019290506001607f1b8282020464012ebd13008102939093019290506001607f1b828202046317499f008102939093019290506001607f1b828202046301a9d4808102939093019290506001607f1b82820204621c63808102939093019290506001607f1b828202046201c6388102939093019290506001607f1b82820204611ab88102939093019290506001607f1b8282020461017c8102939093019290506001607f1b8282020460148102939093019290506001607f1b828202049283019290506001607f1b826721c3677c82b400008504010192506001607c1b8516156125b85770018ebef9eac820ae8682b9793ac6d1e7767001c3d6a24ed82218787d624d3e5eba95f984020492505b6001607d1b8516156125ee577001368b2fc6f9609fe7aceb46aa619baed470018ebef9eac820ae8682b9793ac6d1e77884020492505b6001607e1b851615612623576fbc5ab1b16779be3575bd8f0520a9f21f7001368b2fc6f9609fe7aceb46aa619baed584020492505b6001607f1b851615612657576f454aaa8efe072e7f6ddbab84b40a55c96fbc5ab1b16779be3575bd8f0520a9f21e84020492505b600160801b85161561268b576f0960aadc109e7a3bf4578099615711ea6f454aaa8efe072e7f6ddbab84b40a55c584020492505b600160811b8516156126be576e2bf84208204f5977f9a8cf01fdce3d6f0960aadc109e7a3bf4578099615711d784020492505b600160821b8516156126ef576d03c6ab775dd0b95b4cbee7e65d116e2bf84208204f5977f9a8cf01fdc30784020492505b50909392505050565b60006020607f5b8060ff168260010160ff16101561275b576000600260ff848401160490508460028260ff166080811061274257634e487b7160e01b600052603260045260246000fd5b01541061275157809250612755565b8091505b506126ff565b8360028260ff166080811061278057634e487b7160e01b600052603260045260246000fd5b015410612790579150611d799050565b8360028360ff16608081106127b557634e487b7160e01b600052603260045260246000fd5b0154106127c457509050611d79565b60405162461bcd60e51b81526020600482015260156024820152740ccd2dcc8a0dee6d2e8d2dedc7440f0407c40dac2f605b1b60448201526064016104ef565b60008083905060008360ff16858302901c9150816f03442c4e6074a82f1797f72ac000000002810190508360ff16858302901c9150816f0116b96f757c380fb287fd0e4000000002810190508360ff16858302901c9150816e45ae5bdd5f0e03eca1ff439000000002810190508360ff16858302901c9150816e0defabf91302cd95b9ffda5000000002810190508360ff16858302901c9150816e02529ca9832b22439efff9b800000002810190508360ff16858302901c9150816d54f1cf12bd04e516b6da8800000002810190508360ff16858302901c9150816d0a9e39e257a09ca2d6db5100000002810190508360ff16858302901c9150816d012e066e7b839fa050c30900000002810190508360ff16858302901c9150816c1e33d7d926c329a1ad1a80000002810190508360ff16858302901c9150816c02bee513bdb4a6b19b5f80000002810190508360ff16858302901c9150816b3a9316fa79b88eccf2a0000002810190508360ff16858302901c9150816b048177ebe1fa81237520000002810190508360ff16858302901c9150816a5263fe90242dcbacf0000002810190508360ff16858302901c9150816a057e22099c030d9410000002810190508360ff16858302901c9150816957e22099c030d941000002810190508360ff16858302901c91508169052b6b5456997631000002810190508360ff16858302901c915081684985f67696bf74800002810190508360ff16858302901c9150816803dea12ea99e49800002810190508360ff16858302901c9150816731880f2214b6e00002810190508360ff16858302901c91508167025bcff56eb3600002810190508360ff16858302901c915081661b722e10ab100002810190508360ff16858302901c9150816601317c7007700002810190508360ff16858302901c915081650cba84aafa0002810190508360ff16858302901c9150816482573a0a0002810190508360ff16858302901c9150816405035ad90002810190508360ff16858302901c915081632f881b0002810190508360ff16858302901c9150816301b2934002810190508360ff16858302901c915081620efc4002810190508360ff16858302901c915081617fe002810190508360ff16858302901c91508161042002810190508360ff16858302901c915081602102810190508360ff16858302901c915081600102810190508360ff166001901b856f0688589cc0e9505e2f2fee55800000008381612ba657634e487b7160e01b600052601260045260246000fd5b04010195945050505050565b60006000198284099392505050565b600080610100831015612be9575b6001831115612be457600192831c9201612bcf565b612c1b565b60805b60ff811615611ed757600160ff82161b8410612c105760ff81169390931c92908117905b60011c607f16612bec565b92915050565b8051611d7981612e94565b600060208284031215612c3d578081fd5b8135611bb781612e94565b600060208284031215612c59578081fd5b8151611bb781612e94565b600060208284031215612c75578081fd5b8135611bb781612eac565b600060208284031215612c91578081fd5b8151611bb781612eac565b600060c08284031215612cad578081fd5b60405160c0810181811067ffffffffffffffff82111715612cdc57634e487b7160e01b83526041600452602483fd5b8060405250825181526020830151602082015260408301516040820152612d0560608401612c21565b6060820152612d1660808401612c21565b6080820152612d2760a08401612c21565b60a08201529392505050565b600060208284031215612d44578081fd5b5035919050565b600060208284031215612d5c578081fd5b5051919050565b60008060408385031215612d75578081fd5b50508035926020909101359150565b60008060408385031215612d96578182fd5b505080516020909101519092909150565b60008251815b81811015612dc75760208186018101518583015201612dad565b81811115612dd55782828501525b509190910192915050565b60208082526016908201527527bbb730b136329d102922a8aaa4a922afa7aba722a960511b604082015260600190565b60008219821115612e2357612e23612e7e565b500190565b600082612e4357634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615612e6257612e62612e7e565b500290565b600082821015612e7957612e79612e7e565b500390565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114612ea957600080fd5b50565b8015158114612ea957600080fdfea2646970667358221220b81f0d605fd02a2fe0f4b95fcb06708b034618edb8a98a54a3249507e1ac14de64736f6c63430008020033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.