编译器
0.8.17+commit.8df45f5f
文件 1 的 18:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 18:CryptoSwap2Pool.sol
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "./interfaces/ICryptoPoolToken.sol";
import "./interfaces/ICryptoSwap2Pool.sol";
import "./interfaces/IKokonutSwapExchangeCallback.sol";
import "./library/ReentrancyGuard.sol";
import "./utils/ZKokonutAccess.sol";
import "./interfaces/ICryptoSwapFactory.sol";
contract CryptoSwap2Pool is ICryptoSwap2Pool, ReentrancyGuard, ZKokonutAccess {
using SafeERC20 for IERC20;
uint256 internal constant _ADMIN_ACTIONS_DELAY = 3 * 86400;
uint256 internal constant _MIN_RAMP_TIME = 86400;
uint256 internal constant _MAX_ADMIN_FEE = 10 * 10 ** 9;
uint256 internal constant _MIN_FEE = 5 * 10 ** 5;
uint256 internal constant _MAX_FEE = 5 * 10 ** 9;
uint256 internal constant _MAX_A_CHANGE = 10;
uint256 internal constant _NOISE_FEE = 10 ** 5;
uint256 internal constant _MIN_GAMMA = 10 ** 10;
uint256 internal constant _MAX_GAMMA = 2 * 10 ** 16;
uint256 internal constant _MIN_A = (N_COINS ** N_COINS * _A_MULTIPLIER) / 10;
uint256 internal constant _MAX_A = N_COINS ** N_COINS * _A_MULTIPLIER * 100000;
uint256 public constant override N_COINS = 2;
uint256 internal constant _PRECISION_PRICE_SCALE = 10 ** 18;
uint256 internal constant _PRECISION_EXP = 10 ** 10;
uint256 internal constant _PRECISION_FEE = 10 ** 10;
uint256 internal constant _A_MULTIPLIER = 10000;
address internal immutable _factory;
address public immutable override token;
address internal immutable _coin0;
address internal immutable _coin1;
uint256 internal immutable _PRECISION_COIN0;
uint256 internal immutable _PRECISION_COIN1;
uint256 public override priceScale;
uint256 internal _PriceOracle;
uint256 public override lastPrices;
uint256 public override lastPricesTimestamp;
uint32 public override initialA;
uint32 public override futureA;
uint64 public override initialGamma;
uint64 public override futureGamma;
uint32 public override initialAGammaTime;
uint32 public override futureAGammaTime;
uint256 public override allowedExtraProfit;
uint256 public override futureAllowedExtraProfit;
uint256 public override minRemainingPostRebalanceRatio;
uint256 public override futureRebalancingThreshold;
uint256 public override feeGamma;
uint256 public override futureFeeGamma;
uint256 public override adjustmentStep;
uint256 public override futureAdjustmentStep;
uint256 public override maHalfTime;
uint256 public override futureMaHalfTime;
uint256 public override midFee;
uint256 public override outFee;
uint256 public override adminFee;
uint256 public override flashLoanFee;
uint256 public override futureMidFee;
uint256 public override futureOutFee;
uint256 public override futureAdminFee;
uint256 public override futureFlashLoanFee;
uint256[N_COINS] public override balances;
uint256 public override D;
uint256 public override xcpProfit;
uint256 public override xcpProfitA;
uint256 public override virtualPrice;
bool internal _notAdjusted;
uint256 public override adminActionsDeadline;
modifier readOnlyNonReentrant() {
_checkReadOnlyNonReentrant();
_;
}
function _checkReadOnlyNonReentrant() internal view {
require(!reentrancyGuardEntered(), "Reentrant");
}
constructor(InitializeArgs memory args, address token_, address owner_, address factory_) {
_initializeZKokonutAccess(owner_);
_factory = factory_;
initialA = args.A;
initialGamma = args.gamma;
futureA = args.A;
futureGamma = args.gamma;
midFee = args.midFee;
outFee = args.outFee;
allowedExtraProfit = args.allowedExtraProfit;
minRemainingPostRebalanceRatio = args.minRemainingPostRebalanceRatio;
feeGamma = args.feeGamma;
adjustmentStep = args.adjustmentStep;
adminFee = args.adminFee;
flashLoanFee = args.flashLoanFee;
priceScale = args.initialPrice;
_PriceOracle = args.initialPrice;
lastPrices = args.initialPrice;
lastPricesTimestamp = block.timestamp;
maHalfTime = args.maHalfTime;
xcpProfitA = 10 ** 18;
token = token_;
_coin0 = args.coins[0];
_coin1 = args.coins[1];
_PRECISION_COIN0 = 10 ** (18 - _getDecimals(args.coins[0]));
_PRECISION_COIN1 = 10 ** (18 - _getDecimals(args.coins[1]));
}
function _getDecimals(address tokenAddress) internal view returns (uint256) {
return IERC20Metadata(tokenAddress).decimals();
}
function _AGamma() internal view returns (uint256 mA, uint256 mGamma) {
unchecked {
uint256 t1 = futureAGammaTime;
mA = futureA;
mGamma = futureGamma;
if (block.timestamp < t1) {
uint256 t0 = initialAGammaTime;
t1 -= t0;
t0 = block.timestamp - t0;
uint256 t2 = t1 - t0;
mA = (initialA * t2 + mA * t0) / t1;
mGamma = (initialGamma * t2 + mGamma * t0) / t1;
}
}
}
function _standardize(uint256 x, uint256 y) internal view returns (uint256[N_COINS] memory result) {
result[0] = x * _PRECISION_COIN0;
result[1] = (y * _PRECISION_COIN1 * priceScale) / _PRECISION_PRICE_SCALE;
return result;
}
function _unStandardize(uint256 standardizedAmount, uint256 i) internal view returns (uint256) {
return
i == 0
? standardizedAmount / _PRECISION_COIN0
: (standardizedAmount * _PRECISION_PRICE_SCALE) / _PRECISION_COIN1 / priceScale;
}
function _feeRate(uint256[N_COINS] memory xp) internal view returns (uint256) {
uint256 feeGamma_ = feeGamma;
uint256 f = xp[0] + xp[1];
f =
(feeGamma_ * 10 ** 18) /
(feeGamma_ + 10 ** 18 - ((((10 ** 18 * N_COINS ** N_COINS) * xp[0]) / f) * xp[1]) / f);
return (midFee * f + outFee * (10 ** 18 - f)) / 10 ** 18;
}
function _getXcp(uint256 _D) internal view returns (uint256) {
uint256[N_COINS] memory x;
unchecked {
x[0] = _D / N_COINS;
x[1] = (_D * _PRECISION_PRICE_SCALE) / (priceScale * N_COINS);
}
return _geometricMean(x, true);
}
function _halfpow(uint256 power) internal pure returns (uint256) {
uint256 intpow = power / 10 ** 18;
uint256 otherpow = power - intpow * 10 ** 18;
if (intpow > 59) {
return 0;
}
uint256 result = 10 ** 18 / (2 ** intpow);
if (otherpow == 0) {
return result;
}
uint256 term = 10 ** 18;
uint256 S = 10 ** 18;
bool neg = false;
for (uint256 i = 1; i < 256; ++i) {
uint256 K = i * 10 ** 18;
uint256 c = K - 10 ** 18;
if (otherpow > c) {
c = otherpow - c;
neg = !neg;
} else {
c -= otherpow;
}
term = (term * (c / 2)) / K;
if (neg) {
S -= term;
} else {
S += term;
}
if (term < _PRECISION_EXP) {
return (result * S) / 10 ** 18;
}
}
revert("C");
}
function _sqrtInt(uint256 x) internal pure returns (uint256) {
if (x == 0) {
return 0;
}
uint256 z = (x + 10 ** 18) / 2;
uint256 y = x;
for (uint256 i = 0; i < 256; ++i) {
if (z == y) {
return y;
}
y = z;
z = ((x * 10 ** 18) / z + z) / 2;
}
revert("C");
}
function _calcTokenFeeRate(
uint256[N_COINS] memory xp0,
uint256[N_COINS] memory xp1
) internal view returns (uint256) {
uint256 feeRate = _feeRate(xp1);
uint256 sum = 0;
uint256 diff = 0;
uint256[N_COINS] memory amounts;
unchecked {
for (uint256 i = 0; i < N_COINS; ++i) {
amounts[i] = xp1[i] - xp0[i];
sum += amounts[i];
require(sum >= amounts[i]);
}
uint256 avg = sum / N_COINS;
for (uint256 i = 0; i < N_COINS; ++i) {
diff += (amounts[i] > avg) ? amounts[i] - avg : avg - amounts[i];
}
feeRate = (feeRate * N_COINS) / (4 * (N_COINS - 1));
}
return (feeRate * diff) / sum + _NOISE_FEE;
}
function _calcWithdrawOneCoin(
uint256 tokenAmount,
uint256 i,
uint256[N_COINS] memory xp0
) internal view returns (uint256 dy, uint256 lpFee, uint256 D1, uint256[N_COINS] memory xp1) {
require(i < N_COINS);
uint256 tokenSupply = _lpTotalSupply();
xp1 = _arrCopy(xp0);
(uint256 mA, uint256 mGamma) = _AGamma();
require(tokenAmount <= tokenSupply);
uint256 D0 = futureAGammaTime > 0 ? _newtonD(mA, mGamma, xp1) : D;
uint256 y;
unchecked {
lpFee = (_feeRate(xp1) * tokenAmount) / (2 * _PRECISION_FEE) + 1;
D1 = D0 - (D0 * (tokenAmount - lpFee)) / tokenSupply;
y = _newtonY(mA, mGamma, xp1[1 - i], D1);
}
dy = _unStandardize(xp1[i] - y, i);
xp1[i] = y;
}
function _arrCopy(uint256[N_COINS] memory _input) internal pure returns (uint256[N_COINS] memory result) {
unchecked {
for (uint256 i = 0; i < N_COINS; ++i) {
result[i] = _input[i];
}
}
}
function _claimAdminFee() internal {
(uint256 mA, uint256 mGamma) = _AGamma();
uint256 _xcpProfit = xcpProfit;
uint256 _xcpProfitA = xcpProfitA;
uint256 _minRemainingPostRebalanceRatio = minRemainingPostRebalanceRatio;
unchecked {
for (uint256 i = 0; i < N_COINS; ++i) {
balances[i] = _thisBalanceOf(_coins(i));
}
}
uint256 vprice = virtualPrice;
if (_xcpProfit > _xcpProfitA) {
uint256 fees;
unchecked {
fees = ((_xcpProfit - _xcpProfitA) * adminFee) / _PRECISION_FEE;
}
if (fees > 0) {
address receiver = ICryptoSwapFactory(_factory).getFeeReceiver();
if (receiver != address(0)) {
uint256 frac = (vprice * 10 ** 18) /
(vprice - (fees * _minRemainingPostRebalanceRatio) / _PRECISION_FEE) -
10 ** 18;
uint256 claimed = ICryptoPoolToken(token).mintRelative(receiver, frac);
_xcpProfit -= fees;
xcpProfit = _xcpProfit;
emit ClaimAdminFee(receiver, claimed);
}
}
}
D = _newtonD(mA, mGamma, _standardize(balances[0], balances[1]));
virtualPrice = (10 ** 18 * _getXcp(D)) / _lpTotalSupply();
if (_xcpProfit > _xcpProfitA) {
xcpProfitA = _xcpProfit;
}
}
function _tweakPrice(uint256 mA, uint256 mGamma, uint256[N_COINS] memory xp, uint256 newD) internal {
uint256 oldPriceScale = priceScale;
uint256 newPriceOracle = _PriceOracle;
uint256 lastPrices_ = lastPrices;
{
uint256 lastPricesTimestamp_ = lastPricesTimestamp;
if (lastPricesTimestamp_ < block.timestamp) {
uint256 alpha = _halfpow(((block.timestamp - lastPricesTimestamp_) * 10 ** 18) / maHalfTime);
uint256 price = Math.max(Math.min(lastPrices_, 2 * oldPriceScale), oldPriceScale / 2);
newPriceOracle = (price * (10 ** 18 - alpha) + newPriceOracle * alpha) / 10 ** 18;
_PriceOracle = newPriceOracle;
lastPricesTimestamp = block.timestamp;
}
if (newD == 0) {
newD = _newtonD(mA, mGamma, xp);
}
lastPrices_ = _getPrice(1, mA, mGamma, xp, newD);
lastPrices = lastPrices_;
}
uint256 oldVirtualPrice = virtualPrice;
uint256[N_COINS] memory mXp;
mXp[0] = newD / N_COINS;
mXp[1] = (newD * _PRECISION_PRICE_SCALE) / (N_COINS * oldPriceScale);
uint256 newXcpProfit = 10 ** 18;
uint256 newVirtualPrice = 10 ** 18;
if (oldVirtualPrice > 0) {
newVirtualPrice = (10 ** 18 * _geometricMean(mXp, true)) / _lpTotalSupply();
newXcpProfit = (xcpProfit * newVirtualPrice) / oldVirtualPrice;
uint256 t = futureAGammaTime;
if (newVirtualPrice < oldVirtualPrice && t == 0) {
revert("Loss");
}
if (t == 1) {
futureAGammaTime = 0;
}
}
xcpProfit = newXcpProfit;
uint256 norm = (newPriceOracle * 10 ** 18) / oldPriceScale;
unchecked {
if (norm > 10 ** 18) {
norm -= 10 ** 18;
} else {
norm = 10 ** 18 - norm;
}
}
uint256 mAdjustmentStep = Math.max(adjustmentStep, norm / 5);
bool needsAdjustment = _notAdjusted;
if (
!needsAdjustment &&
(newVirtualPrice - 10 ** 18 >
((newXcpProfit - 10 ** 18) * minRemainingPostRebalanceRatio) / _PRECISION_FEE + allowedExtraProfit) &&
(norm > mAdjustmentStep) &&
(oldVirtualPrice > 0)
) {
needsAdjustment = true;
_notAdjusted = true;
}
if (needsAdjustment) {
if (norm > mAdjustmentStep && oldVirtualPrice > 0) {
lastPrices_ = (oldPriceScale * (norm - mAdjustmentStep) + mAdjustmentStep * newPriceOracle) / norm;
mXp[0] = xp[0];
mXp[1] = (xp[1] * lastPrices_) / oldPriceScale;
uint256 _D = _newtonD(mA, mGamma, mXp);
mXp[0] = _D / N_COINS;
mXp[1] = (_D * _PRECISION_PRICE_SCALE) / (N_COINS * lastPrices_);
oldVirtualPrice = (10 ** 18 * _geometricMean(mXp, true)) / _lpTotalSupply();
if (
(oldVirtualPrice > 10 ** 18) &&
(oldVirtualPrice - 10 ** 18 >
((newXcpProfit - 10 ** 18) * minRemainingPostRebalanceRatio) / _PRECISION_FEE)
) {
priceScale = lastPrices_;
D = _D;
virtualPrice = oldVirtualPrice;
emit TweakPrice(lastPrices_, _D, oldVirtualPrice, newXcpProfit);
return;
} else {
_notAdjusted = false;
D = newD;
virtualPrice = newVirtualPrice;
_claimAdminFee();
return;
}
}
}
D = newD;
virtualPrice = newVirtualPrice;
if (needsAdjustment) {
_notAdjusted = false;
_claimAdminFee();
}
}
function _internalPriceOracle() internal view returns (uint256) {
uint256 _lastPricesTimestamp = lastPricesTimestamp;
if (_lastPricesTimestamp < block.timestamp) {
uint256 alpha = _halfpow(((block.timestamp - _lastPricesTimestamp) * 10 ** 18) / maHalfTime);
return (lastPrices * (10 ** 18 - alpha) + _PriceOracle * alpha) / 10 ** 18;
} else {
return _PriceOracle;
}
}
function exchange(
uint256 i,
uint256 j,
uint256 dx,
uint256 minDy,
bytes calldata data
) external nonReentrant whenNotPaused returns (uint256 dy, uint256 dyFee) {
require(i + j == 1);
require(dx > 0);
(uint256 mA, uint256 mGamma) = _AGamma();
if (futureAGammaTime > 0) {
D = _newtonD(mA, mGamma, _standardize(balances[0], balances[1]));
if (block.timestamp >= futureAGammaTime) {
futureAGammaTime = 1;
}
}
uint256[N_COINS] memory xp0 = balances;
uint256[N_COINS] memory xp1 = _arrCopy(xp0);
xp1[i] = xp1[i] + dx;
balances[i] = xp1[i];
xp0 = _standardize(xp0[0], xp0[1]);
xp1 = _standardize(xp1[0], xp1[1]);
dy = xp1[j] - _newtonY(mA, mGamma, xp1[i], D);
require(dy > 0);
unchecked {
xp1[j] -= dy;
dy = _unStandardize(dy - 1, j);
dyFee = (_feeRate(xp1) * dy) / _PRECISION_FEE;
dy -= dyFee;
require(dy >= minDy, "SP");
balances[j] = balances[j] - dy;
}
_transfer(_coins(j), msg.sender, dy);
if (data.length == 0) {
_pullToken(_coins(i), msg.sender, dx);
} else {
address inCoin = _coins(i);
minDy = _thisBalanceOf(inCoin);
IKokonutSwapExchangeCallback(msg.sender).onExchange(i, j, dx, dy, data);
require(_thisBalanceOf(inCoin) - minDy >= dx);
}
xp1 = _standardize(balances[0], balances[1]);
_tweakPrice(mA, mGamma, xp1, 0);
emit TokenExchange(msg.sender, i, dx, j, dy, dyFee);
}
function addLiquidity(
uint256[] calldata amounts,
uint256 minMintAmount
) external nonReentrant whenNotPaused returns (uint256 dToken, uint256 lpFee) {
require(amounts.length == N_COINS);
require(amounts[0] > 0 || amounts[1] > 0);
(uint256 mA, uint256 mGamma) = _AGamma();
uint256 D0;
if (futureAGammaTime > 0) {
D0 = _newtonD(mA, mGamma, _standardize(balances[0], balances[1]));
if (block.timestamp >= futureAGammaTime) {
futureAGammaTime = 1;
}
} else {
D0 = D;
}
uint256[N_COINS] memory xp0 = balances;
uint256[N_COINS] memory xp1 = _arrCopy(xp0);
for (uint256 i = 0; i < N_COINS; ++i) {
uint256 amount = amounts[i];
if (amount > 0) {
xp1[i] = xp1[i] + amount;
_pullToken(_coins(i), msg.sender, amount);
}
balances[i] = xp1[i];
}
xp0 = _standardize(xp0[0], xp0[1]);
xp1 = _standardize(xp1[0], xp1[1]);
uint256 D1 = _newtonD(mA, mGamma, xp1);
uint256 tokenSupply = _lpTotalSupply();
if (D0 > 0) {
dToken = (tokenSupply * D1) / D0 - tokenSupply;
} else {
dToken = _getXcp(D1);
}
require(dToken > 0);
if (D0 > 0) {
lpFee = (_calcTokenFeeRate(xp0, xp1) * dToken) / _PRECISION_FEE + 1;
dToken -= lpFee;
tokenSupply += dToken;
_mintMsgSender(dToken);
_tweakPrice(mA, mGamma, xp1, D1);
} else {
D = D1;
virtualPrice = 10 ** 18;
xcpProfit = 10 ** 18;
_mintMsgSender(dToken);
tokenSupply += dToken;
}
require(dToken >= minMintAmount, "SP");
emit AddLiquidity(msg.sender, amounts, lpFee, D1, tokenSupply);
}
function removeLiquidity(
uint256 amount,
uint256[] calldata minAmounts
) external nonReentrant returns (uint256[] memory) {
require(minAmounts.length == N_COINS);
uint256 _totalSupply = _lpTotalSupply();
_burnMsgSender(amount);
uint256[] memory dBalances = new uint256[](N_COINS);
uint256[] memory balances_ = new uint256[](N_COINS);
unchecked {
for (uint256 i = 0; i < N_COINS; ++i) {
balances_[i] = balances[i];
uint256 dBalance = (balances_[i] * amount) / _totalSupply;
require(dBalance >= minAmounts[i]);
balances[i] = balances_[i] - dBalance;
balances_[i] = dBalance;
address coin = _coins(i);
_transfer(coin, msg.sender, dBalance);
dBalances[i] = dBalance;
}
uint256 _D = D;
D = _D - (_D * amount) / _totalSupply;
emit RemoveLiquidity(msg.sender, balances_, _totalSupply - amount);
}
return dBalances;
}
function removeLiquidityOneCoin(
uint256 tokenAmount,
uint256 i,
uint256 minAmount
) external nonReentrant whenNotPaused returns (uint256, uint256) {
uint256[N_COINS] memory xp0 = _standardize(balances[0], balances[1]);
(uint256 dy, uint256 lpFee, uint256 D1, uint256[N_COINS] memory xp1) = _calcWithdrawOneCoin(
tokenAmount,
i,
xp0
);
require(dy >= minAmount, "SP");
if (block.timestamp >= futureAGammaTime) {
futureAGammaTime = 1;
}
balances[i] -= dy;
_burnMsgSender(tokenAmount);
_transfer(_coins(i), msg.sender, dy);
(uint256 mA, uint256 mGamma) = _AGamma();
_tweakPrice(mA, mGamma, xp1, D1);
emit RemoveLiquidityOne(msg.sender, i, dy, lpFee, _lpTotalSupply());
return (dy, lpFee);
}
function claimableAdminFee() external view readOnlyNonReentrant returns (uint256) {
uint256 _xcpProfit = xcpProfit;
uint256 _xcpProfitA = xcpProfitA;
uint256 vprice = virtualPrice;
if (_xcpProfit > _xcpProfitA) {
uint256 fees = ((_xcpProfit - _xcpProfitA) * adminFee * minRemainingPostRebalanceRatio) /
(_PRECISION_FEE * _PRECISION_FEE);
if (fees > 0) {
uint256 frac = (vprice * 10 ** 18) / (vprice - fees) - 10 ** 18;
uint256 supply = _lpTotalSupply();
return (supply * frac) / 10 ** 18;
}
}
return 0;
}
function claimAdminFee() external nonReentrant {
_claimAdminFee();
}
function rampAGamma(uint32 futureA_, uint64 futureGamma_, uint32 futureTime_) external onlyOwner {
unchecked {
require(block.timestamp > initialAGammaTime + (_MIN_RAMP_TIME - 1));
require(futureTime_ > block.timestamp + (_MIN_RAMP_TIME - 1));
(uint256 mA, uint256 mGamma) = _AGamma();
require(futureA_ > _MIN_A - 1);
require(futureA_ < _MAX_A + 1);
require(futureGamma_ > _MIN_GAMMA - 1);
require(futureGamma_ < _MAX_GAMMA + 1);
uint256 ratio = (10 ** 18 * uint256(futureA_)) / mA;
require(ratio < 10 ** 18 * _MAX_A_CHANGE + 1);
require(ratio > 10 ** 18 / _MAX_A_CHANGE - 1);
ratio = (10 ** 18 * uint256(futureGamma_)) / mGamma;
require(ratio < 10 ** 18 * _MAX_A_CHANGE + 1);
require(ratio > 10 ** 18 / _MAX_A_CHANGE - 1);
initialA = uint32(mA);
initialGamma = uint64(mGamma);
initialAGammaTime = uint32(block.timestamp);
futureA = uint32(futureA_);
futureGamma = uint64(futureGamma_);
futureAGammaTime = uint32(futureTime_);
emit RampAGamma(mA, futureA_, mGamma, futureGamma_, block.timestamp, futureTime_);
}
}
function stopRampAGamma() external onlyOwner {
(uint256 mA, uint256 mGamma) = _AGamma();
initialA = uint32(mA);
initialGamma = uint64(mGamma);
futureA = uint32(mA);
futureGamma = uint64(mGamma);
initialAGammaTime = uint32(block.timestamp);
futureAGammaTime = uint32(block.timestamp);
emit StopRampA(mA, mGamma, block.timestamp);
}
function commitNewParameters(
uint256 _newMidFee,
uint256 _newOutFee,
uint256 _newAdminFee,
uint256 _newFlashLoanFee,
uint256 _newFeeGamma,
uint256 _newAllowedExtraProfit,
uint256 _newRebalancingThreshold,
uint256 _newAdjustmentStep,
uint256 _newMaHalfTime
) external onlyOwner {
unchecked {
require(adminActionsDeadline == 0);
if (_newOutFee < _MAX_FEE + 1) {
require(_newOutFee > _MIN_FEE - 1);
} else {
_newOutFee = outFee;
}
if (_newMidFee > _MAX_FEE) {
_newMidFee = midFee;
}
require(_newMidFee <= _newOutFee);
if (_newAdminFee > _MAX_ADMIN_FEE) {
_newAdminFee = adminFee;
}
if (_newFlashLoanFee > _MAX_FEE) {
_newFlashLoanFee = flashLoanFee;
}
if (_newFeeGamma < 10 ** 18) {
require(_newFeeGamma > 0);
} else {
_newFeeGamma = feeGamma;
}
if (_newAllowedExtraProfit > 10 ** 18) {
_newAllowedExtraProfit = allowedExtraProfit;
}
if (_newAdjustmentStep > 10 ** 18) {
_newAdjustmentStep = adjustmentStep;
}
if (_newRebalancingThreshold > _PRECISION_FEE) {
_newRebalancingThreshold = minRemainingPostRebalanceRatio;
} else {
require(_newRebalancingThreshold >= 2 * 10 ** 9);
}
if (_newMaHalfTime < 7 * 86400) {
require(_newMaHalfTime > 0);
} else {
_newMaHalfTime = maHalfTime;
}
uint256 _deadline = block.timestamp + _ADMIN_ACTIONS_DELAY;
adminActionsDeadline = _deadline;
futureAdminFee = _newAdminFee;
futureMidFee = _newMidFee;
futureOutFee = _newOutFee;
futureFlashLoanFee = _newFlashLoanFee;
futureFeeGamma = _newFeeGamma;
futureAllowedExtraProfit = _newAllowedExtraProfit;
futureRebalancingThreshold = _newRebalancingThreshold;
futureAdjustmentStep = _newAdjustmentStep;
futureMaHalfTime = _newMaHalfTime;
emit CommitNewParameters(
_deadline,
_newAdminFee,
_newFlashLoanFee,
_newMidFee,
_newOutFee,
_newFeeGamma,
_newAllowedExtraProfit,
_newRebalancingThreshold,
_newAdjustmentStep,
_newMaHalfTime
);
}
}
function applyNewParameters() external nonReentrant onlyOwner {
require(block.timestamp >= adminActionsDeadline);
require(adminActionsDeadline != 0);
adminActionsDeadline = 0;
uint256 adminFee_ = futureAdminFee;
if (adminFee != adminFee_) {
_claimAdminFee();
adminFee = adminFee_;
}
uint256 flashLoanFee_ = futureFlashLoanFee;
flashLoanFee = flashLoanFee_;
uint256 midFee_ = futureMidFee;
midFee = midFee_;
uint256 outFee_ = futureOutFee;
outFee = outFee_;
uint256 feeGamma_ = futureFeeGamma;
feeGamma = feeGamma_;
uint256 allowedExtraProfit_ = futureAllowedExtraProfit;
allowedExtraProfit = allowedExtraProfit_;
uint256 minRemainingPostRebalanceRatio_ = futureRebalancingThreshold;
minRemainingPostRebalanceRatio = minRemainingPostRebalanceRatio_;
uint256 adjustmentStep_ = futureAdjustmentStep;
adjustmentStep = adjustmentStep_;
uint256 maHalfTime_ = futureMaHalfTime;
maHalfTime = maHalfTime_;
emit NewParameters(
adminFee_,
flashLoanFee_,
midFee_,
outFee_,
feeGamma_,
allowedExtraProfit_,
minRemainingPostRebalanceRatio_,
adjustmentStep_,
maHalfTime_
);
}
function revertNewParameters() external onlyOwner {
adminActionsDeadline = 0;
}
function withdrawLostToken(address _target, uint256 _amount, address _to) external onlyOwner {
address[N_COINS] memory coins_ = _coins();
unchecked {
for (uint256 i = 0; i < N_COINS; ++i) {
require(coins_[i] != _target);
}
}
_transfer(_target, _to, _amount);
}
function flashLoan(
IKokonutSwapFlashCallback borrower,
uint256[] calldata amounts,
bytes calldata data
) external nonReentrant {
require(amounts.length == N_COINS);
address[N_COINS] memory coinsList = _coins();
uint256[N_COINS] memory oldBalance;
uint256[] memory fees = new uint256[](N_COINS);
uint256 currentFee = flashLoanFee;
for (uint256 i = 0; i < N_COINS; ++i) {
address coin = coinsList[i];
fees[i] = (amounts[i] * currentFee + _PRECISION_FEE - 1) / _PRECISION_FEE;
oldBalance[i] = _thisBalanceOf(coin);
if (amounts[i] > 0) {
_transfer(coin, address(borrower), amounts[i]);
}
}
borrower.onFlashLoan(msg.sender, amounts, fees, data);
for (uint256 i = 0; i < N_COINS; ++i) {
uint256 newBalance = _thisBalanceOf(coinsList[i]);
require(newBalance >= oldBalance[i] + fees[i], "flashLoan");
unchecked {
fees[i] = newBalance - oldBalance[i];
}
balances[i] += fees[i];
}
(uint256 mA, uint256 mGamma) = _AGamma();
_tweakPrice(mA, mGamma, _standardize(balances[0], balances[1]), 0);
emit FlashLoan(address(borrower), amounts, fees);
}
function getDy(
uint256 i,
uint256 j,
uint256 dx
) external view readOnlyNonReentrant returns (uint256 dy, uint256 dyFee) {
require(i + j == 1);
(uint256 mA, uint256 mGamma) = _AGamma();
uint256[N_COINS] memory xp = balances;
uint256 D0 = (futureAGammaTime > 0) ? _newtonD(mA, mGamma, _standardize(xp[0], xp[1])) : D;
xp[i] += dx;
xp = _standardize(xp[0], xp[1]);
dy = xp[j] - _newtonY(mA, mGamma, xp[i], D0);
require(dy > 0);
unchecked {
xp[j] -= dy;
dy = _unStandardize(dy - 1, j);
dyFee = (_feeRate(xp) * dy) / _PRECISION_FEE;
dy -= dyFee;
}
}
function _getPrice(
uint256 i,
uint256 mA,
uint256 mGamma,
uint256[N_COINS] memory xp,
uint256 D_
) internal view returns (uint256) {
uint256 K0 = ((((10 ** 18 * N_COINS ** N_COINS) * xp[0]) / D_) * xp[1]) / D_;
require(K0 <= 10 ** 18, "K0");
uint256 _g1k0 = mGamma + 10 ** 18 - K0;
uint256 K = (((mA * K0 * mGamma) / _g1k0) * mGamma) / _g1k0 / _A_MULTIPLIER / N_COINS ** N_COINS;
uint256 S = xp[0] + xp[1];
require(D_ <= S, "D");
uint256 mul = ((S - D_) * (mGamma + 10 ** 18 + K0)) / _g1k0 + (D_ * K0) / K / N_COINS ** N_COINS;
uint256 dxi = _PRECISION_PRICE_SCALE + (_PRECISION_PRICE_SCALE * mul) / xp[1 - i];
uint256 dxj = _PRECISION_PRICE_SCALE + (_PRECISION_PRICE_SCALE * mul) / xp[i];
if (i == 0) {
return (((_PRECISION_PRICE_SCALE * dxj) / dxi) * _PRECISION_PRICE_SCALE) / priceScale;
} else {
return (((_PRECISION_PRICE_SCALE * dxj) / dxi) * priceScale) / _PRECISION_PRICE_SCALE;
}
}
function getPrice(uint256 i, uint256 j) public view readOnlyNonReentrant returns (uint256) {
require(i + j == 1);
uint256[N_COINS] memory xp = _standardize(balances[0], balances[1]);
(uint256 mA, uint256 mGamma) = _AGamma();
uint256 D_ = futureAGammaTime > 0 ? _newtonD(mA, mGamma, xp) : D;
return _getPrice(i, mA, mGamma, xp, D_);
}
function calcDeposit(
uint256[] calldata amounts
) external view readOnlyNonReentrant returns (uint256 lpAmount, uint256 lpFee) {
require(amounts.length == N_COINS);
uint256 tokenSupply = _lpTotalSupply();
(uint256 mA, uint256 mGamma) = _AGamma();
uint256[N_COINS] memory xp0 = balances;
uint256[N_COINS] memory xp1 = _arrCopy(xp0);
xp1[0] = xp0[0] + amounts[0];
xp1[1] = xp0[1] + amounts[1];
xp0 = _standardize(xp0[0], xp0[1]);
xp1 = _standardize(xp1[0], xp1[1]);
uint256 D0 = (futureAGammaTime > 0) ? _newtonD(mA, mGamma, xp0) : D;
uint256 D1 = _newtonD(mA, mGamma, xp1);
lpAmount = (tokenSupply * D1) / D0 - tokenSupply;
lpFee = (_calcTokenFeeRate(xp0, xp1) * lpAmount) / _PRECISION_FEE + 1;
lpAmount -= lpFee;
}
function calcWithdraw(uint256 _amount) external view readOnlyNonReentrant returns (uint256[] memory amounts) {
uint256 _totalSupply = _lpTotalSupply();
uint256[N_COINS] memory balances_ = balances;
amounts = new uint256[](N_COINS);
for (uint256 i = 0; i < N_COINS; ++i) {
amounts[i] = (balances_[i] * _amount) / _totalSupply;
}
}
function calcWithdrawOneCoin(
uint256 tokenAmount,
uint256 i
) external view readOnlyNonReentrant returns (uint256 dy, uint256 lpFee) {
(dy, lpFee, , ) = _calcWithdrawOneCoin(tokenAmount, i, _standardize(balances[0], balances[1]));
}
function lpPrice() external view returns (uint256) {
return (2 * virtualPrice * _sqrtInt(_internalPriceOracle())) / 10 ** 18;
}
function A() external view returns (uint256 result) {
(result, ) = _AGamma();
}
function gamma() external view returns (uint256 result) {
(, result) = _AGamma();
}
function fee() external view readOnlyNonReentrant returns (uint256) {
return _feeRate(_standardize(balances[0], balances[1]));
}
function getVirtualPrice() external view readOnlyNonReentrant returns (uint256) {
return (10 ** 18 * _getXcp(D)) / _lpTotalSupply();
}
function priceOracle() external view returns (uint256) {
return _internalPriceOracle();
}
function coins(uint256 i) external view returns (address) {
return _coins(i);
}
function _coins() internal view returns (address[N_COINS] memory) {
return [_coin0, _coin1];
}
function _coins(uint256 i) internal view returns (address) {
if (i == 0) {
return _coin0;
} else if (i == 1) {
return _coin1;
} else {
revert();
}
}
function _lpTotalSupply() internal view returns (uint256) {
return ICryptoPoolToken(token).totalSupply();
}
function _thisBalanceOf(address coin) internal view returns (uint256) {
return IERC20(coin).balanceOf(address(this));
}
function _pullToken(address coin, address from, uint256 amount) internal {
IERC20(coin).safeTransferFrom(from, address(this), amount);
}
function _transfer(address coin, address to, uint256 amount) internal {
IERC20(coin).safeTransfer(to, amount);
}
function _geometricMean(uint256[N_COINS] memory unsortedX, bool sort) internal pure returns (uint256) {
uint256[N_COINS] memory x = _arrCopy(unsortedX);
if (sort && x[0] < x[1]) {
x[0] = unsortedX[1];
x[1] = unsortedX[0];
}
uint256 _D = x[0];
uint256 diff = 0;
for (uint256 i = 0; i < 255; ++i) {
uint256 DPrev = _D;
_D = (_D + (x[0] * x[1]) / _D) / N_COINS;
unchecked {
if (_D > DPrev) {
diff = _D - DPrev;
} else {
diff = DPrev - _D;
}
}
if (diff <= 1 || diff * 10 ** 18 < _D) {
return _D;
}
}
revert("C");
}
function _newtonD(uint256 mA, uint256 mGamma, uint256[N_COINS] memory xUnsorted) internal pure returns (uint256) {
unchecked {
require(mA > _MIN_A - 1 && mA < _MAX_A + 1);
require(mGamma > _MIN_GAMMA - 1 && mGamma < _MAX_GAMMA + 1);
}
uint256[N_COINS] memory x = _arrCopy(xUnsorted);
if (x[0] < x[1]) {
x[0] = xUnsorted[1];
x[1] = xUnsorted[0];
}
require(x[0] > 10 ** 9 - 1 && x[0] < 10 ** 15 * 10 ** 18 + 1);
require((x[1] * 10 ** 18) / x[0] > 10 ** 14 - 1);
uint256 _D = N_COINS * _geometricMean(x, false);
uint256 S = x[0] + x[1];
for (uint256 i = 0; i < 255; ++i) {
uint256 DPrev = _D;
uint256 K0 = ((((10 ** 18 * N_COINS ** 2) * x[0]) / _D) * x[1]) / _D;
uint256 _g1k0 = mGamma + 10 ** 18;
unchecked {
if (_g1k0 > K0) {
_g1k0 = _g1k0 - K0 + 1;
} else {
_g1k0 = K0 - _g1k0 + 1;
}
}
uint256 mul1 = (((((10 ** 18 * _D) / mGamma) * _g1k0) / mGamma) * _g1k0 * _A_MULTIPLIER) / mA;
uint256 mul2 = ((2 * 10 ** 18) * N_COINS * K0) / _g1k0;
uint256 negFprime = (S + (S * mul2) / 10 ** 18) + (mul1 * N_COINS) / K0 - (mul2 * _D) / 10 ** 18;
uint256 D_plus = (_D * (negFprime + S)) / negFprime;
uint256 D_minus = (_D * _D) / negFprime;
if (10 ** 18 > K0) {
D_minus += (((_D * (mul1 / negFprime)) / 10 ** 18) * (10 ** 18 - K0)) / K0;
} else {
D_minus -= (((_D * (mul1 / negFprime)) / 10 ** 18) * (K0 - 10 ** 18)) / K0;
}
unchecked {
if (D_plus > D_minus) {
_D = D_plus - D_minus;
} else {
_D = (D_minus - D_plus) / 2;
}
}
uint256 diff = 0;
unchecked {
if (_D > DPrev) {
diff = _D - DPrev;
} else {
diff = DPrev - _D;
}
}
if (diff * 10 ** 14 < Math.max(10 ** 16, _D)) {
for (uint256 j = 0; j < x.length; ++j) {
uint256 frac = (x[j] * 10 ** 18) / _D;
require((frac > 10 ** 16 - 1) && (frac < 10 ** 20 + 1));
}
return _D;
}
}
revert("C");
}
function _newtonY(uint256 mA, uint256 mGamma, uint256 xJ, uint256 _D) internal pure returns (uint256 y) {
unchecked {
require(mA > _MIN_A - 1 && mA < _MAX_A + 1);
require(mGamma > _MIN_GAMMA - 1 && mGamma < _MAX_GAMMA + 1);
require(_D > 10 ** 17 - 1 && _D < 10 ** 15 * 10 ** 18 + 1);
}
y = _D ** 2 / (xJ * N_COINS ** 2);
uint256 K0I = ((10 ** 18 * N_COINS) * xJ) / _D;
require((K0I > 10 ** 16 * N_COINS - 1) && (K0I < 10 ** 20 * N_COINS + 1));
uint256 convergenceLimit = Math.max(Math.max(xJ / 10 ** 14, _D / 10 ** 14), 100);
for (uint256 j = 0; j < 255; ++j) {
uint256 K0 = (K0I * y * N_COINS) / _D;
uint256 mul1;
uint256 mul2;
{
uint256 _g1k0 = mGamma + 10 ** 18;
unchecked {
if (_g1k0 > K0) {
_g1k0 = _g1k0 - K0 + 1;
} else {
_g1k0 = K0 - _g1k0 + 1;
}
}
mul1 = (((((10 ** 18 * _D) / mGamma) * _g1k0) / mGamma) * _g1k0 * _A_MULTIPLIER) / mA;
mul2 = 10 ** 18 + ((2 * 10 ** 18) * K0) / _g1k0;
}
uint256 S = xJ + y;
uint256 yfprime = 10 ** 18 * y + S * mul2 + mul1;
uint256 yPrev = y;
{
uint256 _dyfprime = _D * mul2;
if (yfprime < _dyfprime) {
y = yPrev / 2;
continue;
} else {
unchecked {
yfprime -= _dyfprime;
}
}
}
{
uint256 fprime = yfprime / y;
uint256 yMinus = mul1 / fprime;
uint256 yPlus = (yfprime + 10 ** 18 * _D) / fprime + (yMinus * 10 ** 18) / K0;
yMinus += (10 ** 18 * S) / fprime;
if (yPlus < yMinus) {
y = yPrev / 2;
} else {
unchecked {
y = yPlus - yMinus;
}
}
}
uint256 diff;
unchecked {
diff = y > yPrev ? y - yPrev : yPrev - y;
}
if (diff < Math.max(convergenceLimit, y / 10 ** 14)) {
uint256 frac = (y * 10 ** 18) / _D;
require((frac > 10 ** 16 - 1) && (frac < 10 ** 20 + 1));
return y;
}
}
revert("C");
}
function _burnMsgSender(uint256 amount) internal {
ICryptoPoolToken(token).burn(msg.sender, amount);
}
function _mintMsgSender(uint256 amount) internal {
ICryptoPoolToken(token).mint(msg.sender, amount);
}
}
文件 3 的 18:ICryptoPoolToken.sol
pragma solidity ^0.8.3;
import "./IPoolToken.sol";
interface ICryptoPoolToken is IPoolToken {
function mintRelative(address to, uint256 frac) external returns (uint256);
}
文件 4 的 18:ICryptoSwap2Pool.sol
pragma solidity ^0.8.3;
import "./IKokonutSwapPool.sol";
interface ICryptoSwap2Pool is IKokonutSwapPool {
event AddLiquidity(
address indexed provider,
uint256[] tokenAmounts,
uint256 fee,
uint256 invariant,
uint256 tokenSupply
);
event RemoveLiquidityOne(
address indexed provider,
uint256 i,
uint256 tokenAmount,
uint256 lpFee,
uint256 tokenSupply
);
event CommitNewParameters(
uint256 indexed deadline,
uint256 adminFee,
uint256 flashLoanFee,
uint256 midFee,
uint256 outFee,
uint256 feeGamma,
uint256 allowedExtraProfit,
uint256 minRemainingPostRebalanceRatio,
uint256 adjustmentStep,
uint256 maHalfTime
);
event NewParameters(
uint256 adminFee,
uint256 flashLoanFee,
uint256 midFee,
uint256 outFee,
uint256 feeGamma,
uint256 allowedExtraProfit,
uint256 minRemainingPostRebalanceRatio,
uint256 adjustmentStep,
uint256 maHalfTime
);
event RampAGamma(
uint256 initialA,
uint256 futureA,
uint256 initialGamma,
uint256 futureGamma,
uint256 initialTime,
uint256 futureTime
);
event StopRampA(uint256 currentA, uint256 currentGamma, uint256 time);
event ClaimAdminFee(address indexed admin, uint256 tokens);
event TweakPrice(uint256 priceScale, uint256 newD, uint256 virtualPrice, uint256 xcpProfit);
function lpPrice() external view returns (uint256);
function gamma() external view returns (uint256);
function midFee() external view returns (uint256);
function outFee() external view returns (uint256);
function priceOracle() external view returns (uint256);
function addLiquidity(uint256[] calldata amounts, uint256 minMintAmount) external returns (uint256, uint256);
function calcDeposit(uint256[] calldata amounts) external view returns (uint256, uint256);
function removeLiquidityOneCoin(
uint256 tokenAmount,
uint256 i,
uint256 minAmount
) external returns (uint256, uint256);
function calcWithdrawOneCoin(uint256 tokenAmount, uint256 i) external view returns (uint256, uint256);
function claimableAdminFee() external view returns (uint256);
function claimAdminFee() external;
function rampAGamma(uint32 futureA, uint64 futureGamma, uint32 futureTime) external;
function stopRampAGamma() external;
function commitNewParameters(
uint256 _newMidFee,
uint256 _newOutFee,
uint256 _newAdminFee,
uint256 _newFlashLoanFee,
uint256 _newFeeGamma,
uint256 _newAllowedExtraProfit,
uint256 _newRebalancingThreshold,
uint256 _newAdjustmentStep,
uint256 _newMaHalfTime
) external;
function applyNewParameters() external;
function revertNewParameters() external;
struct InitializeArgs {
uint32 A;
uint64 gamma;
uint256 midFee;
uint256 outFee;
uint256 allowedExtraProfit;
uint256 minRemainingPostRebalanceRatio;
uint256 feeGamma;
uint256 adjustmentStep;
uint256 adminFee;
uint256 flashLoanFee;
uint256 maHalfTime;
uint256 initialPrice;
address[] coins;
}
function priceScale() external view returns (uint256);
function lastPrices() external view returns (uint256);
function lastPricesTimestamp() external view returns (uint256);
function initialA() external view returns (uint32);
function futureA() external view returns (uint32);
function initialGamma() external view returns (uint64);
function futureGamma() external view returns (uint64);
function initialAGammaTime() external view returns (uint32);
function futureAGammaTime() external view returns (uint32);
function allowedExtraProfit() external view returns (uint256);
function futureAllowedExtraProfit() external view returns (uint256);
function minRemainingPostRebalanceRatio() external view returns (uint256);
function futureRebalancingThreshold() external view returns (uint256);
function feeGamma() external view returns (uint256);
function futureFeeGamma() external view returns (uint256);
function adjustmentStep() external view returns (uint256);
function futureAdjustmentStep() external view returns (uint256);
function maHalfTime() external view returns (uint256);
function futureMaHalfTime() external view returns (uint256);
function futureMidFee() external view returns (uint256);
function futureOutFee() external view returns (uint256);
function futureAdminFee() external view returns (uint256);
function futureFlashLoanFee() external view returns (uint256);
function D() external view returns (uint256);
function xcpProfit() external view returns (uint256);
function xcpProfitA() external view returns (uint256);
function virtualPrice() external view returns (uint256);
function adminActionsDeadline() external view returns (uint256);
}
文件 5 的 18:ICryptoSwapFactory.sol
pragma solidity ^0.8.3;
import "./ICryptoSwap2Pool.sol";
interface ICryptoSwapFactory {
event CryptoPoolDeployed(address pool, ICryptoSwap2Pool.InitializeArgs args, address deployer);
event UpdatePoolDeployer(address oldPoolDeployer, address newPoolDeployer);
event UpdateFeeReceiver(address oldFeeReceiver, address newFeeReceiver);
struct PoolArray {
uint256 index;
address[] coins;
address token;
}
function poolDeployer() external view returns (address);
function poolList(uint256 i) external view returns (address);
function deployPool(ICryptoSwap2Pool.InitializeArgs calldata args) external returns (address);
function setPoolDeployer(address poolDeployer) external;
function setFeeReceiver(address newFeeReceiver) external;
function findPoolForCoins(address _from, address _to, uint256 i) external view returns (address);
function getFeeReceiver() external view returns (address);
function getPoolList() external view returns (address[] memory);
function poolCount() external view returns (uint256);
function getPoolInfo(address _pool) external view returns (PoolArray memory);
}
文件 6 的 18:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 7 的 18:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 8 的 18:IKokonutSwapExchangeCallback.sol
pragma solidity ^0.8.0;
interface IKokonutSwapExchangeCallback {
function onExchange(uint256 i, uint256 j, uint256 dx, uint256 dy, bytes calldata data) external;
}
文件 9 的 18:IKokonutSwapFlashCallback.sol
pragma solidity ^0.8.0;
interface IKokonutSwapFlashCallback {
function onFlashLoan(
address initiator,
uint256[] calldata amounts,
uint256[] calldata fees,
bytes calldata data
) external;
}
文件 10 的 18:IKokonutSwapPool.sol
pragma solidity ^0.8.3;
import "./IKokonutSwapFlashCallback.sol";
interface IKokonutSwapPool {
event TokenExchange(
address indexed buyer,
uint256 soldId,
uint256 tokensSold,
uint256 boughtId,
uint256 tokensBought,
uint256 fee
);
event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256 tokenSupply);
event FlashLoan(address indexed borrower, uint256[] amounts, uint256[] fees);
function N_COINS() external view returns (uint256);
function balances(uint256 i) external view returns (uint256);
function token() external view returns (address);
function coins(uint256 i) external view returns (address);
function getPrice(uint256 i, uint256 j) external view returns (uint256);
function getVirtualPrice() external view returns (uint256);
function A() external view returns (uint256);
function fee() external view returns (uint256);
function adminFee() external view returns (uint256);
function exchange(
uint256 i,
uint256 j,
uint256 dx,
uint256 minDy,
bytes calldata data
) external returns (uint256, uint256);
function flashLoanFee() external view returns (uint256);
function removeLiquidity(uint256 amount, uint256[] calldata minAmounts) external returns (uint256[] memory);
function getDy(uint256 i, uint256 j, uint256 dx) external view returns (uint256, uint256);
function calcWithdraw(uint256 amount) external view returns (uint256[] memory);
function flashLoan(IKokonutSwapFlashCallback borrower, uint256[] calldata amounts, bytes calldata data) external;
function withdrawLostToken(address token, uint256 amount, address to) external;
}
文件 11 的 18:IPoolToken.sol
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IPoolToken is IERC20Metadata {
function mint(address user, uint256 amount) external returns (bool);
function burn(address user, uint256 amount) external returns (bool);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 12 的 18:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
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 average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
文件 13 的 18:Ownable.sol
pragma solidity ^0.8.0;
abstract contract Ownable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(msg.sender);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == msg.sender, "Ownable");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 14 的 18:Pausable.sol
pragma solidity ^0.8.0;
abstract contract Pausable {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable");
}
function _requirePaused() internal view virtual {
require(paused(), "Pausable");
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(msg.sender);
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(msg.sender);
}
}
文件 15 的 18:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "Reentrant");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function reentrancyGuardEntered() public view returns (bool) {
return _status == _ENTERED;
}
}
文件 16 的 18:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 17 的 18:ZKokonutAccess.sol
pragma solidity ^0.8.3;
import "../library/Pausable.sol";
import "../library/Ownable.sol";
abstract contract ZKokonutAccess is Ownable, Pausable {
function _initializeZKokonutAccess(address owner_) internal {
_transferOwnership(owner_);
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
}
文件 18 的 18:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"contracts/CryptoSwap2Pool.sol": "CryptoSwap2Pool"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"components":[{"internalType":"uint32","name":"A","type":"uint32"},{"internalType":"uint64","name":"gamma","type":"uint64"},{"internalType":"uint256","name":"midFee","type":"uint256"},{"internalType":"uint256","name":"outFee","type":"uint256"},{"internalType":"uint256","name":"allowedExtraProfit","type":"uint256"},{"internalType":"uint256","name":"minRemainingPostRebalanceRatio","type":"uint256"},{"internalType":"uint256","name":"feeGamma","type":"uint256"},{"internalType":"uint256","name":"adjustmentStep","type":"uint256"},{"internalType":"uint256","name":"adminFee","type":"uint256"},{"internalType":"uint256","name":"flashLoanFee","type":"uint256"},{"internalType":"uint256","name":"maHalfTime","type":"uint256"},{"internalType":"uint256","name":"initialPrice","type":"uint256"},{"internalType":"address[]","name":"coins","type":"address[]"}],"internalType":"struct ICryptoSwap2Pool.InitializeArgs","name":"args","type":"tuple"},{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"factory_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"invariant","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenSupply","type":"uint256"}],"name":"AddLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"ClaimAdminFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"deadline","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adminFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"flashLoanFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"midFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeGamma","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allowedExtraProfit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minRemainingPostRebalanceRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adjustmentStep","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maHalfTime","type":"uint256"}],"name":"CommitNewParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"fees","type":"uint256[]"}],"name":"FlashLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"adminFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"flashLoanFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"midFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeGamma","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allowedExtraProfit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minRemainingPostRebalanceRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adjustmentStep","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maHalfTime","type":"uint256"}],"name":"NewParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"initialA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"futureA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"initialGamma","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"futureGamma","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"initialTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"futureTime","type":"uint256"}],"name":"RampAGamma","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"tokenSupply","type":"uint256"}],"name":"RemoveLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"i","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenSupply","type":"uint256"}],"name":"RemoveLiquidityOne","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentGamma","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"StopRampA","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"soldId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"boughtId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensBought","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"TokenExchange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"priceScale","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newD","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"virtualPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"xcpProfit","type":"uint256"}],"name":"TweakPrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"A","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"D","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"N_COINS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256","name":"minMintAmount","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"dToken","type":"uint256"},{"internalType":"uint256","name":"lpFee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adjustmentStep","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminActionsDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowedExtraProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"applyNewParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"calcDeposit","outputs":[{"internalType":"uint256","name":"lpAmount","type":"uint256"},{"internalType":"uint256","name":"lpFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"calcWithdraw","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"}],"name":"calcWithdrawOneCoin","outputs":[{"internalType":"uint256","name":"dy","type":"uint256"},{"internalType":"uint256","name":"lpFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimAdminFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimableAdminFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"}],"name":"coins","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMidFee","type":"uint256"},{"internalType":"uint256","name":"_newOutFee","type":"uint256"},{"internalType":"uint256","name":"_newAdminFee","type":"uint256"},{"internalType":"uint256","name":"_newFlashLoanFee","type":"uint256"},{"internalType":"uint256","name":"_newFeeGamma","type":"uint256"},{"internalType":"uint256","name":"_newAllowedExtraProfit","type":"uint256"},{"internalType":"uint256","name":"_newRebalancingThreshold","type":"uint256"},{"internalType":"uint256","name":"_newAdjustmentStep","type":"uint256"},{"internalType":"uint256","name":"_newMaHalfTime","type":"uint256"}],"name":"commitNewParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"j","type":"uint256"},{"internalType":"uint256","name":"dx","type":"uint256"},{"internalType":"uint256","name":"minDy","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"exchange","outputs":[{"internalType":"uint256","name":"dy","type":"uint256"},{"internalType":"uint256","name":"dyFee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeGamma","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IKokonutSwapFlashCallback","name":"borrower","type":"address"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flashLoanFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureA","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureAGammaTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureAdjustmentStep","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureAdminFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureAllowedExtraProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureFeeGamma","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureFlashLoanFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureGamma","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureMaHalfTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureMidFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureOutFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"futureRebalancingThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gamma","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"j","type":"uint256"},{"internalType":"uint256","name":"dx","type":"uint256"}],"name":"getDy","outputs":[{"internalType":"uint256","name":"dy","type":"uint256"},{"internalType":"uint256","name":"dyFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"j","type":"uint256"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVirtualPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialA","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialAGammaTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialGamma","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"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":"lpPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maHalfTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"midFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRemainingPostRebalanceRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceOracle","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"futureA_","type":"uint32"},{"internalType":"uint64","name":"futureGamma_","type":"uint64"},{"internalType":"uint32","name":"futureTime_","type":"uint32"}],"name":"rampAGamma","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reentrancyGuardEntered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"minAmounts","type":"uint256[]"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"minAmount","type":"uint256"}],"name":"removeLiquidityOneCoin","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revertNewParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopRampAGamma","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"virtualPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawLostToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"xcpProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xcpProfitA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]