More Info
Private Name Tags
ContractCreator
TokenTracker
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
14937772 | 2 mins ago | 0.00083916 ETH | ||||
14937772 | 2 mins ago | 0.00083916 ETH | ||||
14936730 | 2 hrs ago | 0.00618564 ETH | ||||
14936730 | 2 hrs ago | 0.00618564 ETH | ||||
14936630 | 2 hrs ago | 0.00330013 ETH | ||||
14936630 | 2 hrs ago | 0.00330013 ETH | ||||
14923334 | 17 hrs ago | 0.00279704 ETH | ||||
14923334 | 17 hrs ago | 0.00279704 ETH | ||||
14906030 | 34 hrs ago | 0.00511401 ETH | ||||
14906030 | 34 hrs ago | 0.00511401 ETH | ||||
14900205 | 41 hrs ago | 0.00774029 ETH | ||||
14900205 | 41 hrs ago | 0.00774029 ETH | ||||
14875606 | 2 days ago | 0.00619326 ETH | ||||
14875606 | 2 days ago | 0.00619326 ETH | ||||
14871811 | 3 days ago | 0.00878442 ETH | ||||
14871811 | 3 days ago | 0.00878442 ETH | ||||
14868143 | 3 days ago | 0.00470139 ETH | ||||
14868143 | 3 days ago | 0.00470139 ETH | ||||
14868111 | 3 days ago | 0.00147518 ETH | ||||
14868111 | 3 days ago | 0.00147518 ETH | ||||
14852034 | 4 days ago | 0.01153882 ETH | ||||
14852034 | 4 days ago | 0.01153882 ETH | ||||
14852004 | 4 days ago | 0.02276871 ETH | ||||
14852004 | 4 days ago | 0.02276871 ETH | ||||
14849110 | 4 days ago | 0.00342268 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x53f1B398...A86843F3a The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
SyncSwapCryptoPoolDelegated
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "../../libraries/Math.sol"; import "../../libraries/UnsafeMath.sol"; import "../../libraries/TransferHelper.sol"; import "../../libraries/ERC20Permit2.sol"; import "../../libraries/MetadataHelper.sol"; import "../../libraries/ReentrancyGuard.sol"; import "../../interfaces/IWETH.sol"; import "../../interfaces/IOwnable.sol"; import "../../interfaces/ICallback.sol"; import "../../interfaces/vault/IVault.sol"; import "../../interfaces/pool/ICryptoPool.sol"; import "../../interfaces/master/IPoolMaster.sol"; import "../../interfaces/master/IFeeRecipient.sol"; import "../../interfaces/master/IFeeManagerV2.sol"; import "../PoolFlashLoans.sol"; import "../crypto/ICryptoMath.sol"; import "../crypto/ICryptoView.sol"; error Overflow(); error InsufficientLiquidityMinted(); error Loss(); interface ICryptoPoolFactory { function master() external view returns (address); function cryptoMath() external view returns (address); function cryptoView() external view returns (address); function cryptoFunc() external view returns (address); function cryptoBurn() external view returns (address); function getDeployData() external view returns (bytes memory); } // This pool uses delegate call with sub implementation contracts CryptoBurn and CryptoFunc to reduce the code size. contract SyncSwapCryptoPoolDelegated is UnsafeMath, ERC20Permit2, ReentrancyGuard { //////////////////////////////////////////////////////// /////////////// CONSTANTS AND IMMUTABLES /////////////// address private WETH = 0x5300000000000000000000000000000000000004; // Linea WETH address public vault = 0x7160570BB153Edd0Ea1775EC2b2Ac9b65F1aB61B; // Linea Vault address public master = 0x4318a74425E5353a1194CF26138Baa87B607657C; // Linea V2 Pool Master uint24 private constant MAX_FEE = 20000; /// @dev Pool type `3` for crypto pools. uint16 public constant poolType = 3; uint public constant poolVersion = 2; address private immutable cryptoFunc; address private immutable cryptoBurn; address public immutable factory; address public immutable token0; address public immutable token1; /// @dev Multipliers for each pooled token's precision to get to the pool precision decimals /// which is agnostic to the pool, but usually is 18. /// For example, TBTC has 18 decimals, so the multiplier should be 10 ** (18 - 18) = 1. /// WBTC has 8, so the multiplier should be 10 ** (18 - 8) => 10 ** 10. /// The value is only for crypto pools, and has no effects on non-crypto pools. uint public immutable token0PrecisionMultiplier; uint public immutable token1PrecisionMultiplier; /////////////// CONSTANTS AND IMMUTABLES /////////////// //////////////////////////////////////////////////////// ICryptoMath public MATH; /// @dev Pool reserve of each pool token as of immediately after the most recent balance event. /// The value is used to measure growth in invariant on mints and input tokens on swaps. uint128 private reserve0_; uint128 private reserve1_; /// @dev Invariant of the pool as of immediately after the most recent liquidity event. uint public invariantLast; /// @dev Price scale determines the price band around which liquidity is concentrated. uint public priceScale; /// @dev Price target given by moving average. /// The oracle is an exponential moving average, with a periodicity determined by MA time. /// The aggregated prices are cached state prices (dy/dx) calculated AFTER the latest trade. uint public cachedPriceOracle; /// @dev The quote by the AMM for an infinitesimally small swap after the last trade. /// It is not equivalent to the last traded price, and is computed by taking /// the partial differential of `x` w.r.t `y`. uint public lastPrices; uint public lastPricesTimestamp; /// @dev Cached (fast to read) virtual price. The cached `virtualPrice` is also used internally. uint public virtualPrice; /// @dev Current pool profits. uint public xcpProfit; /// @dev Full profit at last claim of protocol fees. uint public xcpProfitLast = 1e18; //uint public initialParams; //uint public futureParams; ICryptoPool.PoolParams public poolParams; ICryptoPool.RebalancingParams public rebalancingParams = ICryptoPool.RebalancingParams({ allowedExtraProfit: 2000000000000, adjustmentStep: 146000000000000, maTime: 600, requiredProfit: 5000, checkLastProfit: 0 }); struct TokenAmount { address token; uint amount; } event Sync( uint reserve0, uint reserve1 ); event UpdatePoolProfit( uint xcpProfit, uint virtualPrice ); event UpdateInvariant( uint newInvariant ); event UpdatePriceScale( uint newPriceScale ); event Swapped( address indexed sender, address indexed user, address indexed tokenOut, uint amountIn, uint amountOut, uint24 swapFee, address to ); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Fee( uint amount0, uint amount1 ); receive() external payable {} fallback() external payable { address target = cryptoFunc; // burn(bytes,address,address,bytes): 0xf66eab5b // burnSingle(bytes,address,address,bytes): 0x27b0bcea // calculateSingleWithdrawAmount(address,uint256,uint256,uint256,bool,bool): 0x3e5e465e // function getVirtualPrice() external view returns (uint) 0xe25aa5fa // function getPriceOracle() external view returns (uint) 0xfca513a8 if (msg.sig == 0xf66eab5b || msg.sig == 0x27b0bcea || msg.sig == 0x3e5e465e || msg.sig == 0xe25aa5fa || msg.sig == 0xfca513a8) { target = cryptoBurn; } assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /// @dev Factory must ensures that the parameters are valid. constructor() { (bytes memory _deployData) = ICryptoPoolFactory(msg.sender).getDeployData(); (address _token0, address _token1, uint _token0PrecisionMultiplier, uint _token1PrecisionMultiplier, uint _initialPrice) = abi.decode( _deployData, (address, address, uint, uint, uint) ); //address _master = ICryptoPoolFactory(msg.sender).master(); MATH = ICryptoMath(ICryptoPoolFactory(msg.sender).cryptoMath()); factory = msg.sender; cryptoFunc = ICryptoPoolFactory(msg.sender).cryptoFunc(); cryptoBurn = ICryptoPoolFactory(msg.sender).cryptoBurn(); (token0, token1, token0PrecisionMultiplier, token1PrecisionMultiplier) = ( _token0, _token1, _token0PrecisionMultiplier, _token1PrecisionMultiplier ); // default pool params uint32 _a = 400000; uint64 _gamma = 145000000000000; poolParams = ICryptoPool.PoolParams({ initialA: _a, futureA: _a, initialGamma: _gamma, futureGamma: _gamma, initialTime: 0, futureTime: 0 }); _setInitialPrice(_initialPrice); // try to set symbols for the LP token (bool _success0, string memory _symbol0) = MetadataHelper.getSymbol(_token0); (bool _success1, string memory _symbol1) = MetadataHelper.getSymbol(_token1); if (_success0 && _success1) { _initialize( string(abi.encodePacked("SyncSwap Aqua LP")), string(abi.encodePacked(_symbol0, "/", _symbol1, "-A")) ); } else { _initialize("SLP", "SLP"); } } function _setInitialPrice(uint _initialPrice) private { priceScale = _initialPrice; emit UpdatePriceScale(_initialPrice); cachedPriceOracle = _initialPrice; lastPrices = _initialPrice; lastPricesTimestamp = block.timestamp; } /// @dev Returns the verified sender address otherwise `address(0)`. function _getVerifiedSender(address _sender) private view returns (address) { if (_sender != msg.sender) { // The sender from non-forwarder is invalid. try IPoolMaster(master).isForwarder(msg.sender) returns (bool _isTrustedForwarder) { return _isTrustedForwarder ? _sender : msg.sender; } catch { return msg.sender; } } return msg.sender; } function _balances() private view returns (uint balance0, uint balance1) { balance0 = IERC20(token0).balanceOf(address(this)); balance1 = IERC20(token1).balanceOf(address(this)); } function _updateReserves(uint _balance0, uint _balance1) private { if (_balance0 > type(uint128).max) { revert Overflow(); } if (_balance1 > type(uint128).max) { revert Overflow(); } (reserve0_, reserve1_) = (uint128(_balance0), uint128(_balance1)); emit Sync(_balance0, _balance1); } /// @dev Swaps one token for another - should be called via the router after transferring input tokens. /// The router should ensure that sufficient output tokens are received. function swap( bytes memory _data, address _sender, address _callback, bytes memory _callbackData ) public nonReentrant returns (TokenAmount memory _tokenAmount) { ICallback.BaseSwapCallbackParams memory params; (params.tokenIn, params.to, params.withdrawMode) = abi.decode(_data, (address, address, uint8)); (params.reserve0, params.reserve1) = getReserves(); (params.balance0, params.balance1) = _balances(); // Gets swap fee for the sender. _sender = _getVerifiedSender(_sender); // ----------- Update invariant if A, gamma are undergoing ramps --------- // In case ramp is happening (uint a, uint gamma, uint futureTime) = _params(); // ----------------------- Calculate dy and fees -------------------------- uint xp0; uint xp1; uint _k0_prev; uint _feeAmountOut; ICryptoMath _MATH = MATH; if (params.tokenIn == token0) { (params.amountOut, params.swapFee, _feeAmountOut, xp0, xp1, _k0_prev) = _getAmountOut( GetAmountOutInputParams({ sender: _sender, a: a, gamma: gamma, balance0: params.balance0, balance1: params.balance1, reserve0: params.reserve0, reserve1: params.reserve1, token0In: true, futureTime: futureTime }), _MATH ); params.tokenOut = token1; params.balance1 -= params.amountOut; params.amountIn = params.balance0 - params.reserve0; emit Swap(msg.sender, params.amountIn, 0, 0, params.amountOut, params.to); emit Fee(0, _feeAmountOut); } else { require(params.tokenIn == token1); (params.amountOut, params.swapFee, _feeAmountOut, xp0, xp1, _k0_prev) = _getAmountOut( GetAmountOutInputParams({ sender: _sender, a: a, gamma: gamma, balance0: params.balance0, balance1: params.balance1, reserve0: params.reserve0, reserve1: params.reserve1, token0In: false, futureTime: futureTime }), _MATH ); params.tokenOut = token0; params.balance0 -= params.amountOut; params.amountIn = params.balance1 - params.reserve1; emit Swap(msg.sender, 0, params.amountIn, params.amountOut, 0, params.to); emit Fee(_feeAmountOut, 0); } require(params.amountIn != 0 && params.amountOut != 0); // ------------------------ Tweak `priceScale` ---------------------------- _tweakPrice(a, gamma, xp0, xp1, 0, futureTime, _k0_prev, _MATH); // Updates reserves with up-to-date balances (updated above). _updateReserves(params.balance0, params.balance1); // Transfers output tokens. _transferTokens(params.tokenOut, params.to, params.amountOut, params.withdrawMode); // Calls callback with data. if (_callback != address(0)) { // Fills additional values for callback params. params.sender = _sender; params.callbackData = _callbackData; // Calculates fee amount for callback. params.feeIn = Math.mulDivUnsafeFirstLast(params.amountIn, params.swapFee, 1e5); ICallback(_callback).syncSwapBaseSwapCallback(params); } _tokenAmount.token = params.tokenOut; _tokenAmount.amount = params.amountOut; emit Swapped( msg.sender, _sender, params.tokenOut, params.amountIn, params.amountOut, params.swapFee, params.to ); } struct GetAmountOutArgs { uint xp0; uint xp1; uint invariant; uint xp1PriceScale; uint y; } struct GetAmountOutInputParams { address sender; uint a; uint gamma; uint balance0; uint balance1; uint reserve0; uint reserve1; bool token0In; uint futureTime; } function _getAmountOut( GetAmountOutInputParams memory p, ICryptoMath _MATH ) private view returns ( uint _amountOut, uint24 _swapFee, uint _feeAmountOut, uint _newXp0, uint _newXp1, uint _k0_prev ) { GetAmountOutArgs memory it; it.xp0 = p.balance0 * token0PrecisionMultiplier; it.xp1PriceScale = priceScale * token1PrecisionMultiplier; it.xp1 = Math.mulDivUnsafeLast(p.balance1, it.xp1PriceScale, 1e18); if (p.futureTime > block.timestamp) { if (p.token0In) { // Resue `it.y` as `xp0` here it.y = unsafe_mul( p.reserve0, token0PrecisionMultiplier ); // <---- already safe_mul above for `xp0` it.invariant = _MATH.computeD(p.a, p.gamma, it.y, it.xp1, 0); } else { // Resue `it.y` as `xp1` here it.y = unsafe_div( unsafe_mul(p.reserve1, it.xp1PriceScale), 1e18 ); // <---- already safe_mul above for `xp1` it.invariant = _MATH.computeD(p.a, p.gamma, it.xp0, it.y, 0); } } else { it.invariant = invariantLast; } if (p.token0In) { (it.y, _k0_prev) = _MATH.getY(p.a, p.gamma, it.xp0, it.xp1, it.invariant, 1); _amountOut = it.xp1 - it.y; it.xp1 -= _amountOut; _amountOut -= 1; _amountOut = Math.mulDivUnsafeFirst(1e18, _amountOut, it.xp1PriceScale); _swapFee = _getFee(p.sender, token0, token1, it.xp0, it.xp1); _feeAmountOut = Math.mulDivUnsafeLast(_swapFee, _amountOut, 1e5); _amountOut -= _feeAmountOut; _newXp0 = it.xp0; _newXp1 = unsafe_div(unsafe_mul(p.reserve1 - _amountOut, it.xp1PriceScale), 1e18); // <---- already safe_mul above for `xp1` } else { (it.y, _k0_prev) = _MATH.getY(p.a, p.gamma, it.xp0, it.xp1, it.invariant, 0); _amountOut = it.xp0 - it.y; it.xp0 -= _amountOut; _amountOut -= 1; _amountOut = Math.divUnsafeLast(_amountOut, token0PrecisionMultiplier); _swapFee = _getFee(p.sender, token1, token0, it.xp0, it.xp1); _feeAmountOut = Math.mulDivUnsafeLast(_swapFee, _amountOut, 1e5); _amountOut -= _feeAmountOut; _newXp0 = unsafe_mul(p.reserve0 - _amountOut, token0PrecisionMultiplier); _newXp1 = it.xp1; } } function _transferTokens(address token, address to, uint amount, uint8 withdrawMode) private { if (withdrawMode == 0) { TransferHelper.safeTransfer(token, vault, amount); IVault(vault).deposit(token, to); } else { if (withdrawMode == 1 && token == WETH) { IWETH(WETH).withdraw(amount); TransferHelper.safeTransferETH(to, amount); } else { TransferHelper.safeTransfer(token, to, amount); } } } function getReserves() public view returns (uint _reserve0, uint _reserve1) { (_reserve0, _reserve1) = (reserve0_, reserve1_); } function _getFeeData( address _sender, address _tokenIn, address _tokenOut, bytes memory data ) private view returns (IFeeManagerV2.FeeData memory) { address _feeManager; try IPoolMaster(master).feeManager() returns (address __feeManager) { _feeManager = __feeManager; } catch { // leave `_feeManager` as `address(0)` and return default fee data below } if (_feeManager != address(0)) { try IFeeManagerV2(_feeManager).getSwapFeeData( address(this), _sender, _tokenIn, _tokenOut, data ) returns (IFeeManagerV2.FeeData memory feeData) { return feeData; } catch { // return default fee data, see below } } // return the default fee data here, if fee manager not exists or catch an error return IFeeManagerV2.FeeData({ gamma: 230000000000000, minFee: 260, // 0.26% maxFee: 450 // 0.45% }); //return IFeeManagerV2(_feeManager).getSwapFeeData(address(this), _sender, _tokenIn, _tokenOut, data); } function _getFee( address _sender, address _tokenIn, address _tokenOut, uint xp0, uint xp1 ) internal view returns (uint24 _fee) { _fee = _getFeeWithData(_sender, _tokenIn, _tokenOut, xp0, xp1, abi.encode(msg.sender)); } function _getFeeWithData( address _sender, address _tokenIn, address _tokenOut, uint xp0, uint xp1, bytes memory data ) internal view returns (uint24 _fee) { IFeeManagerV2.FeeData memory feeData = _getFeeData(_sender, _tokenIn, _tokenOut, data); uint f = xp0 + xp1; f = unsafe_mul(feeData.gamma, 1e18) / ( unsafe_add(feeData.gamma, 1e18) - unsafe_div(4e18 * xp0 / f * xp1, f) ); _fee = uint24(unsafe_div( feeData.minFee * f + feeData.maxFee * (1e18 - f), 1e18 )); if (_fee > MAX_FEE) { _fee = MAX_FEE; } } function _getFeeRecipient() internal view returns (address) { try IPoolMaster(master).getFeeRecipient() returns (address _feeRecipient) { return _feeRecipient; } catch { return address(0); } } function _xp(uint _reserve0, uint _reserve1) private view returns (uint xp0, uint xp1) { xp0 = _reserve0 * token0PrecisionMultiplier; xp1 = Math.mulDivUnsafeFirstLast(token1PrecisionMultiplier, priceScale * _reserve1, 1e18); } function _params() private view returns (uint a, uint gamma, uint futureTime) { ICryptoPool.PoolParams memory params = poolParams; gamma = params.futureGamma; a = params.futureA; futureTime = params.futureTime; if (futureTime > block.timestamp) { uint duration = futureTime - params.initialTime; uint elapsed = block.timestamp - params.initialTime; uint remaining = duration - elapsed; a = (params.initialA * remaining + a * elapsed) / duration; gamma = (params.initialGamma * remaining + gamma * elapsed) / duration; } } function _getXCP(uint _invariant, uint _priceScale) private pure returns (uint) { return Math.geometricMean( unsafe_div(_invariant, 2), Math.mulDivUnsafeFirst(1e18, _invariant, Math.mulUnsafeFirst(2, _priceScale)) ); } struct TweakPriceArgs { uint priceScale; uint priceOracle; uint lastPrices; uint lastPricesTimestamp; uint totalSupply; uint xcpProfit; uint virtualPrice; uint oldVirtualPrice; uint newInvariant; uint norm; } /// @notice Tweaks `priceOracle`, `lastPrices` and conditionally adjusts `priceScale`. /// This is called whenever there is an unbalanced liquidity operation: swap, mint, or burnSingle. /// @dev Contains main liquidity rebalancing logic, by tweaking `priceScale`. function _tweakPrice( uint a, uint gamma, uint xp0, uint xp1, uint invariantUnadjusted, uint _futureTime, uint _k0_prev, ICryptoMath _MATH ) private returns (uint, uint) { // returns (newInvariant, newPriceScale) TweakPriceArgs memory it; // ---------------------------- Read storage ------------------------------ ICryptoPool.RebalancingParams memory _rebalancingParams = rebalancingParams; it.priceOracle = cachedPriceOracle; it.priceScale = priceScale; it.lastPricesTimestamp = lastPricesTimestamp; it.totalSupply = totalSupply; it.oldVirtualPrice = virtualPrice; // ----------------------- Update MA if needed ---------------------------- if (it.lastPricesTimestamp < block.timestamp) { // The moving average price oracle is calculated using the `lastPrices` // of the trade at the previous block, and the price oracle logged // before that trade. This can happen only once per block. // ------------------ Calculate moving average params ----------------- // ---------------------------------------------- Update price oracles. // ----------------- We cap state price that goes into the EMA with // 2 x priceScale. it.priceOracle = _MATH.getPriceOracle( it.lastPricesTimestamp, _rebalancingParams.maTime, lastPrices, it.priceScale, it.priceOracle ); cachedPriceOracle = it.priceOracle; lastPricesTimestamp = block.timestamp; } // `priceOracle` is used further on to calculate its vector // distance from `priceScale`. This distance is used to calculate // the amount of adjustment to be done to the `priceScale`. // ---------------- If `invariantUnadjusted` is 0, calculate it ----------------- if (invariantUnadjusted == 0) { invariantUnadjusted = _MATH.computeD(a, gamma, xp0, xp1, _k0_prev); } // ----------------- Calculate and update `lastPrices` -------------------- lastPrices = _MATH.getLastPrices( a, gamma, xp0, xp1, invariantUnadjusted, it.priceScale ); // ------------------------- Update `xcpProfit` --------------------------- uint _xp0; uint _xp1; if (it.oldVirtualPrice != 0) { _xp0 = Math.divUnsafeLast(invariantUnadjusted, 2); _xp1 = Math.mulDivUnsafeFirst(1e18, invariantUnadjusted, Math.mulUnsafeFirst(2, it.priceScale)); it.virtualPrice = Math.mulDivUnsafeFirst(1e18, Math.geometricMean(_xp0, _xp1), it.totalSupply); it.xcpProfit = Math.divUnsafeLast(xcpProfit * it.virtualPrice, it.oldVirtualPrice); // If A and gamma are NOT undergoing ramps (t < block.timestamp), // ensure new `virtualPrice` is not less than `oldVirtualPrice`, // else the pool suffers a loss. if (_futureTime < block.timestamp) { if (it.virtualPrice <= it.oldVirtualPrice) { revert Loss(); } } } else { it.xcpProfit = 1e18; it.virtualPrice = 1e18; } xcpProfit = it.xcpProfit; // ------------ Rebalance liquidity if there's enough profits to adjust it: //if (Math.mulUnsafeFirst(2, it.virtualPrice) - 1e18 > it.xcpProfit + unsafe_mul(_rebalancingParams.allowedExtraProfit, 2)) { if (it.virtualPrice > 1e18 && it.xcpProfit > 1e18 && Math.mulUnsafeFirst(1e4, it.virtualPrice - 1e18) > Math.mulUnsafeFirst(_rebalancingParams.requiredProfit, it.xcpProfit + _rebalancingParams.allowedExtraProfit - 1e18)) { // ------------------- Get adjustment step ---------------------------- // Calculate the vector distance between `priceScale` and `priceOracle`. it.norm = Math.mulDivUnsafeFirst(1e18, it.priceOracle, it.priceScale); if (it.norm > 1e18) { it.norm = unsafe_sub(it.norm, 1e18); } else { it.norm = unsafe_sub(1e18, it.norm); } // Reuse `_futureTime` as `_adjustmentStep` here to avoid stake too deep errors. _futureTime = Math.max(_rebalancingParams.adjustmentStep, Math.divUnsafeLast(it.norm, 5)); // We only adjust prices if the vector distance between `priceOracle` // and `priceScale` is large enough. // This check ensures that no rebalancing occurs if the distance is low // i.e. the pool prices are pegged to the oracle prices. if (it.norm > _futureTime) { // ------------------------------------- Calculate new price scale. // Reuse `_futureTime` as `newPriceScale` to avoid stake too deep errors. _futureTime = Math.divUnsafeLast( it.priceScale * unsafe_sub(it.norm, _futureTime) + (_futureTime * it.priceOracle), it.norm ); // <- norm is non-zero and gt adjustment_step; unsafe = safe // --------------- Update stale xp (using price_scale) with p_new. _xp0 = xp0; _xp1 = Math.mulDivUnsafeLast(xp1, _futureTime, it.priceScale); // unsafe_div because we did safediv before -----^ // ------------------------------------------ Update D with new xp. // Calculate "extended constant product" invariant xCP and virtual price. it.newInvariant = _MATH.computeD(a, gamma, _xp0, _xp1, 0); // ------------------------------------- Convert xp to real prices. _xp0 = Math.divUnsafeLast(it.newInvariant, 2); _xp1 = Math.mulDivUnsafeFirst( 1e18, it.newInvariant, Math.mulUnsafeFirst(2, _futureTime) ); // ---------- Calculate new virtual price using new xp and D. // Reuse `oldVirtualPrice` (but it has new virtual price). it.oldVirtualPrice = Math.mulDivUnsafeFirst( 1e18, Math.geometricMean(_xp0, _xp1), it.totalSupply ); // ---------------------------- Proceed if we've got enough profit. if (it.oldVirtualPrice > 1e18) { //if (Math.mulUnsafeFirst(2, it.oldVirtualPrice) - 1e18 > it.xcpProfit) { // Note - rebalancing fees if (Math.mulUnsafeFirst(1e4, it.oldVirtualPrice - 1e18) > Math.mulUnsafeFirst(_rebalancingParams.requiredProfit, it.xcpProfit - 1e18)) { priceScale = _futureTime; // `newPriceScale` emit UpdatePriceScale(_futureTime); invariantLast = it.newInvariant; emit UpdateInvariant(it.newInvariant); virtualPrice = it.oldVirtualPrice; emit UpdatePoolProfit(it.xcpProfit, it.oldVirtualPrice); return (it.newInvariant, _futureTime); } } } } // --------- `priceScale` was not adjusted. Update the profit counter and D. // If we are here, the `priceScale` adjustment did not happen, // Still need to update the profit counter and D. invariantLast = invariantUnadjusted; emit UpdateInvariant(invariantUnadjusted); virtualPrice = it.virtualPrice; emit UpdatePoolProfit(it.xcpProfit, it.virtualPrice); return (invariantUnadjusted, it.priceScale); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; /// @dev The callback interface for SyncSwap base pool operations. /// Note additional checks will be required for some callbacks, see below for more information. /// Visit the documentation https://syncswap.gitbook.io/api-documentation/ for more details. interface ICallback { struct BaseMintCallbackParams { address sender; address to; uint reserve0; uint reserve1; uint balance0; uint balance1; uint amount0; uint amount1; uint fee0; uint fee1; uint newInvariant; uint oldInvariant; uint totalSupply; uint liquidity; uint24 swapFee; bytes callbackData; } function syncSwapBaseMintCallback(BaseMintCallbackParams calldata params) external; struct BaseBurnCallbackParams { address sender; address to; uint balance0; uint balance1; uint liquidity; uint totalSupply; uint amount0; uint amount1; uint8 withdrawMode; bytes callbackData; } function syncSwapBaseBurnCallback(BaseBurnCallbackParams calldata params) external; struct BaseBurnSingleCallbackParams { address sender; address to; address tokenIn; address tokenOut; uint balance0; uint balance1; uint liquidity; uint totalSupply; uint amount0; uint amount1; uint amountOut; uint amountSwapped; uint feeIn; uint24 swapFee; uint8 withdrawMode; bytes callbackData; } function syncSwapBaseBurnSingleCallback(BaseBurnSingleCallbackParams calldata params) external; struct BaseSwapCallbackParams { address sender; address to; address tokenIn; address tokenOut; uint reserve0; uint reserve1; uint balance0; uint balance1; uint amountIn; uint amountOut; uint feeIn; uint24 swapFee; uint8 withdrawMode; bytes callbackData; } function syncSwapBaseSwapCallback(BaseSwapCallbackParams calldata params) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IOwnable { function owner() external view returns (address); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IWETH { function deposit() external payable; function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function withdraw(uint) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; /// @notice The manager contract to control fees. /// Management functions are omitted. interface IFeeManager { function getSwapFee( address pool, address sender, address tokenIn, address tokenOut, bytes calldata data ) external view returns (uint24); function getProtocolFee(address pool) external view returns (uint24); function getFeeRecipient() external view returns (address); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IFeeManager.sol"; /// @notice The manager contract to control fees. /// Management functions are omitted. interface IFeeManagerV2 is IFeeManager { struct FeeData { uint64 gamma; uint24 minFee; uint24 maxFee; } function getSwapFeeData( address pool, address sender, address tokenIn, address tokenOut, bytes calldata data ) external view returns (FeeData memory); function getSwapFeeHook() external view returns (address); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IFeeRecipient { /// @dev Notifies the fee recipient after sent fees. function notifyFees( uint16 feeType, address token, uint amount, uint feeRate, bytes calldata data ) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IForwarderRegistry { function isForwarder(address forwarder) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IFeeManager.sol"; import "./IForwarderRegistry.sol"; /// @dev The master contract to create pools and manage whitelisted factories. /// Inheriting the fee manager interface to support fee queries. interface IPoolMaster is IFeeManager, IForwarderRegistry { event SetFactoryWhitelisted(address indexed factory, bool whitelisted); event RegisterPool( address indexed factory, address indexed pool, uint16 indexed poolType, bytes data ); event UpdateForwarderRegistry(address indexed newForwarderRegistry); event UpdateFeeManager(address indexed newFeeManager); function wETH() external view returns (address); function vault() external view returns (address); function feeManager() external view returns (address); function pools(uint) external view returns (address); function poolsLength() external view returns (uint); // Forwarder Registry function setForwarderRegistry(address) external; // Fees function setFeeManager(address) external; // Factories function isFactoryWhitelisted(address) external view returns (bool); function setFactoryWhitelisted(address factory, bool whitelisted) external; // Pools function isPool(address) external view returns (bool); function getPool(bytes32) external view returns (address); function createPool(address factory, bytes calldata data) external returns (address pool); function registerPool(address pool, uint16 poolType, bytes calldata data, address token0, address token1) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IPool.sol"; import "../token/IERC20Permit2.sol"; interface IBasePool is IPool, IERC20Permit2 { function token0() external view returns (address); function token1() external view returns (address); function reserve0() external view returns (uint); function reserve1() external view returns (uint); function invariantLast() external view returns (uint); function getReserves() external view returns (uint, uint); function getAmountOut(address tokenIn, uint amountIn, address sender) external view returns (uint amountOut); function getAmountIn(address tokenOut, uint amountOut, address sender) external view returns (uint amountIn); event Mint( address indexed sender, uint amount0, uint amount1, uint liquidity, address indexed to ); event Burn( address indexed sender, uint amount0, uint amount1, uint liquidity, address indexed to ); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync( uint reserve0, uint reserve1 ); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IBasePool.sol"; interface IBasePoolV2 is IBasePool { function poolVersion() external view returns (uint); function sync() external; event MintProtocolFee( address indexed feeRecipient, uint24 protocolFee, uint liquidity, uint totalSupply ); event Swapped( address indexed sender, address indexed user, address indexed tokenOut, uint amountIn, uint amountOut, uint24 swapFee, address to ); event Fee( uint amount0, uint amount1 ); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IBasePoolV2.sol"; import {ICryptoMath} from "../../pool/crypto/ICryptoMath.sol"; import {IPoolFlashLoan} from "./IPoolFlashLoan.sol"; interface ICryptoPool is IBasePoolV2, IPoolFlashLoan { //function wETH() external view returns (address); // private immutable function factory() external view returns(address); function token0PrecisionMultiplier() external view returns (uint); function token1PrecisionMultiplier() external view returns (uint); struct PoolParams { uint32 initialA; uint32 futureA; uint64 initialGamma; uint64 futureGamma; uint32 initialTime; /// @dev Time when ramping is finished. /// This value is 0 (default) when pool is first deployed, and only gets /// populated in `rampParams` when the ramping process is initiated. /// After ramping is finished (i.e. futureParamsTime < block.timestamp), /// the variable is left and not set to 0. uint32 futureTime; } struct RebalancingParams { uint64 allowedExtraProfit; uint64 adjustmentStep; uint32 maTime; uint16 requiredProfit; uint8 checkLastProfit; } function getParams() external view returns (uint a, uint gamma, uint futureTime); function priceScale() external view returns (uint); function cachedPriceOracle() external view returns (uint); function lastPrices() external view returns (uint); function lastPricesTimestamp() external view returns (uint); function virtualPrice() external view returns (uint); function xcpProfit() external view returns (uint); function xcpProfitLast() external view returns (uint); //function poolVersion() external view returns(uint); function poolType() external view returns(uint16); function MATH() external view returns(ICryptoMath); function invariantLast() external view returns(uint); //function poolParams() external view returns(PoolParams memory); //function rebalancingParams() external view returns(RebalancingParams memory); function calculateSingleWithdrawAmount(address _sender,uint a,uint gamma,uint liquidity,bool isToken0Out,bool updateInvariant) external view returns (uint, uint, uint, uint, uint24); function getVirtualPrice() external view returns(uint); //function getLiquidityPrice() external view returns (uint); function getPriceOracle() external returns (uint); function rampParams(uint32 _futureA, uint64 _futureGamma, uint32 _futureTime) external; function stopRampParams() external; function setRebalancingParams(uint64 _allowedExtraProfit, uint64 _adjustmentStep, uint32 _maTime, uint16 _requiredProfit, uint8 _checkLastProfit) external; function claimProtocolFee() external; function updateCryptoMath() external; function skim(address to) external; // Pausable.sol - removed //function paused() external view returns (bool); //function setPaused(bool _status) external; //function owner() external view returns (address); //function transferOwnership(address newOwner) external; event RampParams( uint currentA, uint futureA, uint currentGamma, uint futureGamma, uint currentTime, uint futureTime ); event StopRampParams( uint currentA, uint currentGamma, uint stopTime ); event SetRebalancingParams( uint allowedExtraProfit, uint adjustmentStep, uint maTime, uint requiredProfit, uint checkLastProfit ); event UpdatePoolProfit( uint xcpProfit, uint virtualPrice ); event UpdateInvariant( uint newInvariant ); event UpdatePriceScale( uint newPriceScale ); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IPool { struct TokenAmount { address token; uint amount; } /// @dev Returns the address of pool master. function master() external view returns (address); /// @dev Returns the vault. function vault() external view returns (address); /// @dev Returns the pool type. function poolType() external view returns (uint16); /// @dev Returns the assets of the pool. function getAssets() external view returns (address[] memory assets); /// @dev Returns the swap fee of the pool. function getSwapFee(address sender, address tokenIn, address tokenOut, bytes calldata data) external view returns (uint24 swapFee); /// @dev Returns the protocol fee of the pool. function getProtocolFee() external view returns (uint24 protocolFee); /// @dev Mints liquidity. function mint( bytes calldata data, address sender, address callback, bytes calldata callbackData ) external returns (uint liquidity); /// @dev Burns liquidity. function burn( bytes calldata data, address sender, address callback, bytes calldata callbackData ) external returns (TokenAmount[] memory tokenAmounts); /// @dev Burns liquidity with single output token. function burnSingle( bytes calldata data, address sender, address callback, bytes calldata callbackData ) external returns (TokenAmount memory tokenAmount); /// @dev Swaps between tokens. function swap( bytes calldata data, address sender, address callback, bytes calldata callbackData ) external returns (TokenAmount memory tokenAmount); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "../vault/IERC3156FlashLender.sol"; interface IPoolFlashLoan is IERC3156FlashLender { /** * @dev Emitted for each individual flash loan performed by `flashLoan`. */ event FlashLoan(address indexed recipient, address indexed token, uint amount, uint feeAmount); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IERC165 { /// @notice Query if a contract implements an interface /// @param interfaceID The interface identifier, as specified in ERC-165 /// @dev Interface identification is specified in ERC-165. This function /// uses less than 30,000 gas. /// @return `true` if the contract implements `interfaceID` and /// `interfaceID` is not 0xffffffff, `false` otherwise function supportsInterface(bytes4 interfaceID) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IERC20Base.sol"; interface IERC20 is IERC20Base { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IERC20Base { function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint amount) external returns (bool); function transfer(address to, uint amount) external returns (bool); function transferFrom(address from, address to, uint amount) external returns (bool); event Approval(address indexed owner, address indexed spender, uint amount); event Transfer(address indexed from, address indexed to, uint amount); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IERC20.sol"; interface IERC20Permit is IERC20 { function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; function nonces(address owner) external view returns (uint); function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IERC20Permit.sol"; interface IERC20Permit2 is IERC20Permit { function permit2(address owner, address spender, uint amount, uint deadline, bytes calldata signature) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IERC3156FlashBorrower { /** * @dev Receive a flash loan. * @param initiator The initiator of the loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @param fee The additional amount of tokens to repay. * @param data Arbitrary data structure, intended to contain user-defined parameters. * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" */ function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IERC3156FlashBorrower.sol"; interface IERC3156FlashLender { /** * @dev The amount of currency available to be lent. * @param token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan( address token ) external view returns (uint256); /** * @dev The fee to be charged for a given loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee( address token, uint256 amount ) external view returns (uint256); /** * @dev Initiate a flash loan. * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. * @param token The loan currency. * @param amount The amount of tokens lent. * @param data Arbitrary data structure, intended to contain user-defined parameters. */ function flashLoan( IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data ) external returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IFlashLoanRecipient.sol"; import "./IERC3156FlashLender.sol"; interface IFlashLoan is IERC3156FlashLender { function flashLoanFeePercentage() external view returns (uint); /** * @dev Performs a 'flash loan', sending tokens to `recipient`, executing the `receiveFlashLoan` hook on it, * and then reverting unless the tokens plus a proportional protocol fee have been returned. * * The `tokens` and `amounts` arrays must have the same length, and each entry in these indicates the loan amount * for each token contract. `tokens` must be sorted in ascending order. * * The 'userData' field is ignored by the Vault, and forwarded as-is to `recipient` as part of the * `receiveFlashLoan` call. * * Emits `FlashLoan` events. */ function flashLoanMultiple( IFlashLoanRecipient recipient, address[] memory tokens, uint[] memory amounts, bytes memory userData ) external; /** * @dev Emitted for each individual flash loan performed by `flashLoan`. */ event FlashLoan(address indexed recipient, address indexed token, uint amount, uint feeAmount); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.7.0 <0.9.0; // Inspired by Aave Protocol's IFlashLoanReceiver. interface IFlashLoanRecipient { /** * @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient. * * At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this * call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the * Vault, or else the entire flash loan will revert. * * `userData` is the same value passed in the `IVault.flashLoan` call. */ function receiveFlashLoan( address[] memory tokens, uint[] memory amounts, uint[] memory feeAmounts, bytes memory userData ) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IFlashLoan.sol"; interface IVault is IFlashLoan { function wETH() external view returns (address); function reserves(address token) external view returns (uint reserve); function balanceOf(address token, address owner) external view returns (uint balance); function deposit(address token, address to) external payable returns (uint amount); function depositETH(address to) external payable returns (uint amount); function transferAndDeposit(address token, address to, uint amount) external payable returns (uint); function transfer(address token, address to, uint amount) external; function withdraw(address token, address to, uint amount) external; function withdrawAlternative(address token, address to, uint amount, uint8 mode) external; function withdrawETH(address to, uint amount) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. * * Based on OpenZeppelin's ECDSA library. * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/561d1061fc568f04c7a65853538e834a889751e8/contracts/utils/cryptography/ECDSA.sol */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length if (signature.length != 65) { return address(0); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return address(0); } return ecrecover(hash, v, r, s); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "../interfaces/token/IERC165.sol"; import "../interfaces/token/IERC20Permit2.sol"; import "./SignatureChecker.sol"; error Expired(); error InvalidSignature(); /** * @dev A simple ERC20 implementation for pool's liquidity token, supports permit by both ECDSA signatures from * externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like Argent. * * Based on Solmate's ERC20. * https://github.com/transmissions11/solmate/blob/bff24e835192470ed38bf15dbed6084c2d723ace/src/tokens/ERC20.sol */ contract ERC20Permit2 is IERC165, IERC20Permit2 { uint8 public immutable override decimals = 18; uint public override totalSupply; mapping(address => uint) public override balanceOf; mapping(address => mapping(address => uint)) public override allowance; bytes32 private constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)") mapping(address => uint) public override nonces; // These members are actually immutable as // `_initialize` will only indent to be called once. string public override name; string public override symbol; uint private INITIAL_CHAIN_ID; bytes32 private INITIAL_DOMAIN_SEPARATOR; function _initialize(string memory _name, string memory _symbol) internal { name = _name; symbol = _symbol; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator(); } function supportsInterface(bytes4 interfaceID) external pure override returns (bool) { return interfaceID == this.supportsInterface.selector || // ERC-165 interfaceID == this.permit.selector || // ERC-2612 interfaceID == this.permit2.selector; // Permit2 } function DOMAIN_SEPARATOR() public view override returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : _computeDomainSeparator(); } function _computeDomainSeparator() private view returns (bytes32) { return keccak256( abi.encode( // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, keccak256(bytes(name)), // keccak256(bytes("1")) 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6, block.chainid, address(this) ) ); } function _approve(address _owner, address _spender, uint _amount) private { allowance[_owner][_spender] = _amount; emit Approval(_owner, _spender, _amount); } function approve(address _spender, uint _amount) public override returns (bool) { _approve(msg.sender, _spender, _amount); return true; } function transfer(address _to, uint _amount) public override returns (bool) { balanceOf[msg.sender] -= _amount; // Cannot overflow because the sum of all user balances can't exceed the max uint256 value. unchecked { balanceOf[_to] += _amount; } emit Transfer(msg.sender, _to, _amount); return true; } function transferFrom(address _from, address _to, uint _amount) public override returns (bool) { uint256 _allowed = allowance[_from][msg.sender]; // Saves gas for limited approvals. if (_allowed != type(uint).max) { allowance[_from][msg.sender] = _allowed - _amount; } balanceOf[_from] -= _amount; // Cannot overflow because the sum of all user balances can't exceed the max uint256 value. unchecked { balanceOf[_to] += _amount; } emit Transfer(_from, _to, _amount); return true; } function _mint(address _to, uint _amount) internal { totalSupply += _amount; // Cannot overflow because the sum of all user balances can't exceed the max uint256 value. unchecked { balanceOf[_to] += _amount; } emit Transfer(address(0), _to, _amount); } function _burn(address _from, uint _amount) internal { balanceOf[_from] -= _amount; // Cannot underflow because a user's balance will never be larger than the total supply. unchecked { totalSupply -= _amount; } emit Transfer(_from, address(0), _amount); } modifier ensures(uint _deadline) { // solhint-disable-next-line not-rely-on-time if (block.timestamp > _deadline) { revert Expired(); } _; } function _permitHash( address _owner, address _spender, uint _amount, uint _deadline ) private returns (bytes32) { return keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_TYPEHASH, _owner, _spender, _amount, nonces[_owner]++, _deadline)) ) ); } function permit( address _owner, address _spender, uint _amount, uint _deadline, uint8 _v, bytes32 _r, bytes32 _s ) public override ensures(_deadline) { bytes32 _hash = _permitHash(_owner, _spender, _amount, _deadline); address _recoveredAddress = ecrecover(_hash, _v, _r, _s); if (_recoveredAddress != _owner) { revert InvalidSignature(); } if (_recoveredAddress == address(0)) { revert InvalidSignature(); } _approve(_owner, _spender, _amount); } function permit2( address _owner, address _spender, uint _amount, uint _deadline, bytes calldata _signature ) public override ensures(_deadline) { bytes32 _hash = _permitHash(_owner, _spender, _amount, _deadline); if (!SignatureChecker.isValidSignatureNow(_owner, _hash, _signature)) { revert InvalidSignature(); } _approve(_owner, _spender, _amount); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; /// @dev Math functions. /// @dev Modified from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) library Math { function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } function sqrtInt(uint256 x) internal pure returns (uint256) { if (x == 0) { return 0; } uint z = (x + 1e18) / 2; uint y = x; for (uint i; i < 256; ) { if (z == y) { return y; } y = z; z = (x * 1e18 / z + z) / 2; unchecked { ++i; } } revert(); } function geometricMean(uint a, uint b) internal pure returns (uint) { return Math.sqrt(a * b); } /// @notice Compares a and b and returns 'true' if the difference between a and b /// is less than 1 or equal to each other. /// @param a uint256 to compare with. /// @param b uint256 to compare with. function within1(uint256 a, uint256 b) internal pure returns (bool) { unchecked { if (a > b) { return a - b <= 1; } return b - a <= 1; } } /// @dev Returns the square root of `x`. function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // Let `y = x / 2**r`. // We check `y >= 2**(k + 8)` but shift right by `k` bits // each branch to ensure that if `x >= 256`, then `y >= 256`. let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffffff, shr(r, x)))) z := shl(shr(1, r), z) // Goal was to get `z*z*y` within a small factor of `x`. More iterations could // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`. // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small. // That's not possible if `x < 256` but we can just verify those cases exhaustively. // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`. // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`. // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps. // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)` // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`, // with largest error when `s = 1` and when `s = 256` or `1/256`. // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`. // Then we can estimate `sqrt(y)` using // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`. // There is no overflow risk here since `y < 2**136` after the first branch above. z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If `x+1` is a perfect square, the Babylonian method cycles between // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } // Mul Div /// @dev Rounded down. function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } /// @dev Rounded down. /// This function assumes that `x` is not zero, and must be checked externally. /// Reverts if x is zero. function mulDivUnsafeFirst( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x * y) / x == y) if iszero(and(iszero(iszero(denominator)), eq(div(z, x), y))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } /// @dev Rounded down. /// This function assumes that `denominator` is not zero, and must be checked externally. /// This allows x to be zero. function mulDivUnsafeLast( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(x == 0 || (x * y) / x == y) if iszero(or(iszero(x), eq(div(z, x), y))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } /// @dev Rounded down. /// This function assumes that both `x` and `denominator` are not zero, and must be checked externally. /// Reverts if x is zero. function mulDivUnsafeFirstLast( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require((x * y) / x == y) if iszero(eq(div(z, x), y)) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } // Mul /// @dev Optimized safe multiplication operation for minimal gas cost. /// Equivalent to * function mul( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(x == 0 || (x * y) / x == y) if iszero(or(iszero(x), eq(div(z, x), y))) { revert(0, 0) } } } /// @dev Optimized unsafe multiplication operation for minimal gas cost. /// This function assumes that `x` is not zero, and must be checked externally. /// Reverts if x is zero. function mulUnsafeFirst( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require((x * y) / x == y) if iszero(eq(div(z, x), y)) { revert(0, 0) } } } function mulUnsafe( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) } } // Div /// @dev Optimized safe division operation for minimal gas cost. /// Equivalent to / function div( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { // Store x / y in z for now. z := div(x, y) // Equivalent to require(y != 0) if iszero(y) { revert(0, 0) } } } /// @dev Optimized unsafe division operation for minimal gas cost. /// Division by 0 will not reverts and returns 0, and must be checked externally. function divUnsafeLast( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { z := div(x, y) } } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; library MetadataHelper { /** * @dev Returns symbol of the token. * * @param token The address of a ERC20 token. * * Return boolean indicating the status and the symbol as string; * * NOTE: Symbol is not the standard interface and some tokens may not support it. * Calling against these tokens will not success, with an empty result. */ function getSymbol(address token) internal view returns (bool, string memory) { // bytes4(keccak256(bytes("symbol()"))) (bool success, bytes memory returndata) = token.staticcall(abi.encodeWithSelector(0x95d89b41)); if (success) { return (true, abi.decode(returndata, (string))); } else { return (false, ""); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { /// @dev Public to allow external contracts to read the status. uint256 public reentrantStatus = 1; /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(reentrantStatus == 1); // Any calls to nonReentrant after this point will fail reentrantStatus = 2; _; reentrantStatus = 1; } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like * Argent and Gnosis Safe. * * Based on OpenZeppelin's SignatureChecker library. * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/561d1061fc568f04c7a65853538e834a889751e8/contracts/utils/cryptography/SignatureChecker.sol */ library SignatureChecker { bytes4 constant internal MAGICVALUE = 0x1626ba7e; // bytes4(keccak256("isValidSignature(bytes32,bytes)") /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (address recovered) = ECDSA.recover(hash, signature); if (recovered == signer) { if (recovered != address(0)) { return true; } } (bool success, bytes memory result) = signer.staticcall( abi.encodeWithSelector(MAGICVALUE, hash, signature) ); return ( success && result.length == 32 && abi.decode(result, (bytes32)) == bytes32(MAGICVALUE) ); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /// @dev 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, uint value ) internal { // bytes4(keccak256(bytes("approve(address,uint256)"))); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); if (!success || (data.length != 0 && !abi.decode(data, (bool)))) { revert ApproveFailed(); } } function safeTransfer( address token, address to, uint value ) internal { // bytes4(keccak256(bytes("transfer(address,uint256)"))); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); if (!success || (data.length != 0 && !abi.decode(data, (bool)))) { revert TransferFailed(); } } function safeTransferFrom( address token, address from, address to, uint value ) internal { // bytes4(keccak256(bytes("transferFrom(address,address,uint256)"))); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); if (!success || (data.length != 0 && !abi.decode(data, (bool)))) { revert TransferFromFailed(); } } function safeTransferETH(address to, uint value) internal { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = to.call{value: value}(""); if (!success) { revert ETHTransferFailed(); } } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; /// @dev Unchecked math functions. contract UnsafeMath { function unsafe_div(uint x, uint y) internal pure returns (uint z) { assembly { z := div(x, y) } } function unsafe_mul(uint a, uint b) internal pure returns (uint) { unchecked { return a * b; } } function unsafe_sub(uint a, uint b) internal pure returns (uint) { unchecked { return a - b; } } function unsafe_add(uint a, uint b) internal pure returns (uint) { unchecked { return a + b; } } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; interface ICryptoMath { function getY( uint a, uint gamma, uint x0, uint x1, uint d, uint i ) external view returns (uint y, uint k0_prev); function computeD( uint a, uint gamma, uint xp0, uint xp1, uint k0_prev ) external view returns (uint); function getLastPrices( uint a, uint gamma, uint xp0, uint xp1, uint d, uint priceScale ) external view returns (uint); function getPriceOracle( uint lastTimestamp, uint maTime, uint lastPrices, uint priceScale, uint priceOracle ) external view returns (uint); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; interface ICryptoView { function getAmountOut( address pool, address tokenIn, uint amountIn, address sender, bytes memory feeData ) external view returns (uint); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "../interfaces/token/IERC20.sol"; import "../interfaces/master/IFeeRecipient.sol"; import "../interfaces/master/IPoolMaster.sol"; import "../interfaces/pool/IPoolFlashLoan.sol"; import "../libraries/ReentrancyGuard.sol"; import "../libraries/TransferHelper.sol"; /** * @dev Handles Flash Loans through the Pool. */ abstract contract PoolFlashLoans is IPoolFlashLoan, ReentrancyGuard { uint private constant FLASH_LOAN_FEE = 5e15; // 0.5% bytes32 private constant ERC3156_CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); /** * @dev Returns the protocol fee amount to charge for a flash loan of `amount`. */ function _calculateFlashLoanFeeAmount(uint amount) private pure returns (uint) { return amount * FLASH_LOAN_FEE / 1e18; } function _payFeeAmount(address token, uint amount) private { if (amount != 0) { address _feeRecipient = _getFeeRecipient(); if (_feeRecipient != address(0)) { TransferHelper.safeTransfer(token, _feeRecipient, amount); IFeeRecipient(_feeRecipient).notifyFees(10, token, amount, FLASH_LOAN_FEE, abi.encode(2)); } } } function _getFeeRecipient() internal virtual view returns (address) {} // EIP-3156 Implementations /** * @dev The amount of currency available to be lent. * @param token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan(address token) external view override returns (uint256) { return IERC20(token).balanceOf(address(this)); } /** * @dev The fee to be charged for a given loan. * @param amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee(address /*token*/, uint256 amount) external pure override returns (uint256) { return _calculateFlashLoanFeeAmount(amount); } /** * @dev Initiate a flash loan. * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. * @param token The loan currency. * @param amount The amount of tokens lent. * @param userData Arbitrary data structure, intended to contain user-defined parameters. */ function flashLoan( IERC3156FlashBorrower receiver, address token, uint amount, bytes memory userData ) external override nonReentrant returns (bool) { uint preLoanBalance = IERC20(token).balanceOf(address(this)); uint feeAmount = _calculateFlashLoanFeeAmount(amount); require(preLoanBalance >= amount, "INSUFFICIENT_FLASH_LOAN_BALANCE"); TransferHelper.safeTransfer(token, address(receiver), amount); require( receiver.onFlashLoan(msg.sender, token, amount, feeAmount, userData) == ERC3156_CALLBACK_SUCCESS, "IERC3156_CALLBACK_FAILED" ); // Checking for loan repayment first (without accounting for fees) makes for simpler debugging, and results // in more accurate revert reasons if the flash loan protocol fee percentage is zero. uint postLoanBalance = IERC20(token).balanceOf(address(this)); require(postLoanBalance >= preLoanBalance, "INVALID_POST_LOAN_BALANCE"); // No need for checked arithmetic since we know the loan was fully repaid. uint receivedFeeAmount = postLoanBalance - preLoanBalance; require(receivedFeeAmount >= feeAmount, "INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT"); _payFeeAmount(token, receivedFeeAmount); emit FlashLoan(address(receiver), token, amount, receivedFeeAmount); return true; } }
{ "viaIR": false, "optimizer": { "enabled": true, "runs": 200, "details": { "yul": false } }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"Loss","type":"error"},{"inputs":[],"name":"Overflow","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Fee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"uint24","name":"swapFee","type":"uint24"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"Swapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reserve1","type":"uint256"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newInvariant","type":"uint256"}],"name":"UpdateInvariant","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"xcpProfit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"virtualPrice","type":"uint256"}],"name":"UpdatePoolProfit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newPriceScale","type":"uint256"}],"name":"UpdatePriceScale","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MATH","outputs":[{"internalType":"contract ICryptoMath","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cachedPriceOracle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint256","name":"_reserve0","type":"uint256"},{"internalType":"uint256","name":"_reserve1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"invariantLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPrices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPricesTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"master","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"permit2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolParams","outputs":[{"internalType":"uint32","name":"initialA","type":"uint32"},{"internalType":"uint32","name":"futureA","type":"uint32"},{"internalType":"uint64","name":"initialGamma","type":"uint64"},{"internalType":"uint64","name":"futureGamma","type":"uint64"},{"internalType":"uint32","name":"initialTime","type":"uint32"},{"internalType":"uint32","name":"futureTime","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolType","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancingParams","outputs":[{"internalType":"uint64","name":"allowedExtraProfit","type":"uint64"},{"internalType":"uint64","name":"adjustmentStep","type":"uint64"},{"internalType":"uint32","name":"maTime","type":"uint32"},{"internalType":"uint16","name":"requiredProfit","type":"uint16"},{"internalType":"uint8","name":"checkLastProfit","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reentrantStatus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_callback","type":"address"},{"internalType":"bytes","name":"_callbackData","type":"bytes"}],"name":"swap","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SyncSwapCryptoPoolDelegated.TokenAmount","name":"_tokenAmount","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0PrecisionMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1PrecisionMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"virtualPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xcpProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xcpProfitLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Deployed Bytecode
0x60806040526004361061021e5760003560e01c806391e4bb3411610123578063d21220a7116100ab578063e3bba7161161006f578063e3bba71614610846578063e7231d241461085c578063ed6c154614610872578063ee97f7f31461089f578063fbfa77cf146108bf57610225565b8063d21220a71461078f578063d505accf146107c3578063d6ea073d146107e3578063da815731146107f9578063dd62ed3e1461080e57610225565b8063a9059cbb116100f2578063a9059cbb14610682578063b1dd61b6146106a2578063baa8c7cb146106c4578063bc4041db146106f8578063c45a01551461075b57610225565b806391e4bb341461062b57806395d89b411461064157806396e591a614610656578063a0fbddaf1461066c57610225565b80632c0198cc116101a65780634e25dc47116101755780634e25dc471461055a57806370a082311461058e5780637132bb7f146105bb5780637ecebe00146105e85780638ea875f31461061557610225565b80632c0198cc146104ce578063313ce567146104ee5780633644e5151461052f578063370a48671461054457610225565b8063095ea7b3116101ed578063095ea7b3146103cb5780630dfe1681146103eb57806318160ddd1461042c57806319706b381461044257806323b872dd146104ae57610225565b806301ffc9a71461031e57806306fdde031461035457806307f293f7146103765780630902f1ac1461039957610225565b3661022557005b7f000000000000000000000000fb35c48001bdb59edd14012dee73f202f53977f063f66eab5b60e01b6001600160e01b031960003516148061027957506313d85e7560e11b6001600160e01b031960003516145b806102965750631f2f232f60e11b6001600160e01b031960003516145b806102b3575063712d52fd60e11b6001600160e01b031960003516145b806102d05750631f94a27560e31b6001600160e01b031960003516145b156102f857507f0000000000000000000000006275cb52518217602a1869dbd6e7e8196455e3945b3660008037600080366000845af43d6000803e808015610317573d6000f35b3d6000fd5b005b34801561032a57600080fd5b5061033e610339366004612dc7565b6108df565b60405161034b9190612df2565b60405180910390f35b34801561036057600080fd5b50610369610931565b60405161034b9190612e56565b34801561038257600080fd5b5061038c600e5481565b60405161034b9190612e6d565b3480156103a557600080fd5b50600d546001600160801b0380821691600160801b90041660405161034b929190612e7b565b3480156103d757600080fd5b5061033e6103e6366004612ecc565b6109bf565b3480156103f757600080fd5b5061041f7f00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a481565b60405161034b9190612f12565b34801561043857600080fd5b5061038c60005481565b34801561044e57600080fd5b5060165461049c9063ffffffff8082169164010000000081048216916001600160401b03600160401b8304811692600160801b810490911691600160c01b8204811691600160e01b90041686565b60405161034b96959493929190612f3b565b3480156104ba57600080fd5b5061033e6104c9366004612f8a565b6109d5565b3480156104da57600080fd5b5061031c6104e936600461302b565b610ac7565b3480156104fa57600080fd5b506105227f000000000000000000000000000000000000000000000000000000000000001281565b60405161034b91906130c9565b34801561053b57600080fd5b5061038c610b6c565b34801561055057600080fd5b5061038c60145481565b34801561056657600080fd5b5061038c7f000000000000000000000000000000000000000000000000000000000000000181565b34801561059a57600080fd5b5061038c6105a93660046130d7565b60016020526000908152604090205481565b3480156105c757600080fd5b506105db6105d63660046131f1565b610b8b565b60405161034b91906132ac565b3480156105f457600080fd5b5061038c6106033660046130d7565b60036020526000908152604090205481565b34801561062157600080fd5b5061038c60135481565b34801561063757600080fd5b5061038c60125481565b34801561064d57600080fd5b50610369611216565b34801561066257600080fd5b5061038c60155481565b34801561067857600080fd5b5061038c600f5481565b34801561068e57600080fd5b5061033e61069d366004612ecc565b611223565b3480156106ae57600080fd5b506106b7600381565b60405161034b91906132c4565b3480156106d057600080fd5b5061038c7f000000000000000000000000000000000000000000000000000000e8d4a5100081565b34801561070457600080fd5b5060175461074a906001600160401b0380821691600160401b810490911690600160801b810463ffffffff1690600160a01b810461ffff1690600160b01b900460ff1685565b60405161034b9594939291906132d2565b34801561076757600080fd5b5061041f7f00000000000000000000000087aeb51d606056f48d241c4072f55acd9d93701881565b34801561079b57600080fd5b5061041f7f000000000000000000000000530000000000000000000000000000000000000481565b3480156107cf57600080fd5b5061031c6107de366004613328565b6112aa565b3480156107ef57600080fd5b5061038c60085481565b34801561080557600080fd5b5061038c600281565b34801561081a57600080fd5b5061038c6108293660046133c7565b600260209081526000928352604080842090915290825290205481565b34801561085257600080fd5b5061038c60115481565b34801561086857600080fd5b5061038c60105481565b34801561087e57600080fd5b50600c54610892906001600160a01b031681565b60405161034b919061343c565b3480156108ab57600080fd5b50600b5461041f906001600160a01b031681565b3480156108cb57600080fd5b50600a5461041f906001600160a01b031681565b60006001600160e01b031982166301ffc9a760e01b148061091057506001600160e01b0319821663d505accf60e01b145b8061092b57506001600160e01b03198216630b00663360e21b145b92915050565b6004805461093e90613460565b80601f016020809104026020016040519081016040528092919081815260200182805461096a90613460565b80156109b75780601f1061098c576101008083540402835291602001916109b7565b820191906000526020600020905b81548152906001019060200180831161099a57829003601f168201915b505050505081565b60006109cc33848461139f565b50600192915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120546000198114610a3157610a0c83826134a2565b6001600160a01b03861660009081526002602090815260408083203384529091529020555b6001600160a01b03851660009081526001602052604081208054859290610a599084906134a2565b90915550506001600160a01b03808516600081815260016020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610ab2908790612e6d565b60405180910390a360019150505b9392505050565b8280421115610ae957604051630407b05b60e31b815260040160405180910390fd5b6000610af788888888611407565b9050610b3a888286868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114c192505050565b610b5757604051638baa579f60e01b815260040160405180910390fd5b610b6288888861139f565b5050505050505050565b60006006544614610b8457610b7f6115ed565b905090565b5060075490565b6040805180820190915260008082526020820152600854600114610bae57600080fd5b6002600881905550610c54604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b85806020019051810190610c6891906134cb565b60ff166101808401526001600160a01b039081166020840152166040820152600d546001600160801b03600160801b8204811660a0840152166080820152610cae611676565b60e083015260c0820152610cc18561179c565b94506000806000610cd061183b565b600c54604088015193965091945092506000918291829182916001600160a01b03908116917f00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a48216911603610e9857610d846040518061012001604052808f6001600160a01b031681526020018a81526020018981526020018b60c0015181526020018b60e0015181526020018b6080015181526020018b60a001518152602001600115158152602001888152508261196e565b62ffffff9094166101608f01526101208e018590526001600160a01b037f00000000000000000000000053000000000000000000000000000000000000041660608f015260e08e018051929a50909850929650909450610de59083906134a2565b905250608089015160c08a0151610dfc91906134a2565b6101008a0181905260208a01516101208b01516040516001600160a01b039092169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d82292610e5192916000918291613526565b60405180910390a37fa6205f24a082c01e6c705e20c1a026c246eedf9800b87b84440f05e8271aaf27600083604051610e8b929190613564565b60405180910390a1611051565b7f00000000000000000000000053000000000000000000000000000000000000046001600160a01b031689604001516001600160a01b031614610eda57600080fd5b610f3f6040518061012001604052808f6001600160a01b031681526020018a81526020018981526020018b60c0015181526020018b60e0015181526020018b6080015181526020018b60a001518152602001600015158152602001888152508261196e565b62ffffff9094166101608f01526101208e018590526001600160a01b037f00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a41660608f015260c08e018051929a50909850929650909450610fa09083906134a2565b90525060a089015160e08a0151610fb791906134a2565b6101008a0181905260208a01516101208b01516040516001600160a01b039092169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229261100e926000929091908390613572565b60405180910390a37fa6205f24a082c01e6c705e20c1a026c246eedf9800b87b84440f05e8271aaf278260006040516110489291906135a7565b60405180910390a15b61010089015115801590611069575061012089015115155b61107257600080fd5b6110838888878760008b8988611ea7565b50506110978960c001518a60e001516125fa565b6110b589606001518a602001518b61012001518c61018001516126b3565b6001600160a01b038c161561115c576001600160a01b038d1689526101a089018b90526101008901516101608a01516110f7919062ffffff16620186a06127f8565b6101408a015260405163608dbcbb60e01b81526001600160a01b038d169063608dbcbb90611129908c906004016136ea565b600060405180830381600087803b15801561114357600080fd5b505af1158015611157573d6000803e3d6000fd5b505050505b88606001518a600001906001600160a01b031690816001600160a01b0316815250508861012001518a602001818152505088606001516001600160a01b03168d6001600160a01b0316336001600160a01b03167faa077b6dc26efdfd606d4340c04a5a222ff968ec199f0b184f4c0f7a5c8e8d718c61010001518d61012001518e61016001518f602001516040516111f794939291906136fb565b60405180910390a45050600160085550959a9950505050505050505050565b6005805461093e90613460565b336000908152600160205260408120805483919083906112449084906134a2565b90915550506001600160a01b038316600081815260016020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611299908690612e6d565b60405180910390a350600192915050565b83804211156112cc57604051630407b05b60e31b815260040160405180910390fd5b60006112da89898989611407565b90506000600182878787604051600081526020016040526040516113019493929190613730565b6020604051602081039080840390855afa158015611323573d6000803e3d6000fd5b505050602060405103519050896001600160a01b0316816001600160a01b03161461136157604051638baa579f60e01b815260040160405180910390fd5b6001600160a01b03811661138857604051638baa579f60e01b815260040160405180910390fd5b6113938a8a8a61139f565b50505050505050505050565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906113fa908590612e6d565b60405180910390a3505050565b6000611411610b6c565b6001600160a01b038616600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c99289928992899290919061145f83613758565b919050558760405160200161147996959493929190613772565b604051602081830303815290604052805190602001206040516020016114a09291906137c1565b6040516020818303038152906040528051906020012090505b949350505050565b6000806114ce8484612810565b9050846001600160a01b0316816001600160a01b031603611502576001600160a01b03811615611502576001915050610ac0565b600080866001600160a01b0316631626ba7e60e01b878760405160240161152a9291906137f2565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516115689190613834565b600060405180830381855afa9150503d80600081146115a3576040519150601f19603f3d011682016040523d82523d6000602084013e6115a8565b606091505b50915091508180156115bb575080516020145b80156115e257508051630b135d3f60e11b906115e0908301602090810190840161384b565b145b979650505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f600460405161161f91906138de565b60405190819003812061165b92917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc690469030906020016138ea565b60405160208183030381529060405280519060200120905090565b6000807f00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a46001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016116c59190612f12565b602060405180830381865afa1580156116e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611706919061384b565b6040516370a0823160e01b81529092506001600160a01b037f000000000000000000000000530000000000000000000000000000000000000416906370a0823190611755903090600401612f12565b602060405180830381865afa158015611772573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611796919061384b565b90509091565b60006001600160a01b038216331461183457600b54604051632af3bd5560e21b81526001600160a01b039091169063abcef554906117de903390600401612f12565b602060405180830381865afa925050508015611817575060408051601f3d908101601f191682019092526118149181019061393f565b60015b611822575033919050565b8061182d5733610ac0565b5090919050565b5033919050565b6040805160c08101825260165463ffffffff808216835264010000000082048116602084018190526001600160401b03600160401b8404811695850195909552600160801b830490941660608401819052600160c01b830482166080850152600160e01b9092041660a08301819052909142821115611968576000816080015163ffffffff16836118cc91906134a2565b90506000826080015163ffffffff16426118e691906134a2565b905060006118f482846134a2565b9050826119018389613960565b855161191490849063ffffffff16613960565b61191e919061397f565b61192891906139a8565b9650826119358388613960565b8286604001516001600160401b031661194e9190613960565b611958919061397f565b61196291906139a8565b95505050505b50909192565b6000806000806000806119a96040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000e8d4a5100089606001516119d99190613960565b8152600f54611a09907f000000000000000000000000000000000000000000000000000000000000000190613960565b6060820181905260808a0151611a2791670de0b6b3a76400006128c3565b6020820152610100890151421015611b63578860e0015115611afb5760a08901517f000000000000000000000000000000000000000000000000000000e8d4a5100002608082018190526020808b01516040808d0151928501519051636ca4fd9160e11b81526001600160a01b038d169463d949fb2294611ab0949390926000906004016139bc565b602060405180830381865afa158015611acd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af1919061384b565b6040820152611b6c565b611b1d611b0f8a60c0015183606001510290565b670de0b6b3a7640000900490565b6080820181905260208a01516040808c015184519151636ca4fd9160e11b81526001600160a01b038d169463d949fb2294611ab0949093929091906000906004016139bc565b600e5460408201525b8860e0015115611cfc576020808a01516040808c0151845193850151858301519251631a63711f60e01b81526001600160a01b038e1695631a63711f95611bbd9590949391926001906004016139fe565b6040805180830381865afa158015611bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bfd9190613a4d565b608083018290526020830151909350611c1691906134a2565b96508681602001818151611c2a91906134a2565b905250611c386001886134a2565b9650611c51670de0b6b3a76400008883606001516128d7565b9650611cac89600001517f00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a47f0000000000000000000000005300000000000000000000000000000000000004846000015185602001516128ec565b9550611cc18662ffffff1688620186a06128c3565b9450611ccd85886134a2565b965080600001519350611cf5611b0f888b60c00151611cec91906134a2565b83606001510290565b9250611e9c565b6020808a01516040808c0151845193850151858301519251631a63711f60e01b81526001600160a01b038e1695631a63711f95611d439590949391926000906004016139fe565b6040805180830381865afa158015611d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d839190613a4d565b608083018290528251909350611d9991906134a2565b96508681600001818151611dad91906134a2565b905250611dbb6001886134a2565b8951825160208401517f000000000000000000000000000000000000000000000000000000e8d4a510009093049950611e37927f0000000000000000000000005300000000000000000000000000000000000004917f00000000000000000000000006efdbff2a14a7c8e15944d1f4a48f9f95f663a4916128ec565b9550611e4c8662ffffff1688620186a06128c3565b9450611e5885886134a2565b9650611e92878a60a00151611e6d91906134a2565b7f000000000000000000000000000000000000000000000000000000e8d4a510000290565b9350806020015192505b509295509295509295565b600080611f00604051806101400160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805160a0810182526017546001600160401b038082168352600160401b820416602080840191909152600160801b820463ffffffff1693830193909352600160a01b810461ffff16606080840191909152600160b01b90910460ff1660808084019190915260105493850193909352600f5484526012549084018190526000549284019290925260135460e08401529042111561202d576060820151604080830151601154855160208701519351634180db7360e11b81526001600160a01b038b1695638301b6e695611fdd95919491939192600401613a9b565b602060405180830381865afa158015611ffa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201e919061384b565b60208301819052601055426012555b876000036120ad57604051636ca4fd9160e11b81526001600160a01b0386169063d949fb2290612069908f908f908f908f908d90600401613add565b602060405180830381865afa158015612086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120aa919061384b565b97505b846001600160a01b0316630b994d458d8d8d8d8d88600001516040518763ffffffff1660e01b81526004016120e796959493929190613af8565b602060405180830381865afa158015612104573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612128919061384b565b60115560e08201516000908190156121de5760028a049150612161670de0b6b3a76400008b61215c60028860000151612925565b6128d7565b9050612183670de0b6b3a76400006121798484612936565b86608001516128d7565b60c085018190526014546121a49161219a91613960565b8560e00151900490565b60a0850152428910156121d9578360e001518460c00151116121d95760405163b50754c160e01b815260040160405180910390fd5b6121f4565b670de0b6b3a764000060a0850181905260c08501525b60a084015160145560c0840151670de0b6b3a76400001080156122225750670de0b6b3a76400008460a00151115b801561228a575061226a836060015161ffff16670de0b6b3a764000085600001516001600160401b03168760a0015161225b919061397f565b61226591906134a2565b612925565b612288612710670de0b6b3a76400008760c0015161226591906134a2565b115b1561255f576122aa670de0b6b3a7640000856020015186600001516128d7565b6101208501819052670de0b6b3a764000010156122da5761012084018051670de0b6b3a763ffff190190526122ee565b61012084018051670de0b6b3a76400000390525b61231483602001516001600160401b031661230f8661012001516005900490565b6129d1565b985088846101200151111561255f5761236084602001518a6123369190613960565b6101208601518b9003865161234b9190613960565b612355919061397f565b856101200151900490565b98508b91506123748b8a86600001516128c3565b9050866001600160a01b031663d949fb228f8f858560006040518663ffffffff1660e01b81526004016123ab9594939291906139bc565b602060405180830381865afa1580156123c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ec919061384b565b61010085018190526002808204935061241391670de0b6b3a76400009161215c908d612925565b905061242b670de0b6b3a76400006121798484612936565b60e08501819052670de0b6b3a7640000101561255f57612465836060015161ffff16670de0b6b3a76400008660a0015161226591906134a2565b612483612710670de0b6b3a76400008760e0015161226591906134a2565b111561255f57600f8990556040517fcb12ab4101e9e15b90a22516ca404e94b85586dbdcf7d0792ab8da11206e61b6906124be908b90612e6d565b60405180910390a1610100840151600e8190556040517f9e4e1b03f35e9c0cd24e1dfac3528faaaf88b254e1530b0090ce33f9d7597033916124ff91612e6d565b60405180910390a160e0840151601381905560a08501516040517f4d2cbcbcdaca7676a354e7297481cf51e67a13c8c07ad1c42928605c8ea522d0926125459291612e7b565b60405180910390a1505050610100015191508490506125ed565b600e8a90556040517f9e4e1b03f35e9c0cd24e1dfac3528faaaf88b254e1530b0090ce33f9d759703390612594908c90612e6d565b60405180910390a160c0840151601381905560a08501516040517f4d2cbcbcdaca7676a354e7297481cf51e67a13c8c07ad1c42928605c8ea522d0926125da9291612e7b565b60405180910390a1505090518793509150505b9850989650505050505050565b6001600160801b0382111561262257604051631a93c68960e11b815260040160405180910390fd5b6001600160801b0381111561264a57604051631a93c68960e11b815260040160405180910390fd5b6001600160801b03808316908216600160801b026fffffffffffffffffffffffffffffffff191617600d556040517fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a906126a79084908490612e7b565b60405180910390a15050565b8060ff1660000361275157600a546126d69085906001600160a01b0316846129e0565b600a54604051631f2c13e160e31b81526001600160a01b039091169063f9609f08906127089087908790600401613b20565b6020604051808303816000875af1158015612727573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274b919061384b565b506127f2565b8060ff16600114801561277157506009546001600160a01b038581169116145b156127e757600954604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d906127a6908590600401612e6d565b600060405180830381600087803b1580156127c057600080fd5b505af11580156127d4573d6000803e3d6000fd5b505050506127e28383612ad3565b6127f2565b6127f28484846129e0565b50505050565b828202838104831461280957600080fd5b0492915050565b600081516041146128235750600061092b565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612869576000935050505061092b565b6001868285856040516000815260200160405260405161288c9493929190613730565b6020604051602081039080840390855afa1580156128ae573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b828202831584820484141761280957600080fd5b82820281151584820484141661280957600080fd5b600061291b8686868686336040516020016129079190612f12565b604051602081830303815290604052612b55565b9695505050505050565b818102828104821461092b57600080fd5b6000610ac06129458385613960565b70ffffffffffffffffffffffffffffffffff811160071b81811c68ffffffffffffffffff1060061b1781811c64ffffffffff1060051b1781811c62ffffff1060041b1781811c620100000160b5600192831c1b0260121c80830401811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b600081831161182d5781610ac0565b600080846001600160a01b031663a9059cbb8585604051602401612a05929190613b3b565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051612a3e9190613834565b6000604051808303816000865af19150503d8060008114612a7b576040519150601f19603f3d011682016040523d82523d6000602084013e612a80565b606091505b5091509150811580612aae5750805115801590612aae575080806020019051810190612aac919061393f565b155b15612acc576040516312171d8360e31b815260040160405180910390fd5b5050505050565b6000826001600160a01b031682604051612aec90613b49565b60006040518083038185875af1925050503d8060008114612b29576040519150601f19603f3d011682016040523d82523d6000602084013e612b2e565b606091505b5050905080612b505760405163b12d13eb60e01b815260040160405180910390fd5b505050565b600080612b6488888886612c5e565b90506000612b72858761397f565b9050612ba58582612b8b89673782dace9d900000613960565b612b9591906139a8565b612b9f9190613960565b82900490565b8251612bc1906001600160401b0316670de0b6b3a76400000190565b612bcb91906134a2565b8251612be7906001600160401b0316670de0b6b3a76400000290565b612bf191906139a8565b9050612c3b612c0882670de0b6b3a76400006134a2565b836040015162ffffff16612c1c9190613960565b82846020015162ffffff16612c319190613960565b611b0f919061397f565b9250614e2062ffffff84161115612c5257614e2092505b50509695505050505050565b6040805160608101825260008082526020820181905291810191909152600b546040805163d0fb020360e01b815290516000926001600160a01b03169163d0fb02039160048083019260209291908290030181865afa925050508015612ce1575060408051601f3d908101601f19168201909252612cde91810190613b54565b60015b15612ce95790505b6001600160a01b03811615612d7357604051635a59621b60e11b81526001600160a01b0382169063b4b2c43690612d2c9030908a908a908a908a90600401613b75565b606060405180830381865afa925050508015612d65575060408051601f3d908101601f19168201909252612d6291810190613c4a565b60015b15612d735791506114b99050565b50506040805160608101825265d12f0c4c6000815261010460208201526101c291810191909152949350505050565b6001600160e01b031981165b8114612db957600080fd5b50565b803561092b81612da2565b600060208284031215612ddc57612ddc600080fd5b60006114b98484612dbc565b8015155b82525050565b6020810161092b8284612de8565b60005b83811015612e1b578181015183820152602001612e03565b50506000910152565b6000612e2e825190565b808452602084019350612e45818560208601612e00565b601f01601f19169290920192915050565b60208082528101610ac08184612e24565b80612dec565b6020810161092b8284612e67565b60408101612e898285612e67565b610ac06020830184612e67565b60006001600160a01b03821661092b565b612dae81612e96565b803561092b81612ea7565b80612dae565b803561092b81612ebb565b60008060408385031215612ee257612ee2600080fd5b6000612eee8585612eb0565b9250506020612eff85828601612ec1565b9150509250929050565b612dec81612e96565b6020810161092b8284612f09565b63ffffffff8116612dec565b6001600160401b038116612dec565b60c08101612f498289612f20565b612f566020830188612f20565b612f636040830187612f2c565b612f706060830186612f2c565b612f7d6080830185612f20565b6115e260a0830184612f20565b600080600060608486031215612fa257612fa2600080fd5b6000612fae8686612eb0565b9350506020612fbf86828701612eb0565b9250506040612fd086828701612ec1565b9150509250925092565b60008083601f840112612fef57612fef600080fd5b5081356001600160401b0381111561300957613009600080fd5b60208301915083600182028301111561302457613024600080fd5b9250929050565b60008060008060008060a0878903121561304757613047600080fd5b60006130538989612eb0565b965050602061306489828a01612eb0565b955050604061307589828a01612ec1565b945050606061308689828a01612ec1565b93505060808701356001600160401b038111156130a5576130a5600080fd5b6130b189828a01612fda565b92509250509295509295509295565b60ff8116612dec565b6020810161092b82846130c0565b6000602082840312156130ec576130ec600080fd5b60006114b98484612eb0565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681018181106001600160401b0382111715613133576131336130f8565b6040525050565b600061314560405190565b9050613151828261310e565b919050565b60006001600160401b0382111561316f5761316f6130f8565b601f19601f83011660200192915050565b82818337506000910152565b600061319f61319a84613156565b61313a565b9050828152602081018484840111156131ba576131ba600080fd5b6131c5848285613180565b509392505050565b600082601f8301126131e1576131e1600080fd5b81356114b984826020860161318c565b6000806000806080858703121561320a5761320a600080fd5b84356001600160401b0381111561322357613223600080fd5b61322f878288016131cd565b945050602061324087828801612eb0565b935050604061325187828801612eb0565b92505060608501356001600160401b0381111561327057613270600080fd5b61327c878288016131cd565b91505092959194509250565b805160408301906132998482612f09565b5060208201516127f26020850182612e67565b6040810161092b8284613288565b61ffff8116612dec565b6020810161092b82846132ba565b60a081016132e08288612f2c565b6132ed6020830187612f2c565b6132fa6040830186612f20565b61330760608301856132ba565b61291b60808301846130c0565b60ff8116612dae565b803561092b81613314565b600080600080600080600060e0888a03121561334657613346600080fd5b60006133528a8a612eb0565b97505060206133638a828b01612eb0565b96505060406133748a828b01612ec1565b95505060606133858a828b01612ec1565b94505060806133968a828b0161331d565b93505060a06133a78a828b01612ec1565b92505060c06133b88a828b01612ec1565b91505092959891949750929550565b600080604083850312156133dd576133dd600080fd5b60006133e98585612eb0565b9250506020612eff85828601612eb0565b600061092b6001600160a01b038316613411565b90565b6001600160a01b031690565b600061092b826133fa565b600061092b8261341d565b612dec81613428565b6020810161092b8284613433565b634e487b7160e01b600052602260045260246000fd5b60028104600182168061347457607f821691505b6020821081036134865761348661344a565b50919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561092b5761092b61348c565b805161092b81612ea7565b805161092b81613314565b6000806000606084860312156134e3576134e3600080fd5b60006134ef86866134b5565b9350506020613500868287016134b5565b9250506040612fd0868287016134c0565b600061092b61340e8381565b612dec81613511565b608081016135348287612e67565b613541602083018661351d565b61354e604083018561351d565b61355b6060830184612e67565b95945050505050565b60408101612e89828561351d565b60808101613580828761351d565b61358d6020830186612e67565b61359a6040830185612e67565b61355b606083018461351d565b604081016135b58285612e67565b610ac0602083018461351d565b62ffffff8116612dec565b80516000906101c08401906135e28582612f09565b5060208301516135f56020860182612f09565b5060408301516136086040860182612f09565b50606083015161361b6060860182612f09565b50608083015161362e6080860182612e67565b5060a083015161364160a0860182612e67565b5060c083015161365460c0860182612e67565b5060e083015161366760e0860182612e67565b5061010083015161367c610100860182612e67565b50610120830151613691610120860182612e67565b506101408301516136a6610140860182612e67565b506101608301516136bb6101608601826135c2565b506101808301516136d06101808601826130c0565b506101a08301518482036101a086015261355b8282612e24565b60208082528101610ac081846135cd565b608081016137098287612e67565b6137166020830186612e67565b61372360408301856135c2565b61355b6060830184612f09565b6080810161373e8287612e67565b61374b60208301866130c0565b61354e6040830185612e67565b6000600019820361376b5761376b61348c565b5060010190565b60c081016137808289612e67565b61378d6020830188612f09565b61379a6040830187612f09565b6137a76060830186612e67565b6137b46080830185612e67565b6115e260a0830184612e67565b61190160f01b815260020160006137d88285612e67565b6020820191506137e88284612e67565b5060200192915050565b604081016138008285612e67565b81810360208301526114b98184612e24565b600061381c825190565b61382a818560208601612e00565b9290920192915050565b6000610ac08284613812565b805161092b81612ebb565b60006020828403121561386057613860600080fd5b60006114b98484613840565b6000815461387981613460565b60018216801561389057600181146138a5576138d5565b60ff19831686528115158202860193506138d5565b60008581526020902060005b838110156138cd578154888201526001909101906020016138b1565b838801955050505b50505092915050565b6000610ac0828461386c565b60a081016138f8828861351d565b6139056020830187612e67565b613912604083018661351d565b61391f6060830185612e67565b61291b6080830184612f09565b801515612dae565b805161092b8161392c565b60006020828403121561395457613954600080fd5b60006114b98484613934565b8181028082158382048514176139785761397861348c565b5092915050565b8082018082111561092b5761092b61348c565b634e487b7160e01b600052601260045260246000fd5b6000826139b7576139b7613992565b500490565b60a081016139ca8288612e67565b6139d76020830187612e67565b6139e46040830186612e67565b6139f16060830185612e67565b61291b608083018461351d565b60c08101613a0c8289612e67565b613a196020830188612e67565b613a266040830187612e67565b613a336060830186612e67565b613a406080830185612e67565b6115e260a083018461351d565b60008060408385031215613a6357613a63600080fd5b6000613a6f8585613840565b9250506020612eff85828601613840565b600061092b61340e63ffffffff841681565b612dec81613a80565b60a08101613aa98288612e67565b613ab66020830187613a92565b613ac36040830186612e67565b613ad06060830185612e67565b61291b6080830184612e67565b60a08101613aeb8288612e67565b613ab66020830187612e67565b60c08101613b068289612e67565b613b136020830188612e67565b61379a6040830187612e67565b60408101613b2e8285612f09565b610ac06020830184612f09565b60408101612e898285612f09565b600061092b8261340e565b600060208284031215613b6957613b69600080fd5b60006114b984846134b5565b60a08101613b838288612f09565b613b906020830187612f09565b613b9d6040830186612f09565b613baa6060830185612f09565b81810360808301526115e28184612e24565b6001600160401b038116612dae565b805161092b81613bbc565b62ffffff8116612dae565b805161092b81613bd6565b600060608284031215613c0157613c01600080fd5b613c0b606061313a565b90506000613c198484613bcb565b8252506020613c2a84848301613be1565b6020830152506040613c3e84828501613be1565b60408301525092915050565b600060608284031215613c5f57613c5f600080fd5b60006114b98484613bec56fea26469706673582212205a3b4e80d15975bd20f118e243514e3ab79a5f6321e693c77b65d55eeb5c8a7464736f6c63430008170033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
SCROLL | 100.00% | $0.999931 | 36,799.7274 | $36,797.19 |
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.