@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.
Files changed (166) hide show
  1. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/AaveV3/PendleAaveV3SCY.sol/PendleAaveV3SCY.dbg.json +1 -1
  2. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/AaveV3/PendleAaveV3SCY.sol/PendleAaveV3SCY.json +2 -2
  3. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/AaveV3/WadRayMath.sol/WadRayMath.dbg.json +1 -1
  4. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiSAvaxSCY.sol/PendleQiSAvaxSCY.dbg.json +1 -1
  5. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiSAvaxSCY.sol/PendleQiSAvaxSCY.json +2 -2
  6. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiTokenHelper.sol/PendleQiTokenHelper.dbg.json +1 -1
  7. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiTokenSCY.sol/PendleQiTokenSCY.dbg.json +1 -1
  8. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleQiTokenSCY.sol/PendleQiTokenSCY.json +2 -2
  9. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/BenQi/PendleSAvaxSCY.sol/PendleSAvaxSCY.dbg.json +1 -1
  10. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/Euler/PendleEulerSCY.sol/PendleEulerSCY.dbg.json +1 -1
  11. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleERC4626SCY.sol/PendleERC4626SCY.dbg.json +1 -1
  12. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleStargateSCY.sol/PendleStargateSCY.dbg.json +1 -1
  13. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleStargateSCY.sol/PendleStargateSCY.json +2 -2
  14. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleWstEthSCY.sol/PendleWstEthSCY.dbg.json +1 -1
  15. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/PendleYearnVaultSCY.sol/PendleYearnVaultSCY.dbg.json +1 -1
  16. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/TraderJoe/PendleSJoeSCY.sol/PendleSJoeSCY.dbg.json +1 -1
  17. package/build/artifacts/contracts/SuperComposableYield/SCY-implementations/TraderJoe/PendleSJoeSCY.sol/PendleSJoeSCY.json +2 -2
  18. package/build/artifacts/contracts/SuperComposableYield/base-implementations/SCYBase.sol/SCYBase.dbg.json +1 -1
  19. package/build/artifacts/contracts/SuperComposableYield/base-implementations/SCYBaseWithRewards.sol/SCYBaseWithRewards.dbg.json +1 -1
  20. package/build/artifacts/contracts/core/LiquidityMining/CelerAbstracts/CelerReceiverUpg.sol/CelerReceiverUpg.dbg.json +1 -1
  21. package/build/artifacts/contracts/core/LiquidityMining/CelerAbstracts/CelerSenderUpg.sol/CelerSenderUpg.dbg.json +1 -1
  22. package/build/artifacts/contracts/core/LiquidityMining/GaugeController/PendleGaugeControllerBaseUpg.sol/PendleGaugeControllerBaseUpg.dbg.json +1 -1
  23. package/build/artifacts/contracts/core/LiquidityMining/GaugeController/PendleGaugeControllerMainchainUpg.sol/PendleGaugeControllerMainchainUpg.dbg.json +1 -1
  24. package/build/artifacts/contracts/core/LiquidityMining/GaugeController/PendleGaugeControllerSidechainUpg.sol/PendleGaugeControllerSidechainUpg.dbg.json +1 -1
  25. package/build/artifacts/contracts/core/LiquidityMining/PendleGauge.sol/PendleGauge.dbg.json +1 -1
  26. package/build/artifacts/contracts/core/LiquidityMining/VotingController/PendleVotingControllerUpg.sol/PendleVotingControllerUpg.dbg.json +1 -1
  27. package/build/artifacts/contracts/core/LiquidityMining/VotingController/VotingControllerStorageUpg.sol/VotingControllerStorageUpg.dbg.json +1 -1
  28. package/build/artifacts/contracts/core/LiquidityMining/VotingEscrow/VotingEscrowPendleMainchain.sol/VotingEscrowPendleMainchain.dbg.json +1 -1
  29. package/build/artifacts/contracts/core/LiquidityMining/VotingEscrow/VotingEscrowPendleSidechain.sol/VotingEscrowPendleSidechain.dbg.json +1 -1
  30. package/build/artifacts/contracts/core/LiquidityMining/VotingEscrow/VotingEscrowTokenBase.sol/VotingEscrowTokenBase.dbg.json +1 -1
  31. package/build/artifacts/contracts/core/Market/PendleMarket.sol/PendleMarket.dbg.json +1 -1
  32. package/build/artifacts/contracts/core/Market/PendleMarket.sol/PendleMarket.json +8 -8
  33. package/build/artifacts/contracts/core/Market/PendleMarketFactory.sol/PendleMarketFactory.dbg.json +1 -1
  34. package/build/artifacts/contracts/core/Market/PendleMarketFactory.sol/PendleMarketFactory.json +2 -2
  35. package/build/artifacts/contracts/core/PendleERC20.sol/PendleERC20.dbg.json +1 -1
  36. package/build/artifacts/contracts/core/PendleRouter.sol/PendleRouter.dbg.json +1 -1
  37. package/build/artifacts/contracts/core/PendleRouter.sol/PendleRouter.json +2 -2
  38. package/build/artifacts/contracts/core/YieldContracts/InterestManagerYT.sol/InterestManagerYT.dbg.json +1 -1
  39. package/build/artifacts/contracts/core/YieldContracts/PendlePrincipalToken.sol/PendlePrincipalToken.dbg.json +1 -1
  40. package/build/artifacts/contracts/core/YieldContracts/PendleYieldContractFactory.sol/PendleYieldContractFactory.dbg.json +1 -1
  41. package/build/artifacts/contracts/core/YieldContracts/PendleYieldToken.sol/PendleYieldToken.dbg.json +1 -1
  42. package/build/artifacts/contracts/core/actions/ActionAddRemoveLiq.sol/ActionAddRemoveLiq.dbg.json +1 -1
  43. package/build/artifacts/contracts/core/actions/ActionAddRemoveLiq.sol/ActionAddRemoveLiq.json +2 -2
  44. package/build/artifacts/contracts/core/actions/ActionCallback.sol/ActionCallback.dbg.json +1 -1
  45. package/build/artifacts/contracts/core/actions/ActionCallback.sol/ActionCallback.json +2 -2
  46. package/build/artifacts/contracts/core/actions/ActionMintRedeem.sol/ActionMintRedeem.dbg.json +1 -1
  47. package/build/artifacts/contracts/core/actions/ActionMintRedeem.sol/ActionMintRedeem.json +2 -2
  48. package/build/artifacts/contracts/core/actions/ActionMisc.sol/ActionMisc.dbg.json +1 -1
  49. package/build/artifacts/contracts/core/actions/ActionSwapPT.sol/ActionSwapPT.dbg.json +1 -1
  50. package/build/artifacts/contracts/core/actions/ActionSwapPT.sol/ActionSwapPT.json +2 -2
  51. package/build/artifacts/contracts/core/actions/ActionSwapYT.sol/ActionSwapYT.dbg.json +1 -1
  52. package/build/artifacts/contracts/core/actions/ActionSwapYT.sol/ActionSwapYT.json +4 -4
  53. package/build/artifacts/contracts/core/actions/base/ActionBaseMintRedeem.sol/ActionBaseMintRedeem.dbg.json +1 -1
  54. package/build/artifacts/contracts/core/actions/base/CallbackHelper.sol/CallbackHelper.dbg.json +1 -1
  55. package/build/artifacts/contracts/interfaces/IAToken.sol/IAToken.dbg.json +1 -1
  56. package/build/artifacts/contracts/interfaces/IAavePool.sol/IAavePool.dbg.json +1 -1
  57. package/build/artifacts/contracts/interfaces/IAaveRewardsController.sol/IAaveRewardsController.dbg.json +1 -1
  58. package/build/artifacts/contracts/interfaces/IBenQiComptroller.sol/IBenQiComptroller.dbg.json +1 -1
  59. package/build/artifacts/contracts/interfaces/IBenQiInterestRateModel.sol/IBenQiInterestRateModel.dbg.json +1 -1
  60. package/build/artifacts/contracts/interfaces/ICelerMessageBus.sol/ICelerMessageBus.dbg.json +1 -1
  61. package/build/artifacts/contracts/interfaces/ICelerMessageReceiverApp.sol/ICelerMessageReceiverApp.dbg.json +1 -1
  62. package/build/artifacts/contracts/interfaces/IERC4626.sol/IERC4626.dbg.json +1 -1
  63. package/build/artifacts/contracts/interfaces/IEulerEToken.sol/IEulerEToken.dbg.json +1 -1
  64. package/build/artifacts/contracts/interfaces/IEulerMarkets.sol/IEulerMarkets.dbg.json +1 -1
  65. package/build/artifacts/contracts/interfaces/IPActionAddRemoveLiq.sol/IPActionAddRemoveLiq.dbg.json +1 -1
  66. package/build/artifacts/contracts/interfaces/IPActionMintRedeem.sol/IPActionMintRedeem.dbg.json +1 -1
  67. package/build/artifacts/contracts/interfaces/IPActionMisc.sol/IPActionMisc.dbg.json +1 -1
  68. package/build/artifacts/contracts/interfaces/IPActionSwapPT.sol/IPActionSwapPT.dbg.json +1 -1
  69. package/build/artifacts/contracts/interfaces/IPActionSwapYT.sol/IPActionSwapYT.dbg.json +1 -1
  70. package/build/artifacts/contracts/interfaces/IPActionSwapYT.sol/IPActionSwapYT.json +2 -2
  71. package/build/artifacts/contracts/interfaces/IPAllAction.sol/IPAllAction.dbg.json +1 -1
  72. package/build/artifacts/contracts/interfaces/IPAllAction.sol/IPAllAction.json +2 -2
  73. package/build/artifacts/contracts/interfaces/IPGauge.sol/IPGauge.dbg.json +1 -1
  74. package/build/artifacts/contracts/interfaces/IPGaugeController.sol/IPGaugeController.dbg.json +1 -1
  75. package/build/artifacts/contracts/interfaces/IPGaugeControllerMainchain.sol/IPGaugeControllerMainchain.dbg.json +1 -1
  76. package/build/artifacts/contracts/interfaces/IPInterestManagerYT.sol/IPInterestManagerYT.dbg.json +1 -1
  77. package/build/artifacts/contracts/interfaces/IPMarket.sol/IPMarket.dbg.json +1 -1
  78. package/build/artifacts/contracts/interfaces/IPMarketFactory.sol/IPMarketFactory.dbg.json +1 -1
  79. package/build/artifacts/contracts/interfaces/IPMarketSwapCallback.sol/IPMarketSwapCallback.dbg.json +1 -1
  80. package/build/artifacts/contracts/interfaces/IPPrincipalToken.sol/IPPrincipalToken.dbg.json +1 -1
  81. package/build/artifacts/contracts/interfaces/IPVeToken.sol/IPVeToken.dbg.json +1 -1
  82. package/build/artifacts/contracts/interfaces/IPVotingController.sol/IPVotingController.dbg.json +1 -1
  83. package/build/artifacts/contracts/interfaces/IPVotingEscrow.sol/IPVotingEscrow.dbg.json +1 -1
  84. package/build/artifacts/contracts/interfaces/IPYieldContractFactory.sol/IPYieldContractFactory.dbg.json +1 -1
  85. package/build/artifacts/contracts/interfaces/IPYieldToken.sol/IPYieldToken.dbg.json +1 -1
  86. package/build/artifacts/contracts/interfaces/IQiAvax.sol/IQiAvax.dbg.json +1 -1
  87. package/build/artifacts/contracts/interfaces/IQiErc20.sol/IQiErc20.dbg.json +1 -1
  88. package/build/artifacts/contracts/interfaces/IQiToken.sol/IQiToken.dbg.json +1 -1
  89. package/build/artifacts/contracts/interfaces/IRewardManager.sol/IRewardManager.dbg.json +1 -1
  90. package/build/artifacts/contracts/interfaces/ISAvax.sol/ISAvax.dbg.json +1 -1
  91. package/build/artifacts/contracts/interfaces/ISJoe.sol/ISJoe.dbg.json +1 -1
  92. package/build/artifacts/contracts/interfaces/IStETH.sol/IStETH.dbg.json +1 -1
  93. package/build/artifacts/contracts/interfaces/IStargateLPStaking.sol/IStargateLPStaking.dbg.json +1 -1
  94. package/build/artifacts/contracts/interfaces/IStargatePool.sol/IStargatePool.dbg.json +1 -1
  95. package/build/artifacts/contracts/interfaces/IStargateRouter.sol/IStargateRouter.dbg.json +1 -1
  96. package/build/artifacts/contracts/interfaces/ISuperComposableYield.sol/ISuperComposableYield.dbg.json +1 -1
  97. package/build/artifacts/contracts/interfaces/IWAvax.sol/IWAvax.dbg.json +1 -1
  98. package/build/artifacts/contracts/interfaces/IWETH.sol/IWETH.dbg.json +1 -1
  99. package/build/artifacts/contracts/interfaces/IWstETH.sol/IWstETH.dbg.json +1 -1
  100. package/build/artifacts/contracts/interfaces/IYearnVault.sol/IYearnVault.dbg.json +1 -1
  101. package/build/artifacts/contracts/libraries/OracleLib.sol/OracleLib.dbg.json +1 -1
  102. package/build/artifacts/contracts/libraries/RewardManager.sol/RewardManager.dbg.json +1 -1
  103. package/build/artifacts/contracts/libraries/RewardManagerAbstract.sol/RewardManagerAbstract.dbg.json +1 -1
  104. package/build/artifacts/contracts/libraries/SCY/SCYUtils.sol/SCYUtils.dbg.json +1 -1
  105. package/build/artifacts/contracts/libraries/VeBalanceLib.sol/VeBalanceLib.dbg.json +1 -1
  106. package/build/artifacts/contracts/libraries/VeHistoryLib.sol/Checkpoints.dbg.json +1 -1
  107. package/build/artifacts/contracts/libraries/helpers/ArrayLib.sol/ArrayLib.dbg.json +1 -1
  108. package/build/artifacts/contracts/libraries/helpers/ExpiryUtilsLib.sol/ExpiryUtils.dbg.json +1 -1
  109. package/build/artifacts/contracts/libraries/helpers/MiniHelpers.sol/MiniHelpers.dbg.json +1 -1
  110. package/build/artifacts/contracts/libraries/helpers/PYIndex.sol/PYIndexLib.dbg.json +1 -1
  111. package/build/artifacts/contracts/libraries/helpers/SSTORE2Deployer.sol/SSTORE2Deployer.dbg.json +1 -1
  112. package/build/artifacts/contracts/libraries/helpers/TokenHelper.sol/TokenHelper.dbg.json +1 -1
  113. package/build/artifacts/contracts/libraries/kyberswap/KyberSwapHelper.sol/KyberSwapHelper.dbg.json +1 -1
  114. package/build/artifacts/contracts/libraries/math/LogExpMath.sol/LogExpMath.dbg.json +1 -1
  115. package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/MarketApproxPtInLib.dbg.json +4 -0
  116. package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/{MarketApproxLib.json → MarketApproxPtInLib.json} +3 -3
  117. package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/MarketApproxPtOutLib.dbg.json +4 -0
  118. package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/MarketApproxPtOutLib.json +10 -0
  119. package/build/artifacts/contracts/libraries/math/MarketMathCore.sol/MarketMathCore.dbg.json +1 -1
  120. package/build/artifacts/contracts/libraries/math/Math.sol/Math.dbg.json +1 -1
  121. package/build/artifacts/contracts/libraries/math/WeekMath.sol/WeekMath.dbg.json +1 -1
  122. package/build/artifacts/contracts/libraries/solmate/SSTORE2.sol/SSTORE2.dbg.json +1 -1
  123. package/build/artifacts/contracts/offchain-helpers/MarketMathStatic.sol/MarketMathStatic.dbg.json +1 -1
  124. package/build/artifacts/contracts/offchain-helpers/MarketMathStatic.sol/MarketMathStatic.json +2 -2
  125. package/build/artifacts/contracts/offchain-helpers/RouterStatic.sol/RouterStatic.dbg.json +1 -1
  126. package/build/artifacts/contracts/offchain-helpers/RouterStatic.sol/RouterStatic.json +116 -56
  127. package/build/artifacts/contracts/periphery/BoringOwnableUpgradeable.sol/BoringOwnableUpgradeable.dbg.json +1 -1
  128. package/build/artifacts/contracts/periphery/BoringOwnableUpgradeable.sol/BoringOwnableUpgradeableData.dbg.json +1 -1
  129. package/contracts/SuperComposableYield/base-implementations/SCYBaseWithRewards.sol +6 -1
  130. package/contracts/core/actions/ActionAddRemoveLiq.sol +2 -1
  131. package/contracts/core/actions/ActionSwapPT.sol +2 -1
  132. package/contracts/core/actions/ActionSwapYT.sol +3 -2
  133. package/contracts/interfaces/IPActionSwapYT.sol +2 -2
  134. package/contracts/libraries/math/MarketApproxLib.sol +373 -447
  135. package/contracts/offchain-helpers/MarketMathStatic.sol +32 -14
  136. package/contracts/offchain-helpers/RouterStatic.sol +48 -18
  137. package/deployments/43113-markets/benqi-market-35237d.json +8 -0
  138. package/deployments/43113-markets/benqi-market-438DAA.json +8 -0
  139. package/deployments/43113-markets/benqi-market-a45e40.json +8 -0
  140. package/deployments/43113-testenv.json +22 -0
  141. package/package.json +1 -1
  142. package/typechain-types/ActionSwapYT.ts +5 -5
  143. package/typechain-types/IPActionSwapYT.ts +5 -5
  144. package/typechain-types/IPAllAction.ts +5 -5
  145. package/typechain-types/RouterStatic.ts +57 -4
  146. package/typechain-types/factories/ActionAddRemoveLiq__factory.ts +1 -1
  147. package/typechain-types/factories/ActionCallback__factory.ts +1 -1
  148. package/typechain-types/factories/ActionMintRedeem__factory.ts +1 -1
  149. package/typechain-types/factories/ActionSwapPT__factory.ts +1 -1
  150. package/typechain-types/factories/ActionSwapYT__factory.ts +3 -3
  151. package/typechain-types/factories/IPActionSwapYT__factory.ts +2 -2
  152. package/typechain-types/factories/IPAllAction__factory.ts +2 -2
  153. package/typechain-types/factories/MarketMathStatic__factory.ts +1 -1
  154. package/typechain-types/factories/PendleAaveV3SCY__factory.ts +1 -1
  155. package/typechain-types/factories/PendleMarketFactory__factory.ts +1 -1
  156. package/typechain-types/factories/PendleMarket__factory.ts +1 -1
  157. package/typechain-types/factories/PendleQiSAvaxSCY__factory.ts +1 -1
  158. package/typechain-types/factories/PendleQiTokenSCY__factory.ts +1 -1
  159. package/typechain-types/factories/PendleRouter__factory.ts +1 -1
  160. package/typechain-types/factories/PendleSJoeSCY__factory.ts +1 -1
  161. package/typechain-types/factories/PendleStargateSCY__factory.ts +1 -1
  162. package/typechain-types/factories/RouterStatic__factory.ts +61 -1
  163. package/typechain-types/hardhat.d.ts +0 -90
  164. package/typechain-types/index.ts +0 -20
  165. package/build/artifacts/contracts/libraries/math/MarketApproxLib.sol/MarketApproxLib.dbg.json +0 -4
  166. 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
- // solhint-disable reason-string, ordering
31
- library MarketApproxLib {
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 VarsSwapPtForExactScy {
39
- uint256 netPtInGuess;
40
- int256 assetToAccount;
41
- int256 assetToReserve;
42
- uint256 netAssetOut;
43
- uint256 minAssetOut;
44
- uint256 largestGoodSlope;
45
- bool isSlopeNonNeg;
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
- /// `guessMin` & `guessMax` is to guess the `netPtIn`
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 market,
52
- PYIndex index,
53
- uint256 minScyOut,
54
- uint256 blockTime,
55
- ApproxParams memory approx
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
- require(isValidApproxParams(approx), "invalid approx approx");
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
- VarsSwapPtForExactScy memory vars;
83
- MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
79
+ uint256 minAssetOut = arg.index.scyToAssetUp(arg.minScyOut);
84
80
 
85
- if (approx.guessMax == type(uint256).max) approx.guessMax = calcMaxPtIn(comp.totalAsset);
81
+ for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
82
+ (bool isGoodSlope, uint256 guess) = nextGuess(p, comp, arg.market.totalPt, iter);
86
83
 
87
- vars.minAssetOut = index.scyToAssetUp(minScyOut);
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
- (vars.assetToAccount, vars.assetToReserve) = market.calcTrade(
89
+ (uint256 netAssetOut, uint256 netAssetToReserve) = calcAssetOut(
90
+ arg.market,
104
91
  comp,
105
- vars.netPtInGuess.neg()
92
+ guess
106
93
  );
107
- vars.netAssetOut = vars.assetToAccount.Uint();
108
-
109
- if (vars.netAssetOut >= vars.minAssetOut) {
110
- approx.guessMax = vars.netPtInGuess;
111
- bool isAnswerAccepted = Math.isAGreaterApproxB(
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
- vars.netPtInGuess,
119
- index.assetToScy(vars.netAssetOut),
120
- index.assetToScy(vars.assetToReserve.Uint())
100
+ guess,
101
+ arg.index.assetToScy(netAssetOut),
102
+ arg.index.assetToScy(netAssetToReserve)
121
103
  );
104
+ }
122
105
  } else {
123
- approx.guessMin = vars.netPtInGuess;
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 VarsSwapExactScyForYt {
134
- uint256 netPtInGuess;
135
- int256 assetToAccount;
136
- int256 assetToReserve;
137
- uint256 netAssetOut;
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 market,
147
- PYIndex index,
148
- uint256 maxScyIn,
149
- uint256 blockTime,
150
- ApproxParams memory approx
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
- require(isValidApproxParams(approx), "invalid approx approx");
182
-
183
- VarsSwapExactScyForYt memory vars;
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
- vars.maxAssetIn = index.scyToAsset(maxScyIn);
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 (approx.guessMin == 0) approx.guessMin = vars.maxAssetIn;
151
+ if (p.guessMin == 0) p.guessMin = maxAssetIn;
192
152
 
193
- for (uint256 iter = 0; iter < approx.maxIteration; ) {
153
+ for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
194
154
  // ytOutGuess = ptInGuess
195
- vars.netPtInGuess = getCurrentGuess(iter, approx);
196
-
197
- (vars.isSlopeNonNeg, vars.largestGoodSlope) = updateSlope(
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
- (vars.assetToAccount, vars.assetToReserve) = market.calcTrade(
161
+ (uint256 netAssetOut, uint256 netAssetToReserve) = calcAssetOut(
162
+ arg.market,
209
163
  comp,
210
- vars.netPtInGuess.neg()
164
+ guess
211
165
  );
212
- vars.netAssetOut = vars.assetToAccount.Uint();
213
- vars.amountAssetNeedMore = vars.netPtInGuess - vars.netAssetOut;
214
-
215
- if (vars.amountAssetNeedMore <= vars.maxAssetIn) {
216
- approx.guessMin = vars.netPtInGuess;
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
- vars.netPtInGuess,
225
- index.assetToScy(vars.amountAssetNeedMore),
226
- index.assetToScy(vars.assetToReserve.Uint())
174
+ guess,
175
+ arg.index.assetToScy(netAssetToPull),
176
+ arg.index.assetToScy(netAssetToReserve)
227
177
  );
228
178
  } else {
229
- approx.guessMax = vars.netPtInGuess - 1;
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 VarsSwapExactScyForPt {
240
- uint256 maxAssetIn;
241
- uint256 ptOutGuess;
242
- int256 assetToAccount;
243
- int256 assetToReserve;
244
- uint256 netAssetIn;
185
+ struct Args6 {
186
+ MarketState market;
187
+ PYIndex index;
188
+ uint256 totalPtIn;
189
+ uint256 blockTime;
245
190
  }
246
191
 
247
- function approxSwapExactScyForPt(
248
- MarketState memory market,
249
- PYIndex index,
250
- uint256 maxScyIn,
251
- uint256 blockTime,
252
- ApproxParams memory approx
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, /*netPtOut*/
258
- uint256, /*netScyIn*/
202
+ uint256, /*netPtSwap*/
203
+ uint256, /*netScyFromSwap*/
259
204
  uint256 /*netScyToReserve*/
260
205
  )
261
206
  {
262
207
  /*
263
- the algorithm is essentially to:
264
- 1. binary search netPtOut
265
- 2. if netScyIn smaller & approx maxScyIn => answer found
266
-
267
- Psuedo code:
268
- maxAssetIn = maxScyIn -> asset
269
- binary search netPtOut:
270
- netAssetIn = calcTrade(netPtOut)
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
- require(isValidApproxParams(approx), "invalid approx approx");
218
+ Args6 memory arg = Args6(_market, _index, _totalPtIn, _blockTime);
219
+ require(arg.market.totalLp != 0, "no existing lp");
279
220
 
280
- VarsSwapExactScyForPt memory vars;
281
- MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
282
- if (approx.guessMax == type(uint256).max) {
283
- approx.guessMax = calcMaxPtOut(market.totalPt, comp);
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
- vars.maxAssetIn = index.scyToAsset(maxScyIn);
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
- for (uint256 iter = 0; iter < approx.maxIteration; ) {
289
- vars.ptOutGuess = getCurrentGuess(iter, approx);
290
- (vars.assetToAccount, vars.assetToReserve) = market.calcTrade(
234
+ (uint256 netAssetOut, uint256 netAssetToReserve) = calcAssetOut(
235
+ arg.market,
291
236
  comp,
292
- vars.ptOutGuess.Int()
237
+ guess
293
238
  );
294
- vars.netAssetIn = vars.assetToAccount.abs();
295
-
296
- if (vars.netAssetIn <= vars.maxAssetIn) {
297
- approx.guessMin = vars.ptOutGuess;
298
- bool isAnswerAccepted = Math.isASmallerApproxB(
299
- vars.netAssetIn,
300
- vars.maxAssetIn,
301
- approx.eps
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
- unchecked {
314
- ++iter;
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
- struct VarsSwapYtForExactScy {
321
- uint256 minAssetOut;
322
- uint256 ptOutGuess;
323
- int256 assetToAccount;
324
- int256 assetToReserve;
325
- uint256 netAssetOwed;
326
- uint256 netAssetOut;
327
- }
275
+ ////////////////////////////////////////////////////////////////////////////////
328
276
 
329
- function approxSwapYtForExactScy(
277
+ function calcAssetOut(
330
278
  MarketState memory market,
331
- PYIndex index,
332
- uint256 minScyOut,
333
- uint256 blockTime,
334
- ApproxParams memory approx
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, /*netYtIn*/
340
- uint256, /*netScyOut*/
385
+ uint256, /*netPtOut*/
386
+ uint256, /*netScyIn*/
341
387
  uint256 /*netScyToReserve*/
342
388
  )
343
389
  {
344
390
  /*
345
- the algorithm is essentially to:
346
- 1. Binary search netPtOut (therefore netScyIn) (netYtIn == netPtOut)
347
- 2. flashswap netPtOut (now we owe netScyIn)
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
- require(isValidApproxParams(approx), "invalid approx approx");
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
- VarsSwapYtForExactScy memory vars;
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
- vars.minAssetOut = index.scyToAssetUp(minScyOut);
402
+ for (uint256 iter = 0; iter < p.maxIteration; ++iter) {
403
+ uint256 guess = nextGuess(p, iter);
374
404
 
375
- for (uint256 iter = 0; iter < approx.maxIteration; ) {
376
- // ytInGuess = ptOutGuess
377
- vars.ptOutGuess = getCurrentGuess(iter, approx);
405
+ (uint256 netAssetIn, uint256 netAssetToReserve) = calcAssetIn(arg.market, comp, guess);
378
406
 
379
- (vars.assetToAccount, vars.assetToReserve) = market.calcTrade(
380
- comp,
381
- vars.ptOutGuess.Int()
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
- vars.ptOutGuess,
395
- index.assetToScy(vars.netAssetOut),
396
- index.assetToScy(vars.assetToReserve.Uint())
412
+ guess,
413
+ arg.index.assetToScy(netAssetIn),
414
+ arg.index.assetToScy(netAssetToReserve)
397
415
  );
398
- }
399
416
  } else {
400
- approx.guessMin = vars.ptOutGuess + 1;
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 VarsSwapPtToAddLiquidity {
411
- uint256 netPtInGuess;
412
- int256 assetToAccount;
413
- int256 assetToReserve;
414
- uint256 netAssetOut;
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 approxSwapPtToAddLiquidity(
425
- MarketState memory market,
426
- PYIndex index,
427
- uint256 netPtAdded,
428
- uint256 blockTime,
429
- ApproxParams memory approx
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, /*netPtIn*/
440
+ uint256, /*netYtIn*/
435
441
  uint256, /*netScyOut*/
436
442
  uint256 /*netScyToReserve*/
437
443
  )
438
444
  {
439
445
  /*
440
- The algorithm is essentially to:
441
- 1. Binary search netPtIn (therefore netScyOut)
442
- 2. Swap netPtIn for netScyOut
443
- 3. Use (netPtAdded - netPtIn) and netScyOut to mint LP
444
- 4. If (netPtAdded - netPtIn) / netScyOut ratio is close enough to the market's PT/SCY ratio
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
- require(market.totalLp != 0, "no existing lp");
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
- VarsSwapPtToAddLiquidity memory vars;
453
- MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
457
+ uint256 minAssetOut = arg.index.scyToAssetUp(arg.minScyOut);
454
458
 
455
- if (approx.guessMax == type(uint256).max) {
456
- // ensures that netPtIn is always valid and not greater than netPtAdded
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
- for (uint256 iter = 0; iter < approx.maxIteration; ) {
463
- vars.netPtInGuess = getCurrentGuess(iter, approx);
464
-
465
- (vars.isSlopeNonNeg, vars.largestGoodSlope) = updateSlope(
462
+ (uint256 netAssetOwed, uint256 netAssetToReserve) = calcAssetIn(
463
+ arg.market,
466
464
  comp,
467
- market.totalPt,
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
- (vars.assetToAccount, vars.assetToReserve) = market.calcTrade(
477
- comp,
478
- vars.netPtInGuess.neg()
479
- );
468
+ uint256 netAssetOut = guess - netAssetOwed;
480
469
 
481
- vars.netAssetOut = vars.assetToAccount.Uint();
482
- vars.netPtRemaining = netPtAdded - vars.netPtInGuess;
483
- vars.newTotalPt = market.totalPt.Uint() + vars.netPtInGuess;
484
- vars.newTotalAsset = (comp.totalAsset - vars.assetToAccount - vars.assetToReserve)
485
- .Uint();
486
-
487
- // it is desired that
488
- // netAssetOut / newTotalAsset = netPtRemaining / newTotalPt
489
- // which is equivalent to
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
- // needs less asset --> swap less PT
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 VarsSwapScyToAddLiquidity {
519
- uint256 netAssetAdded;
520
- uint256 ptOutGuess;
521
- int256 assetToAccount;
522
- int256 assetToReserve;
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 market,
533
- PYIndex index,
534
- uint256 netScyAdded,
535
- uint256 blockTime,
536
- ApproxParams memory approx
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, /*netPtOut*/
542
- uint256, /*netScyIn*/
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 (netScyAdded - netScyIn) to mint LP
551
- 4. If netPtOut / (netScyAdded - netScyIn) ratio is close enough to the market's PT/SCY ratio
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
- VarsSwapScyToAddLiquidity memory vars;
559
- MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
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
- require(isValidApproxParams(approx), "invalid approx");
521
+ MarketPreCompute memory comp = arg.market.getMarketPreCompute(arg.index, arg.blockTime);
522
+ ApproxParamsPtOut memory p = newApproxParamsPtOut(_approx, comp, arg.market.totalPt);
565
523
 
566
- vars.netAssetAdded = index.scyToAsset(netScyAdded);
524
+ uint256 totalAssetIn = arg.index.scyToAsset(arg.totalScyIn);
567
525
 
568
- for (uint256 iter = 0; iter < approx.maxIteration; ) {
569
- vars.ptOutGuess = getCurrentGuess(iter, approx);
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
- vars.netAssetIn = vars.assetToAccount.abs();
529
+ (uint256 netAssetIn, uint256 netAssetToReserve) = calcAssetIn(arg.market, comp, guess);
576
530
 
577
- if (vars.netAssetIn > vars.netAssetAdded) {
578
- approx.guessMax = vars.ptOutGuess - 1;
579
- unchecked {
580
- ++iter;
581
- }
531
+ if (netAssetIn > totalAssetIn) {
532
+ p.guessMax = guess - 1;
582
533
  continue;
583
534
  }
584
535
 
585
- vars.netAssetRemaining = vars.netAssetAdded - vars.netAssetIn;
586
- vars.newTotalPt = market.totalPt.Uint() - vars.ptOutGuess;
587
- vars.newTotalAsset = (comp.totalAsset - vars.assetToAccount - vars.assetToReserve)
588
- .Uint();
536
+ uint256 ptNumerator;
537
+ uint256 assetNumerator;
589
538
 
590
- // it is desired that
591
- // ptOutGuess / newTotalPt = netAssetRemaining / newTotalAsset
592
- // which is equivalent to
593
- // ptOutGuess * newTotalAsset = netAssetRemaining * newTotalPt
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
- vars.ptNumerator = vars.ptOutGuess * vars.newTotalAsset;
596
- vars.assetNumerator = vars.netAssetRemaining * vars.newTotalPt;
544
+ // it is desired that
545
+ // guess / newTotalPt = netAssetRemaining / newTotalAsset
546
+ // which is equivalent to
547
+ // guess * newTotalAsset = netAssetRemaining * newTotalPt
597
548
 
598
- if (Math.isAApproxB(vars.ptNumerator, vars.assetNumerator, approx.eps)) {
549
+ ptNumerator = guess * newTotalAsset;
550
+ assetNumerator = netAssetRemaining * newTotalPt;
551
+ }
552
+
553
+ if (Math.isAApproxB(ptNumerator, assetNumerator, p.eps)) {
599
554
  return (
600
- vars.ptOutGuess,
601
- index.assetToScy(vars.netAssetIn),
602
- index.assetToScy(vars.assetToReserve.Uint())
555
+ guess,
556
+ arg.index.assetToScy(netAssetIn),
557
+ arg.index.assetToScy(netAssetToReserve)
603
558
  );
604
559
  }
605
560
 
606
- if (vars.ptNumerator <= vars.assetNumerator) {
561
+ if (ptNumerator <= assetNumerator) {
607
562
  // needs more PT
608
- approx.guessMin = vars.ptOutGuess + 1;
563
+ p.guessMin = guess + 1;
609
564
  } else {
610
565
  // needs less PT
611
- approx.guessMax = vars.ptOutGuess - 1;
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
- function updateSlope(
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
- // ptToMarket < totalAsset && totalPt
638
- function slopeFactor(
639
- int256 totalPt,
640
- int256 ptToAccount,
641
- MarketPreCompute memory comp
642
- ) internal pure returns (int256) {
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
- int256 part2 = sumPt.divDown(diffAssetPtToMarket).ln();
654
- int256 part3 = Math.IONE.divDown(comp.rateScalar);
581
+ netAssetIn = assetToAccount.abs();
582
+ netAssetToReserve = assetToReserve.Uint();
583
+ }
655
584
 
656
- return comp.rateAnchor - (part1 - part2).mulDown(part3);
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(int256 totalPt, MarketPreCompute memory comp)
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 calcMaxPtIn(int256 totalAsset) internal pure returns (uint256) {
673
- return totalAsset.Uint() - 1;
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
  }