@pendle/core-v2 0.10.2-testnet → 0.10.4-testnet
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/AaveV3/PendleAaveV3SCY.sol/PendleAaveV3SCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/AaveV3/PendleAaveV3SCY.sol/PendleAaveV3SCY.json +2 -2
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/AaveV3/WadRayMath.sol/WadRayMath.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiSAvaxSCY.sol/PendleQiSAvaxSCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiSAvaxSCY.sol/PendleQiSAvaxSCY.json +2 -2
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiTokenHelper.sol/PendleQiTokenHelper.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiTokenSCY.sol/PendleQiTokenSCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiTokenSCY.sol/PendleQiTokenSCY.json +2 -2
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleSAvaxSCY.sol/PendleSAvaxSCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/Euler/PendleEulerSCY.sol/PendleEulerSCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleERC4626SCY.sol/PendleERC4626SCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleStargateSCY.sol/PendleStargateSCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleStargateSCY.sol/PendleStargateSCY.json +2 -2
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleWstEthSCY.sol/PendleWstEthSCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleYearnVaultSCY.sol/PendleYearnVaultSCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/TraderJoe/PendleSJoeSCY.sol/PendleSJoeSCY.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/TraderJoe/PendleSJoeSCY.sol/PendleSJoeSCY.json +2 -2
- package/build/artifacts/contracts/SuperComposableYield/base-implementations/SCYBase.sol/SCYBase.dbg.json +1 -1
- package/build/artifacts/contracts/SuperComposableYield/base-implementations/SCYBaseWithRewards.sol/SCYBaseWithRewards.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/CelerAbstracts/CelerReceiverUpg.sol/CelerReceiverUpg.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/CelerAbstracts/CelerSenderUpg.sol/CelerSenderUpg.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/GaugeController/PendleGaugeControllerBaseUpg.sol/PendleGaugeControllerBaseUpg.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/GaugeController/PendleGaugeControllerMainchainUpg.sol/PendleGaugeControllerMainchainUpg.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/GaugeController/PendleGaugeControllerSidechainUpg.sol/PendleGaugeControllerSidechainUpg.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/PendleGauge.sol/PendleGauge.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/VotingController/PendleVotingControllerUpg.sol/PendleVotingControllerUpg.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/VotingController/VotingControllerStorageUpg.sol/VotingControllerStorageUpg.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/VotingEscrow/VotingEscrowPendleMainchain.sol/VotingEscrowPendleMainchain.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/VotingEscrow/VotingEscrowPendleSidechain.sol/VotingEscrowPendleSidechain.dbg.json +1 -1
- package/build/artifacts/contracts/core/LiquidityMining/VotingEscrow/VotingEscrowTokenBase.sol/VotingEscrowTokenBase.dbg.json +1 -1
- package/build/artifacts/contracts/core/Market/PendleMarket.sol/PendleMarket.dbg.json +1 -1
- package/build/artifacts/contracts/core/Market/PendleMarket.sol/PendleMarket.json +8 -8
- package/build/artifacts/contracts/core/Market/PendleMarketFactory.sol/PendleMarketFactory.dbg.json +1 -1
- package/build/artifacts/contracts/core/Market/PendleMarketFactory.sol/PendleMarketFactory.json +2 -2
- package/build/artifacts/contracts/core/PendleERC20.sol/PendleERC20.dbg.json +1 -1
- package/build/artifacts/contracts/core/PendleRouter.sol/PendleRouter.dbg.json +1 -1
- package/build/artifacts/contracts/core/PendleRouter.sol/PendleRouter.json +2 -2
- package/build/artifacts/contracts/core/YieldContracts/InterestManagerYT.sol/InterestManagerYT.dbg.json +1 -1
- package/build/artifacts/contracts/core/YieldContracts/PendlePrincipalToken.sol/PendlePrincipalToken.dbg.json +1 -1
- package/build/artifacts/contracts/core/YieldContracts/PendleYieldContractFactory.sol/PendleYieldContractFactory.dbg.json +1 -1
- package/build/artifacts/contracts/core/YieldContracts/PendleYieldToken.sol/PendleYieldToken.dbg.json +1 -1
- package/build/artifacts/contracts/core/actions/ActionAddRemoveLiq.sol/ActionAddRemoveLiq.dbg.json +1 -1
- package/build/artifacts/contracts/core/actions/ActionAddRemoveLiq.sol/ActionAddRemoveLiq.json +2 -2
- package/build/artifacts/contracts/core/actions/ActionCallback.sol/ActionCallback.dbg.json +1 -1
- package/build/artifacts/contracts/core/actions/ActionCallback.sol/ActionCallback.json +2 -2
- package/build/artifacts/contracts/core/actions/ActionMintRedeem.sol/ActionMintRedeem.dbg.json +1 -1
- package/build/artifacts/contracts/core/actions/ActionMintRedeem.sol/ActionMintRedeem.json +2 -2
- package/build/artifacts/contracts/core/actions/ActionMisc.sol/ActionMisc.dbg.json +1 -1
- package/build/artifacts/contracts/core/actions/ActionSwapPT.sol/ActionSwapPT.dbg.json +1 -1
- package/build/artifacts/contracts/core/actions/ActionSwapPT.sol/ActionSwapPT.json +2 -2
- package/build/artifacts/contracts/core/actions/ActionSwapYT.sol/ActionSwapYT.dbg.json +1 -1
- package/build/artifacts/contracts/core/actions/ActionSwapYT.sol/ActionSwapYT.json +4 -4
- package/build/artifacts/contracts/core/actions/base/ActionBaseMintRedeem.sol/ActionBaseMintRedeem.dbg.json +1 -1
- package/build/artifacts/contracts/core/actions/base/CallbackHelper.sol/CallbackHelper.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IAToken.sol/IAToken.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IAavePool.sol/IAavePool.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IAaveRewardsController.sol/IAaveRewardsController.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IBenQiComptroller.sol/IBenQiComptroller.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IBenQiInterestRateModel.sol/IBenQiInterestRateModel.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/ICelerMessageBus.sol/ICelerMessageBus.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/ICelerMessageReceiverApp.sol/ICelerMessageReceiverApp.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IERC4626.sol/IERC4626.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IEulerEToken.sol/IEulerEToken.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IEulerMarkets.sol/IEulerMarkets.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPActionAddRemoveLiq.sol/IPActionAddRemoveLiq.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPActionMintRedeem.sol/IPActionMintRedeem.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPActionMisc.sol/IPActionMisc.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPActionSwapPT.sol/IPActionSwapPT.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPActionSwapYT.sol/IPActionSwapYT.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPActionSwapYT.sol/IPActionSwapYT.json +2 -2
- package/build/artifacts/contracts/interfaces/IPAllAction.sol/IPAllAction.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPAllAction.sol/IPAllAction.json +2 -2
- package/build/artifacts/contracts/interfaces/IPGauge.sol/IPGauge.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPGaugeController.sol/IPGaugeController.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPGaugeControllerMainchain.sol/IPGaugeControllerMainchain.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPInterestManagerYT.sol/IPInterestManagerYT.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPMarket.sol/IPMarket.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPMarketFactory.sol/IPMarketFactory.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPMarketSwapCallback.sol/IPMarketSwapCallback.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPPrincipalToken.sol/IPPrincipalToken.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPVeToken.sol/IPVeToken.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPVotingController.sol/IPVotingController.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPVotingEscrow.sol/IPVotingEscrow.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPYieldContractFactory.sol/IPYieldContractFactory.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IPYieldToken.sol/IPYieldToken.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IQiAvax.sol/IQiAvax.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IQiErc20.sol/IQiErc20.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IQiToken.sol/IQiToken.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IRewardManager.sol/IRewardManager.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/ISAvax.sol/ISAvax.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/ISJoe.sol/ISJoe.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IStETH.sol/IStETH.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IStargateLPStaking.sol/IStargateLPStaking.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IStargatePool.sol/IStargatePool.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IStargateRouter.sol/IStargateRouter.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/ISuperComposableYield.sol/ISuperComposableYield.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IWAvax.sol/IWAvax.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IWETH.sol/IWETH.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IWstETH.sol/IWstETH.dbg.json +1 -1
- package/build/artifacts/contracts/interfaces/IYearnVault.sol/IYearnVault.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/OracleLib.sol/OracleLib.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/RewardManager.sol/RewardManager.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/RewardManagerAbstract.sol/RewardManagerAbstract.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/SCY/SCYUtils.sol/SCYUtils.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/VeBalanceLib.sol/VeBalanceLib.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/VeHistoryLib.sol/Checkpoints.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/helpers/ArrayLib.sol/ArrayLib.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/helpers/ExpiryUtilsLib.sol/ExpiryUtils.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/helpers/MiniHelpers.sol/MiniHelpers.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/helpers/PYIndex.sol/PYIndexLib.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/helpers/SSTORE2Deployer.sol/SSTORE2Deployer.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/helpers/TokenHelper.sol/TokenHelper.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/kyberswap/KyberSwapHelper.sol/KyberSwapHelper.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/math/LogExpMath.sol/LogExpMath.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/MarketApproxPtInLib.dbg.json +4 -0
- package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/{MarketApproxLib.json → MarketApproxPtInLib.json} +3 -3
- package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/MarketApproxPtOutLib.dbg.json +4 -0
- package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/MarketApproxPtOutLib.json +10 -0
- package/build/artifacts/contracts/libraries/math/MarketMathCore.sol/MarketMathCore.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/math/Math.sol/Math.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/math/WeekMath.sol/WeekMath.dbg.json +1 -1
- package/build/artifacts/contracts/libraries/solmate/SSTORE2.sol/SSTORE2.dbg.json +1 -1
- package/build/artifacts/contracts/offchain-helpers/MarketMathStatic.sol/MarketMathStatic.dbg.json +1 -1
- package/build/artifacts/contracts/offchain-helpers/MarketMathStatic.sol/MarketMathStatic.json +2 -2
- package/build/artifacts/contracts/offchain-helpers/RouterStatic.sol/RouterStatic.dbg.json +1 -1
- package/build/artifacts/contracts/offchain-helpers/RouterStatic.sol/RouterStatic.json +116 -56
- package/build/artifacts/contracts/periphery/BoringOwnableUpgradeable.sol/BoringOwnableUpgradeable.dbg.json +1 -1
- package/build/artifacts/contracts/periphery/BoringOwnableUpgradeable.sol/BoringOwnableUpgradeableData.dbg.json +1 -1
- package/contracts/SuperComposableYield/base-implementations/SCYBaseWithRewards.sol +6 -1
- package/contracts/core/actions/ActionAddRemoveLiq.sol +2 -1
- package/contracts/core/actions/ActionSwapPT.sol +2 -1
- package/contracts/core/actions/ActionSwapYT.sol +3 -2
- package/contracts/interfaces/IPActionSwapYT.sol +2 -2
- package/contracts/libraries/math/MarketApproxLib.sol +373 -447
- package/contracts/offchain-helpers/MarketMathStatic.sol +32 -14
- package/contracts/offchain-helpers/RouterStatic.sol +48 -18
- package/deployments/43113-markets/benqi-market-35237d.json +8 -0
- package/deployments/43113-markets/benqi-market-438DAA.json +8 -0
- package/deployments/43113-markets/benqi-market-a45e40.json +8 -0
- package/deployments/43113-testenv.json +22 -0
- package/package.json +1 -1
- package/typechain-types/ActionSwapYT.ts +5 -5
- package/typechain-types/IPActionSwapYT.ts +5 -5
- package/typechain-types/IPAllAction.ts +5 -5
- package/typechain-types/RouterStatic.ts +57 -4
- package/typechain-types/factories/ActionAddRemoveLiq__factory.ts +1 -1
- package/typechain-types/factories/ActionCallback__factory.ts +1 -1
- package/typechain-types/factories/ActionMintRedeem__factory.ts +1 -1
- package/typechain-types/factories/ActionSwapPT__factory.ts +1 -1
- package/typechain-types/factories/ActionSwapYT__factory.ts +3 -3
- package/typechain-types/factories/IPActionSwapYT__factory.ts +2 -2
- package/typechain-types/factories/IPAllAction__factory.ts +2 -2
- package/typechain-types/factories/MarketMathStatic__factory.ts +1 -1
- package/typechain-types/factories/PendleAaveV3SCY__factory.ts +1 -1
- package/typechain-types/factories/PendleMarketFactory__factory.ts +1 -1
- package/typechain-types/factories/PendleMarket__factory.ts +1 -1
- package/typechain-types/factories/PendleQiSAvaxSCY__factory.ts +1 -1
- package/typechain-types/factories/PendleQiTokenSCY__factory.ts +1 -1
- package/typechain-types/factories/PendleRouter__factory.ts +1 -1
- package/typechain-types/factories/PendleSJoeSCY__factory.ts +1 -1
- package/typechain-types/factories/PendleStargateSCY__factory.ts +1 -1
- package/typechain-types/factories/RouterStatic__factory.ts +61 -1
- package/typechain-types/hardhat.d.ts +0 -90
- package/typechain-types/index.ts +0 -20
- package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/MarketApproxLib.dbg.json +0 -4
- package/deployments/43113-benqi.json +0 -10
|
@@ -27,32 +27,36 @@ struct ApproxParams {
|
|
|
27
27
|
/// approximation, it will be used (and save all the guessing).
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
library MarketApproxPtInLib {
|
|
31
|
+
using MarketMathCore for MarketState;
|
|
32
|
+
using PYIndexLib for PYIndex;
|
|
32
33
|
using Math for uint256;
|
|
33
34
|
using Math for int256;
|
|
34
35
|
using LogExpMath for int256;
|
|
35
|
-
using PYIndexLib for PYIndex;
|
|
36
|
-
using MarketMathCore for MarketState;
|
|
37
36
|
|
|
38
|
-
struct
|
|
39
|
-
uint256
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
uint256
|
|
43
|
-
uint256
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
struct ApproxParamsPtIn {
|
|
38
|
+
uint256 guessMin;
|
|
39
|
+
uint256 guessMax;
|
|
40
|
+
uint256 guessOffchain;
|
|
41
|
+
uint256 maxIteration;
|
|
42
|
+
uint256 eps;
|
|
43
|
+
//
|
|
44
|
+
uint256 biggestGoodGuess;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
struct Args1 {
|
|
48
|
+
MarketState market;
|
|
49
|
+
PYIndex index;
|
|
50
|
+
uint256 minScyOut;
|
|
51
|
+
uint256 blockTime;
|
|
52
|
+
}
|
|
49
53
|
|
|
50
54
|
function approxSwapPtForExactScy(
|
|
51
|
-
MarketState memory
|
|
52
|
-
PYIndex
|
|
53
|
-
uint256
|
|
54
|
-
uint256
|
|
55
|
-
ApproxParams memory
|
|
55
|
+
MarketState memory _market,
|
|
56
|
+
PYIndex _index,
|
|
57
|
+
uint256 _minScyOut,
|
|
58
|
+
uint256 _blockTime,
|
|
59
|
+
ApproxParams memory _approx
|
|
56
60
|
)
|
|
57
61
|
internal
|
|
58
62
|
pure
|
|
@@ -66,88 +70,58 @@ library MarketApproxLib {
|
|
|
66
70
|
the algorithm is essentially to:
|
|
67
71
|
1. binary search netPtIn
|
|
68
72
|
2. if netScyOut is greater & approx minScyOut => answer found
|
|
69
|
-
|
|
70
|
-
Psuedo code:
|
|
71
|
-
binary search netPtIn:
|
|
72
|
-
netAssetOut = calcTrade(netPtIn)
|
|
73
|
-
if (netScyOut >= minScyOut):
|
|
74
|
-
guessMax = netPtIn;
|
|
75
|
-
if (netScyOut `greaterApprox` minScyOut) => answer found
|
|
76
|
-
else:
|
|
77
|
-
guessMin = netPtIn;
|
|
78
73
|
*/
|
|
79
74
|
|
|
80
|
-
|
|
75
|
+
Args1 memory arg = Args1(_market, _index, _minScyOut, _blockTime);
|
|
76
|
+
MarketPreCompute memory comp = arg.market.getMarketPreCompute(arg.index, arg.blockTime);
|
|
77
|
+
ApproxParamsPtIn memory p = newApproxParamsPtIn(_approx, comp.totalAsset);
|
|
81
78
|
|
|
82
|
-
|
|
83
|
-
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
|
|
79
|
+
uint256 minAssetOut = arg.index.scyToAssetUp(arg.minScyOut);
|
|
84
80
|
|
|
85
|
-
|
|
81
|
+
for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
|
|
82
|
+
(bool isGoodSlope, uint256 guess) = nextGuess(p, comp, arg.market.totalPt, iter);
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
for (uint256 iter = 0; iter < approx.maxIteration; ) {
|
|
90
|
-
vars.netPtInGuess = getCurrentGuess(iter, approx);
|
|
91
|
-
|
|
92
|
-
(vars.isSlopeNonNeg, vars.largestGoodSlope) = updateSlope(
|
|
93
|
-
comp,
|
|
94
|
-
market.totalPt,
|
|
95
|
-
vars.netPtInGuess,
|
|
96
|
-
vars.largestGoodSlope
|
|
97
|
-
);
|
|
98
|
-
if (!vars.isSlopeNonNeg) {
|
|
99
|
-
approx.guessMax = vars.netPtInGuess;
|
|
84
|
+
if (!isGoodSlope) {
|
|
85
|
+
p.guessMax = guess;
|
|
100
86
|
continue;
|
|
101
87
|
}
|
|
102
88
|
|
|
103
|
-
(
|
|
89
|
+
(uint256 netAssetOut, uint256 netAssetToReserve) = calcAssetOut(
|
|
90
|
+
arg.market,
|
|
104
91
|
comp,
|
|
105
|
-
|
|
92
|
+
guess
|
|
106
93
|
);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
vars.netAssetOut,
|
|
113
|
-
vars.minAssetOut,
|
|
114
|
-
approx.eps
|
|
115
|
-
);
|
|
116
|
-
if (isAnswerAccepted)
|
|
94
|
+
|
|
95
|
+
if (netAssetOut >= minAssetOut) {
|
|
96
|
+
p.guessMax = guess;
|
|
97
|
+
bool isAnswerAccepted = Math.isAGreaterApproxB(netAssetOut, minAssetOut, p.eps);
|
|
98
|
+
if (isAnswerAccepted) {
|
|
117
99
|
return (
|
|
118
|
-
|
|
119
|
-
index.assetToScy(
|
|
120
|
-
index.assetToScy(
|
|
100
|
+
guess,
|
|
101
|
+
arg.index.assetToScy(netAssetOut),
|
|
102
|
+
arg.index.assetToScy(netAssetToReserve)
|
|
121
103
|
);
|
|
104
|
+
}
|
|
122
105
|
} else {
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
unchecked {
|
|
127
|
-
++iter;
|
|
106
|
+
p.guessMin = guess;
|
|
128
107
|
}
|
|
129
108
|
}
|
|
130
109
|
revert("approx fail");
|
|
131
110
|
}
|
|
132
111
|
|
|
133
|
-
struct
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
uint256
|
|
138
|
-
uint256 amountAssetNeedMore;
|
|
139
|
-
uint256 largestGoodSlope;
|
|
140
|
-
bool isSlopeNonNeg;
|
|
141
|
-
uint256 maxAssetIn;
|
|
112
|
+
struct Args2 {
|
|
113
|
+
MarketState market;
|
|
114
|
+
PYIndex index;
|
|
115
|
+
uint256 maxScyIn;
|
|
116
|
+
uint256 blockTime;
|
|
142
117
|
}
|
|
143
118
|
|
|
144
|
-
/// `guessMin` & `guessMax` is to guess the `netPtIn` == `netYtOut`
|
|
145
119
|
function approxSwapExactScyForYt(
|
|
146
|
-
MarketState memory
|
|
147
|
-
PYIndex
|
|
148
|
-
uint256
|
|
149
|
-
uint256
|
|
150
|
-
ApproxParams memory
|
|
120
|
+
MarketState memory _market,
|
|
121
|
+
PYIndex _index,
|
|
122
|
+
uint256 _maxScyIn,
|
|
123
|
+
uint256 _blockTime,
|
|
124
|
+
ApproxParams memory _approx
|
|
151
125
|
)
|
|
152
126
|
internal
|
|
153
127
|
pure
|
|
@@ -165,498 +139,464 @@ library MarketApproxLib {
|
|
|
165
139
|
4. Pay back PT & give user YT.
|
|
166
140
|
5. If the PT loan can be successfully & amount of additional SCY is smallerApprox maxScyIn
|
|
167
141
|
=> answer found
|
|
168
|
-
|
|
169
|
-
Psuedo code:
|
|
170
|
-
maxAssetIn = maxScyIn -> asset
|
|
171
|
-
binary search netPtIn:
|
|
172
|
-
netAssetOut = calcTrade(netPtIn)
|
|
173
|
-
totalAssetNeedMoreToConvertPt = netPtIn - netAssetOut
|
|
174
|
-
if (totalAssetNeedMoreToConvertPt <= maxAssetIn):
|
|
175
|
-
guessMin = netPtIn;
|
|
176
|
-
if (totalAssetNeedMoreToConvertPt `smallerApprox` maxAssetIn) => answer found
|
|
177
|
-
else:
|
|
178
|
-
guessMax = netPtOut;
|
|
179
142
|
*/
|
|
180
143
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
|
|
144
|
+
Args2 memory arg = Args2(_market, _index, _maxScyIn, _blockTime);
|
|
145
|
+
MarketPreCompute memory comp = arg.market.getMarketPreCompute(arg.index, arg.blockTime);
|
|
146
|
+
ApproxParamsPtIn memory p = newApproxParamsPtIn(_approx, comp.totalAsset);
|
|
185
147
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (approx.guessMax == type(uint256).max) approx.guessMax = calcMaxPtIn(comp.totalAsset);
|
|
148
|
+
uint256 maxAssetIn = arg.index.scyToAsset(arg.maxScyIn);
|
|
189
149
|
|
|
190
150
|
// at minimum we will flashswap maxAssetIn since we have enough SCY to payback the PT loan
|
|
191
|
-
if (
|
|
151
|
+
if (p.guessMin == 0) p.guessMin = maxAssetIn;
|
|
192
152
|
|
|
193
|
-
for (uint256 iter = 0; iter <
|
|
153
|
+
for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
|
|
194
154
|
// ytOutGuess = ptInGuess
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
comp,
|
|
199
|
-
market.totalPt,
|
|
200
|
-
vars.netPtInGuess,
|
|
201
|
-
vars.largestGoodSlope
|
|
202
|
-
);
|
|
203
|
-
if (!vars.isSlopeNonNeg) {
|
|
204
|
-
approx.guessMax = vars.netPtInGuess - 1;
|
|
155
|
+
(bool isGoodSlope, uint256 guess) = nextGuess(p, comp, arg.market.totalPt, iter);
|
|
156
|
+
if (!isGoodSlope) {
|
|
157
|
+
p.guessMax = guess;
|
|
205
158
|
continue;
|
|
206
159
|
}
|
|
207
160
|
|
|
208
|
-
(
|
|
161
|
+
(uint256 netAssetOut, uint256 netAssetToReserve) = calcAssetOut(
|
|
162
|
+
arg.market,
|
|
209
163
|
comp,
|
|
210
|
-
|
|
164
|
+
guess
|
|
211
165
|
);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
bool isAnswerAccepted = Math.isASmallerApproxB(
|
|
218
|
-
vars.amountAssetNeedMore,
|
|
219
|
-
vars.maxAssetIn,
|
|
220
|
-
approx.eps
|
|
221
|
-
);
|
|
166
|
+
|
|
167
|
+
uint256 netAssetToPull = guess - netAssetOut;
|
|
168
|
+
|
|
169
|
+
if (netAssetToPull <= maxAssetIn) {
|
|
170
|
+
p.guessMin = guess;
|
|
171
|
+
bool isAnswerAccepted = Math.isASmallerApproxB(netAssetToPull, maxAssetIn, p.eps);
|
|
222
172
|
if (isAnswerAccepted)
|
|
223
173
|
return (
|
|
224
|
-
|
|
225
|
-
index.assetToScy(
|
|
226
|
-
index.assetToScy(
|
|
174
|
+
guess,
|
|
175
|
+
arg.index.assetToScy(netAssetToPull),
|
|
176
|
+
arg.index.assetToScy(netAssetToReserve)
|
|
227
177
|
);
|
|
228
178
|
} else {
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
unchecked {
|
|
233
|
-
++iter;
|
|
179
|
+
p.guessMax = guess;
|
|
234
180
|
}
|
|
235
181
|
}
|
|
236
182
|
revert("approx fail");
|
|
237
183
|
}
|
|
238
184
|
|
|
239
|
-
struct
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
uint256 netAssetIn;
|
|
185
|
+
struct Args6 {
|
|
186
|
+
MarketState market;
|
|
187
|
+
PYIndex index;
|
|
188
|
+
uint256 totalPtIn;
|
|
189
|
+
uint256 blockTime;
|
|
245
190
|
}
|
|
246
191
|
|
|
247
|
-
function
|
|
248
|
-
MarketState memory
|
|
249
|
-
PYIndex
|
|
250
|
-
uint256
|
|
251
|
-
uint256
|
|
252
|
-
ApproxParams memory
|
|
192
|
+
function approxSwapPtToAddLiquidity(
|
|
193
|
+
MarketState memory _market,
|
|
194
|
+
PYIndex _index,
|
|
195
|
+
uint256 _totalPtIn,
|
|
196
|
+
uint256 _blockTime,
|
|
197
|
+
ApproxParams memory _approx
|
|
253
198
|
)
|
|
254
199
|
internal
|
|
255
200
|
pure
|
|
256
201
|
returns (
|
|
257
|
-
uint256, /*
|
|
258
|
-
uint256, /*
|
|
202
|
+
uint256, /*netPtSwap*/
|
|
203
|
+
uint256, /*netScyFromSwap*/
|
|
259
204
|
uint256 /*netScyToReserve*/
|
|
260
205
|
)
|
|
261
206
|
{
|
|
262
207
|
/*
|
|
263
|
-
|
|
264
|
-
1.
|
|
265
|
-
2.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if (netAssetIn <= maxAssetIn):
|
|
272
|
-
guessMin = netPtOut
|
|
273
|
-
if (netAssetIn `smallerApprox` maxAssetIn) => answer found
|
|
274
|
-
else:
|
|
275
|
-
guessMax = netPtOut;
|
|
208
|
+
The algorithm is essentially to:
|
|
209
|
+
1. Binary search netPtIn (therefore netScyOut)
|
|
210
|
+
2. Swap netPtIn for netScyOut
|
|
211
|
+
3. Use (totalPtIn - netPtIn) and netScyOut to mint LP
|
|
212
|
+
4. If (totalPtIn - netPtIn) / netScyOut ratio is close enough to the market's PT/SCY ratio
|
|
213
|
+
=> answer found
|
|
214
|
+
|
|
215
|
+
Note that market maintains PT/SCY ratio, but here PT/asset is used instead
|
|
276
216
|
*/
|
|
277
217
|
|
|
278
|
-
|
|
218
|
+
Args6 memory arg = Args6(_market, _index, _totalPtIn, _blockTime);
|
|
219
|
+
require(arg.market.totalLp != 0, "no existing lp");
|
|
279
220
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
221
|
+
MarketPreCompute memory comp = arg.market.getMarketPreCompute(arg.index, arg.blockTime);
|
|
222
|
+
ApproxParamsPtIn memory p = newApproxParamsPtIn(_approx, comp.totalAsset);
|
|
223
|
+
|
|
224
|
+
p.guessMax = Math.min(p.guessMax, arg.totalPtIn);
|
|
285
225
|
|
|
286
|
-
|
|
226
|
+
for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
|
|
227
|
+
(bool isGoodSlope, uint256 guess) = nextGuess(p, comp, arg.market.totalPt, iter);
|
|
228
|
+
|
|
229
|
+
if (!isGoodSlope) {
|
|
230
|
+
p.guessMax = guess;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
287
233
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
(vars.assetToAccount, vars.assetToReserve) = market.calcTrade(
|
|
234
|
+
(uint256 netAssetOut, uint256 netAssetToReserve) = calcAssetOut(
|
|
235
|
+
arg.market,
|
|
291
236
|
comp,
|
|
292
|
-
|
|
237
|
+
guess
|
|
293
238
|
);
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
239
|
+
|
|
240
|
+
uint256 assetNumerator;
|
|
241
|
+
uint256 ptNumerator;
|
|
242
|
+
{
|
|
243
|
+
uint256 newTotalPt = arg.market.totalPt.Uint() + guess;
|
|
244
|
+
uint256 netPtRemaining = arg.totalPtIn - guess;
|
|
245
|
+
uint256 newTotalAsset = (comp.totalAsset.Uint() - netAssetOut - netAssetToReserve);
|
|
246
|
+
|
|
247
|
+
// it is desired that
|
|
248
|
+
// netAssetOut / newTotalAsset = netPtRemaining / newTotalPt
|
|
249
|
+
// which is equivalent to
|
|
250
|
+
// netAssetOut * newTotalPt = netPtRemaining * newTotalAsset
|
|
251
|
+
|
|
252
|
+
assetNumerator = netAssetOut * newTotalPt;
|
|
253
|
+
ptNumerator = netPtRemaining * newTotalAsset;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (Math.isAApproxB(assetNumerator, ptNumerator, p.eps)) {
|
|
257
|
+
return (
|
|
258
|
+
guess,
|
|
259
|
+
arg.index.assetToScy(netAssetOut),
|
|
260
|
+
arg.index.assetToScy(netAssetToReserve)
|
|
302
261
|
);
|
|
303
|
-
if (isAnswerAccepted)
|
|
304
|
-
return (
|
|
305
|
-
vars.ptOutGuess,
|
|
306
|
-
index.assetToScy(vars.netAssetIn),
|
|
307
|
-
index.assetToScy(vars.assetToReserve.Uint())
|
|
308
|
-
);
|
|
309
|
-
} else {
|
|
310
|
-
approx.guessMax = vars.ptOutGuess;
|
|
311
262
|
}
|
|
312
263
|
|
|
313
|
-
|
|
314
|
-
|
|
264
|
+
if (assetNumerator <= ptNumerator) {
|
|
265
|
+
// needs more asset --> swap more PT
|
|
266
|
+
p.guessMin = guess + 1;
|
|
267
|
+
} else {
|
|
268
|
+
// needs less asset --> swap less PT
|
|
269
|
+
p.guessMax = guess - 1;
|
|
315
270
|
}
|
|
316
271
|
}
|
|
317
272
|
revert("approx fail");
|
|
318
273
|
}
|
|
319
274
|
|
|
320
|
-
|
|
321
|
-
uint256 minAssetOut;
|
|
322
|
-
uint256 ptOutGuess;
|
|
323
|
-
int256 assetToAccount;
|
|
324
|
-
int256 assetToReserve;
|
|
325
|
-
uint256 netAssetOwed;
|
|
326
|
-
uint256 netAssetOut;
|
|
327
|
-
}
|
|
275
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
328
276
|
|
|
329
|
-
function
|
|
277
|
+
function calcAssetOut(
|
|
330
278
|
MarketState memory market,
|
|
331
|
-
|
|
332
|
-
uint256
|
|
333
|
-
|
|
334
|
-
|
|
279
|
+
MarketPreCompute memory comp,
|
|
280
|
+
uint256 netPtIn
|
|
281
|
+
) internal pure returns (uint256 netAssetOut, uint256 netAssetToReserve) {
|
|
282
|
+
(int256 assetToAccount, int256 assetToReserve) = market.calcTrade(comp, netPtIn.neg());
|
|
283
|
+
|
|
284
|
+
netAssetOut = assetToAccount.Uint();
|
|
285
|
+
netAssetToReserve = assetToReserve.Uint();
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function newApproxParamsPtIn(ApproxParams memory _approx, int256 totalAsset)
|
|
289
|
+
internal
|
|
290
|
+
pure
|
|
291
|
+
returns (ApproxParamsPtIn memory res)
|
|
292
|
+
{
|
|
293
|
+
res.guessMin = _approx.guessMin;
|
|
294
|
+
res.guessMax = Math.min(_approx.guessMax, calcMaxPtIn(totalAsset));
|
|
295
|
+
res.guessOffchain = _approx.guessOffchain;
|
|
296
|
+
res.maxIteration = _approx.maxIteration;
|
|
297
|
+
res.eps = _approx.eps;
|
|
298
|
+
|
|
299
|
+
require(res.guessMin <= res.guessMax && res.eps <= Math.ONE, "invalid approx params");
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function calcMaxPtIn(int256 totalAsset) internal pure returns (uint256) {
|
|
303
|
+
return totalAsset.Uint() - 1;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function nextGuess(
|
|
307
|
+
ApproxParamsPtIn memory p,
|
|
308
|
+
MarketPreCompute memory comp,
|
|
309
|
+
int256 totalPt,
|
|
310
|
+
uint256 iter
|
|
311
|
+
) internal pure returns (bool, uint256) {
|
|
312
|
+
uint256 guess = _nextGuessPrivate(p, iter);
|
|
313
|
+
if (guess <= p.biggestGoodGuess) return (true, guess);
|
|
314
|
+
|
|
315
|
+
int256 slope = calcSlope(comp, totalPt, guess.Int());
|
|
316
|
+
if (slope < 0) return (false, guess);
|
|
317
|
+
|
|
318
|
+
p.biggestGoodGuess = guess;
|
|
319
|
+
return (true, guess);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function _nextGuessPrivate(ApproxParamsPtIn memory p, uint256 iter)
|
|
323
|
+
private
|
|
324
|
+
pure
|
|
325
|
+
returns (uint256)
|
|
326
|
+
{
|
|
327
|
+
if (iter == 0 && p.guessOffchain != 0) return p.guessOffchain;
|
|
328
|
+
else if (p.guessMin > p.guessMax) return p.guessMax;
|
|
329
|
+
else return (p.guessMin + p.guessMax) / 2;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function calcSlope(
|
|
333
|
+
MarketPreCompute memory comp,
|
|
334
|
+
int256 totalPt,
|
|
335
|
+
int256 ptToMarket //
|
|
336
|
+
) internal pure returns (int256) {
|
|
337
|
+
int256 diffAssetPtToMarket = comp.totalAsset - ptToMarket;
|
|
338
|
+
int256 sumPt = ptToMarket + totalPt; // probably can skip sumPt check
|
|
339
|
+
|
|
340
|
+
require(diffAssetPtToMarket > 0 && sumPt > 0, "invalid ptToMarket");
|
|
341
|
+
|
|
342
|
+
int256 part1 = (ptToMarket * (totalPt + comp.totalAsset)).divDown(
|
|
343
|
+
sumPt * diffAssetPtToMarket
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
int256 part2 = sumPt.divDown(diffAssetPtToMarket).ln();
|
|
347
|
+
int256 part3 = Math.IONE.divDown(comp.rateScalar);
|
|
348
|
+
|
|
349
|
+
return comp.rateAnchor - (part1 - part2).mulDown(part3);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
library MarketApproxPtOutLib {
|
|
354
|
+
using MarketMathCore for MarketState;
|
|
355
|
+
using PYIndexLib for PYIndex;
|
|
356
|
+
using Math for uint256;
|
|
357
|
+
using Math for int256;
|
|
358
|
+
using LogExpMath for int256;
|
|
359
|
+
|
|
360
|
+
struct ApproxParamsPtOut {
|
|
361
|
+
uint256 guessMin;
|
|
362
|
+
uint256 guessMax;
|
|
363
|
+
uint256 guessOffchain;
|
|
364
|
+
uint256 maxIteration;
|
|
365
|
+
uint256 eps;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
struct Args4 {
|
|
369
|
+
MarketState market;
|
|
370
|
+
PYIndex index;
|
|
371
|
+
uint256 maxScyIn;
|
|
372
|
+
uint256 blockTime;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function approxSwapExactScyForPt(
|
|
376
|
+
MarketState memory _market,
|
|
377
|
+
PYIndex _index,
|
|
378
|
+
uint256 _maxScyIn,
|
|
379
|
+
uint256 _blockTime,
|
|
380
|
+
ApproxParams memory _approx
|
|
335
381
|
)
|
|
336
382
|
internal
|
|
337
383
|
pure
|
|
338
384
|
returns (
|
|
339
|
-
uint256, /*
|
|
340
|
-
uint256, /*
|
|
385
|
+
uint256, /*netPtOut*/
|
|
386
|
+
uint256, /*netScyIn*/
|
|
341
387
|
uint256 /*netScyToReserve*/
|
|
342
388
|
)
|
|
343
389
|
{
|
|
344
390
|
/*
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
2.
|
|
348
|
-
3. Pair netPtOut with the corresponding amount of Yt => redeem Scy
|
|
349
|
-
4. Pay back Scy & the exceed amount of Scy (netScyOut) is transferred out to user
|
|
350
|
-
5. If netScyOut is greater approx minScyOut => answer found
|
|
351
|
-
|
|
352
|
-
Psuedo code:
|
|
353
|
-
minAssetOut = minScyOut -> asset
|
|
354
|
-
binary search netPtOut:
|
|
355
|
-
netAssetIn = calcTrade(netPtOut)
|
|
356
|
-
netAssetFromPtYt = netPtOut
|
|
357
|
-
netAssetOut = netAssetFromPtYt - netAssetIn
|
|
358
|
-
if (netAssetOut >= minAssetOut):
|
|
359
|
-
guessMax = netPtOut
|
|
360
|
-
if (netAssetOut `greaterApprox` minAssetOut) => answer found
|
|
361
|
-
else:
|
|
362
|
-
guessMin = netPtOut;
|
|
391
|
+
1. Binary search netPtOut
|
|
392
|
+
2. Calc netScyIn to swap to receive netPtOut
|
|
393
|
+
2. If netScyIn < maxScyIn && netScyIn ~ maxScyIn => answer found
|
|
363
394
|
*/
|
|
364
395
|
|
|
365
|
-
|
|
396
|
+
Args4 memory arg = Args4(_market, _index, _maxScyIn, _blockTime);
|
|
397
|
+
MarketPreCompute memory comp = arg.market.getMarketPreCompute(arg.index, arg.blockTime);
|
|
398
|
+
ApproxParamsPtOut memory p = newApproxParamsPtOut(_approx, comp, arg.market.totalPt);
|
|
366
399
|
|
|
367
|
-
|
|
368
|
-
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
|
|
369
|
-
if (approx.guessMax == type(uint256).max) {
|
|
370
|
-
approx.guessMax = calcMaxPtOut(market.totalPt, comp);
|
|
371
|
-
}
|
|
400
|
+
uint256 maxAssetIn = arg.index.scyToAsset(arg.maxScyIn);
|
|
372
401
|
|
|
373
|
-
|
|
402
|
+
for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
|
|
403
|
+
uint256 guess = nextGuess(p, iter);
|
|
374
404
|
|
|
375
|
-
|
|
376
|
-
// ytInGuess = ptOutGuess
|
|
377
|
-
vars.ptOutGuess = getCurrentGuess(iter, approx);
|
|
405
|
+
(uint256 netAssetIn, uint256 netAssetToReserve) = calcAssetIn(arg.market, comp, guess);
|
|
378
406
|
|
|
379
|
-
(
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
vars.netAssetOwed = vars.assetToAccount.abs();
|
|
384
|
-
|
|
385
|
-
// since ptOutGuess is between guessMin & guessMax, it's guaranteed that
|
|
386
|
-
// there are enough Yt to pair with ptOut
|
|
387
|
-
|
|
388
|
-
vars.netAssetOut = vars.ptOutGuess - vars.netAssetOwed;
|
|
389
|
-
|
|
390
|
-
if (vars.netAssetOut >= vars.minAssetOut) {
|
|
391
|
-
approx.guessMax = vars.ptOutGuess;
|
|
392
|
-
if (Math.isAGreaterApproxB(vars.netAssetOut, vars.minAssetOut, approx.eps)) {
|
|
407
|
+
if (netAssetIn <= maxAssetIn) {
|
|
408
|
+
p.guessMin = guess;
|
|
409
|
+
bool isAnswerAccepted = Math.isASmallerApproxB(netAssetIn, maxAssetIn, p.eps);
|
|
410
|
+
if (isAnswerAccepted)
|
|
393
411
|
return (
|
|
394
|
-
|
|
395
|
-
index.assetToScy(
|
|
396
|
-
index.assetToScy(
|
|
412
|
+
guess,
|
|
413
|
+
arg.index.assetToScy(netAssetIn),
|
|
414
|
+
arg.index.assetToScy(netAssetToReserve)
|
|
397
415
|
);
|
|
398
|
-
}
|
|
399
416
|
} else {
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
unchecked {
|
|
404
|
-
++iter;
|
|
417
|
+
p.guessMax = guess - 1;
|
|
405
418
|
}
|
|
406
419
|
}
|
|
407
420
|
revert("approx fail");
|
|
408
421
|
}
|
|
409
422
|
|
|
410
|
-
struct
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
uint256
|
|
415
|
-
uint256 netPtRemaining;
|
|
416
|
-
uint256 newTotalPt;
|
|
417
|
-
uint256 newTotalAsset;
|
|
418
|
-
uint256 largestGoodSlope;
|
|
419
|
-
uint256 assetNumerator;
|
|
420
|
-
uint256 ptNumerator;
|
|
421
|
-
bool isSlopeNonNeg;
|
|
423
|
+
struct Args5 {
|
|
424
|
+
MarketState market;
|
|
425
|
+
PYIndex index;
|
|
426
|
+
uint256 minScyOut;
|
|
427
|
+
uint256 blockTime;
|
|
422
428
|
}
|
|
423
429
|
|
|
424
|
-
function
|
|
425
|
-
MarketState memory
|
|
426
|
-
PYIndex
|
|
427
|
-
uint256
|
|
428
|
-
uint256
|
|
429
|
-
ApproxParams memory
|
|
430
|
+
function approxSwapYtForExactScy(
|
|
431
|
+
MarketState memory _market,
|
|
432
|
+
PYIndex _index,
|
|
433
|
+
uint256 _minScyOut,
|
|
434
|
+
uint256 _blockTime,
|
|
435
|
+
ApproxParams memory _approx
|
|
430
436
|
)
|
|
431
437
|
internal
|
|
432
438
|
pure
|
|
433
439
|
returns (
|
|
434
|
-
uint256, /*
|
|
440
|
+
uint256, /*netYtIn*/
|
|
435
441
|
uint256, /*netScyOut*/
|
|
436
442
|
uint256 /*netScyToReserve*/
|
|
437
443
|
)
|
|
438
444
|
{
|
|
439
445
|
/*
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
=> answer found
|
|
446
|
-
|
|
447
|
-
Note that market maintains PT/SCY ratio, but here PT/asset is used instead
|
|
446
|
+
1. Binary search netPtOut (therefore netScyIn)
|
|
447
|
+
2. Flashswap netPtOut (now we owe netScyIn)
|
|
448
|
+
3. Pair netPtOut with netYtIn Yt => get SCY (netPtOut == netYtIn)
|
|
449
|
+
4. Pay back SCY & the exceed amount of SCY (netScyOut) is transferred out to user
|
|
450
|
+
5. If netScyOut > minScyOut && netScyOut ~ minScyOut => answer found
|
|
448
451
|
*/
|
|
449
452
|
|
|
450
|
-
|
|
453
|
+
Args5 memory arg = Args5(_market, _index, _minScyOut, _blockTime);
|
|
454
|
+
MarketPreCompute memory comp = arg.market.getMarketPreCompute(arg.index, arg.blockTime);
|
|
455
|
+
ApproxParamsPtOut memory p = newApproxParamsPtOut(_approx, comp, arg.market.totalPt);
|
|
451
456
|
|
|
452
|
-
|
|
453
|
-
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
|
|
457
|
+
uint256 minAssetOut = arg.index.scyToAssetUp(arg.minScyOut);
|
|
454
458
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
approx.guessMax = Math.min(calcMaxPtIn(comp.totalAsset), netPtAdded);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
require(isValidApproxParams(approx), "invalid approx");
|
|
459
|
+
for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
|
|
460
|
+
uint256 guess = nextGuess(p, iter);
|
|
461
461
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
(vars.isSlopeNonNeg, vars.largestGoodSlope) = updateSlope(
|
|
462
|
+
(uint256 netAssetOwed, uint256 netAssetToReserve) = calcAssetIn(
|
|
463
|
+
arg.market,
|
|
466
464
|
comp,
|
|
467
|
-
|
|
468
|
-
vars.netPtInGuess,
|
|
469
|
-
vars.largestGoodSlope
|
|
465
|
+
guess
|
|
470
466
|
);
|
|
471
|
-
if (!vars.isSlopeNonNeg) {
|
|
472
|
-
approx.guessMax = vars.netPtInGuess;
|
|
473
|
-
continue;
|
|
474
|
-
}
|
|
475
467
|
|
|
476
|
-
|
|
477
|
-
comp,
|
|
478
|
-
vars.netPtInGuess.neg()
|
|
479
|
-
);
|
|
468
|
+
uint256 netAssetOut = guess - netAssetOwed;
|
|
480
469
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
// netAssetOut * newTotalPt = netPtRemaining * newTotalAsset
|
|
491
|
-
|
|
492
|
-
vars.assetNumerator = vars.netAssetOut * vars.newTotalPt;
|
|
493
|
-
vars.ptNumerator = vars.netPtRemaining * vars.newTotalAsset;
|
|
494
|
-
|
|
495
|
-
if (Math.isAApproxB(vars.assetNumerator, vars.ptNumerator, approx.eps)) {
|
|
496
|
-
return (
|
|
497
|
-
vars.netPtInGuess,
|
|
498
|
-
index.assetToScy(vars.netAssetOut),
|
|
499
|
-
index.assetToScy(vars.assetToReserve.Uint())
|
|
500
|
-
);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
if (vars.assetNumerator <= vars.ptNumerator) {
|
|
504
|
-
// needs more asset --> swap more PT
|
|
505
|
-
approx.guessMin = vars.netPtInGuess + 1;
|
|
470
|
+
if (netAssetOut >= minAssetOut) {
|
|
471
|
+
p.guessMax = guess;
|
|
472
|
+
if (Math.isAGreaterApproxB(netAssetOut, minAssetOut, p.eps)) {
|
|
473
|
+
return (
|
|
474
|
+
guess,
|
|
475
|
+
arg.index.assetToScy(netAssetOut),
|
|
476
|
+
arg.index.assetToScy(netAssetToReserve)
|
|
477
|
+
);
|
|
478
|
+
}
|
|
506
479
|
} else {
|
|
507
|
-
|
|
508
|
-
approx.guessMax = vars.netPtInGuess - 1;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
unchecked {
|
|
512
|
-
++iter;
|
|
480
|
+
p.guessMin = guess + 1;
|
|
513
481
|
}
|
|
514
482
|
}
|
|
515
483
|
revert("approx fail");
|
|
516
484
|
}
|
|
517
485
|
|
|
518
|
-
struct
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
uint256 netAssetIn;
|
|
524
|
-
uint256 netAssetRemaining;
|
|
525
|
-
uint256 newTotalPt;
|
|
526
|
-
uint256 newTotalAsset;
|
|
527
|
-
uint256 ptNumerator;
|
|
528
|
-
uint256 assetNumerator;
|
|
486
|
+
struct Args6 {
|
|
487
|
+
MarketState market;
|
|
488
|
+
PYIndex index;
|
|
489
|
+
uint256 totalScyIn;
|
|
490
|
+
uint256 blockTime;
|
|
529
491
|
}
|
|
530
492
|
|
|
531
493
|
function approxSwapScyToAddLiquidity(
|
|
532
|
-
MarketState memory
|
|
533
|
-
PYIndex
|
|
534
|
-
uint256
|
|
535
|
-
uint256
|
|
536
|
-
ApproxParams memory
|
|
494
|
+
MarketState memory _market,
|
|
495
|
+
PYIndex _index,
|
|
496
|
+
uint256 _totalScyIn,
|
|
497
|
+
uint256 _blockTime,
|
|
498
|
+
ApproxParams memory _approx
|
|
537
499
|
)
|
|
538
500
|
internal
|
|
539
501
|
pure
|
|
540
502
|
returns (
|
|
541
|
-
uint256, /*
|
|
542
|
-
uint256, /*
|
|
503
|
+
uint256, /*netPtFromSwap*/
|
|
504
|
+
uint256, /*netScySwap*/
|
|
543
505
|
uint256 /*netScyToReserve*/
|
|
544
506
|
)
|
|
545
507
|
{
|
|
546
508
|
/*
|
|
547
|
-
The algorithm is essentially to:
|
|
548
509
|
1. Binary search netPtOut (therefore netScyIn)
|
|
549
510
|
2. Swap netScyIn for netPtOut
|
|
550
|
-
3. Use netPtOut and (
|
|
551
|
-
4. If netPtOut / (
|
|
511
|
+
3. Use netPtOut and (totalScyIn - netScyIn) to mint LP
|
|
512
|
+
4. If netPtOut / (totalScyIn - netScyIn) ratio is close enough to the market's PT/SCY ratio
|
|
552
513
|
=> answer found
|
|
553
514
|
|
|
554
515
|
Note that market maintains PT/SCY ratio, but here PT/asset is used instead
|
|
555
516
|
*/
|
|
556
|
-
require(market.totalLp != 0, "no existing lp");
|
|
557
517
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
if (approx.guessMax == type(uint256).max) {
|
|
561
|
-
approx.guessMax = calcMaxPtOut(market.totalPt, comp);
|
|
562
|
-
}
|
|
518
|
+
Args6 memory arg = Args6(_market, _index, _totalScyIn, _blockTime);
|
|
519
|
+
require(arg.market.totalLp != 0, "no existing lp");
|
|
563
520
|
|
|
564
|
-
|
|
521
|
+
MarketPreCompute memory comp = arg.market.getMarketPreCompute(arg.index, arg.blockTime);
|
|
522
|
+
ApproxParamsPtOut memory p = newApproxParamsPtOut(_approx, comp, arg.market.totalPt);
|
|
565
523
|
|
|
566
|
-
|
|
524
|
+
uint256 totalAssetIn = arg.index.scyToAsset(arg.totalScyIn);
|
|
567
525
|
|
|
568
|
-
for (uint256 iter = 0; iter <
|
|
569
|
-
|
|
570
|
-
(vars.assetToAccount, vars.assetToReserve) = market.calcTrade(
|
|
571
|
-
comp,
|
|
572
|
-
vars.ptOutGuess.Int()
|
|
573
|
-
);
|
|
526
|
+
for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
|
|
527
|
+
uint256 guess = nextGuess(p, iter);
|
|
574
528
|
|
|
575
|
-
|
|
529
|
+
(uint256 netAssetIn, uint256 netAssetToReserve) = calcAssetIn(arg.market, comp, guess);
|
|
576
530
|
|
|
577
|
-
if (
|
|
578
|
-
|
|
579
|
-
unchecked {
|
|
580
|
-
++iter;
|
|
581
|
-
}
|
|
531
|
+
if (netAssetIn > totalAssetIn) {
|
|
532
|
+
p.guessMax = guess - 1;
|
|
582
533
|
continue;
|
|
583
534
|
}
|
|
584
535
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
vars.newTotalAsset = (comp.totalAsset - vars.assetToAccount - vars.assetToReserve)
|
|
588
|
-
.Uint();
|
|
536
|
+
uint256 ptNumerator;
|
|
537
|
+
uint256 assetNumerator;
|
|
589
538
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
539
|
+
{
|
|
540
|
+
uint256 netAssetRemaining = totalAssetIn - netAssetIn;
|
|
541
|
+
uint256 newTotalPt = arg.market.totalPt.Uint() - guess;
|
|
542
|
+
uint256 newTotalAsset = comp.totalAsset.Uint() + netAssetIn - netAssetToReserve;
|
|
594
543
|
|
|
595
|
-
|
|
596
|
-
|
|
544
|
+
// it is desired that
|
|
545
|
+
// guess / newTotalPt = netAssetRemaining / newTotalAsset
|
|
546
|
+
// which is equivalent to
|
|
547
|
+
// guess * newTotalAsset = netAssetRemaining * newTotalPt
|
|
597
548
|
|
|
598
|
-
|
|
549
|
+
ptNumerator = guess * newTotalAsset;
|
|
550
|
+
assetNumerator = netAssetRemaining * newTotalPt;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if (Math.isAApproxB(ptNumerator, assetNumerator, p.eps)) {
|
|
599
554
|
return (
|
|
600
|
-
|
|
601
|
-
index.assetToScy(
|
|
602
|
-
index.assetToScy(
|
|
555
|
+
guess,
|
|
556
|
+
arg.index.assetToScy(netAssetIn),
|
|
557
|
+
arg.index.assetToScy(netAssetToReserve)
|
|
603
558
|
);
|
|
604
559
|
}
|
|
605
560
|
|
|
606
|
-
if (
|
|
561
|
+
if (ptNumerator <= assetNumerator) {
|
|
607
562
|
// needs more PT
|
|
608
|
-
|
|
563
|
+
p.guessMin = guess + 1;
|
|
609
564
|
} else {
|
|
610
565
|
// needs less PT
|
|
611
|
-
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
unchecked {
|
|
615
|
-
++iter;
|
|
566
|
+
p.guessMax = guess - 1;
|
|
616
567
|
}
|
|
617
568
|
}
|
|
618
569
|
revert("approx fail");
|
|
619
570
|
}
|
|
620
571
|
|
|
621
|
-
|
|
622
|
-
MarketPreCompute memory comp,
|
|
623
|
-
int256 totalPt,
|
|
624
|
-
uint256 ptInGuess,
|
|
625
|
-
uint256 largestGoodSlope
|
|
626
|
-
) internal pure returns (bool isSlopeNonNeg, uint256 newLargestGoodSlope) {
|
|
627
|
-
if (ptInGuess <= largestGoodSlope) {
|
|
628
|
-
return (true, largestGoodSlope);
|
|
629
|
-
}
|
|
630
|
-
// it's not guaranteed that the current slope is good
|
|
631
|
-
// we therefore have to recalculate the slope
|
|
632
|
-
int256 slope = slopeFactor(totalPt, ptInGuess.neg(), comp);
|
|
633
|
-
if (slope >= 0) return (true, ptInGuess);
|
|
634
|
-
else return (false, largestGoodSlope);
|
|
635
|
-
}
|
|
572
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
636
573
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
int256 ptToMarket = -ptToAccount;
|
|
644
|
-
int256 diffAssetPtToMarket = comp.totalAsset - ptToMarket;
|
|
645
|
-
int256 sumPt = ptToMarket + totalPt;
|
|
646
|
-
|
|
647
|
-
require(diffAssetPtToMarket > 0 && sumPt > 0, "invalid ptToMarket");
|
|
648
|
-
|
|
649
|
-
int256 part1 = (ptToMarket * (totalPt + comp.totalAsset)).divDown(
|
|
650
|
-
sumPt * diffAssetPtToMarket
|
|
651
|
-
);
|
|
574
|
+
function calcAssetIn(
|
|
575
|
+
MarketState memory market,
|
|
576
|
+
MarketPreCompute memory comp,
|
|
577
|
+
uint256 netPtOut
|
|
578
|
+
) internal pure returns (uint256 netAssetIn, uint256 netAssetToReserve) {
|
|
579
|
+
(int256 assetToAccount, int256 assetToReserve) = market.calcTrade(comp, netPtOut.Int());
|
|
652
580
|
|
|
653
|
-
|
|
654
|
-
|
|
581
|
+
netAssetIn = assetToAccount.abs();
|
|
582
|
+
netAssetToReserve = assetToReserve.Uint();
|
|
583
|
+
}
|
|
655
584
|
|
|
656
|
-
|
|
585
|
+
function newApproxParamsPtOut(
|
|
586
|
+
ApproxParams memory _approx,
|
|
587
|
+
MarketPreCompute memory comp,
|
|
588
|
+
int256 totalPt
|
|
589
|
+
) internal pure returns (ApproxParamsPtOut memory res) {
|
|
590
|
+
res.guessMin = _approx.guessMin;
|
|
591
|
+
res.guessMax = Math.min(_approx.guessMax, calcMaxPtOut(comp, totalPt));
|
|
592
|
+
res.guessOffchain = _approx.guessOffchain;
|
|
593
|
+
res.maxIteration = _approx.maxIteration;
|
|
594
|
+
res.eps = _approx.eps;
|
|
595
|
+
|
|
596
|
+
require(res.guessMin <= res.guessMax && res.eps <= Math.ONE, "invalid approx params");
|
|
657
597
|
}
|
|
658
598
|
|
|
659
|
-
function calcMaxPtOut(
|
|
599
|
+
function calcMaxPtOut(MarketPreCompute memory comp, int256 totalPt)
|
|
660
600
|
internal
|
|
661
601
|
pure
|
|
662
602
|
returns (uint256)
|
|
@@ -669,23 +609,9 @@ library MarketApproxLib {
|
|
|
669
609
|
return (maxPtOut.Uint() * 999) / 1000;
|
|
670
610
|
}
|
|
671
611
|
|
|
672
|
-
function
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
function isValidApproxParams(ApproxParams memory approx) internal pure returns (bool) {
|
|
677
|
-
return (approx.guessMin <= approx.guessMax && approx.eps <= Math.ONE);
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
function getCurrentGuess(uint256 iteration, ApproxParams memory approx)
|
|
681
|
-
internal
|
|
682
|
-
pure
|
|
683
|
-
returns (uint256)
|
|
684
|
-
{
|
|
685
|
-
if (iteration == 0 && approx.guessOffchain != 0) return approx.guessOffchain;
|
|
686
|
-
else {
|
|
687
|
-
if (approx.guessMin > approx.guessMax) return approx.guessMax;
|
|
688
|
-
return (approx.guessMin + approx.guessMax) / 2;
|
|
689
|
-
}
|
|
612
|
+
function nextGuess(ApproxParamsPtOut memory p, uint256 iter) private pure returns (uint256) {
|
|
613
|
+
if (iter == 0 && p.guessOffchain != 0) return p.guessOffchain;
|
|
614
|
+
else if (p.guessMin > p.guessMax) return p.guessMax;
|
|
615
|
+
else return (p.guessMin + p.guessMax) / 2;
|
|
690
616
|
}
|
|
691
617
|
}
|