@dolomite-exchange/dolomite-margin 0.2.6 → 0.2.7

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 (200) hide show
  1. package/build/contracts/Account.json +11 -11
  2. package/build/contracts/Actions.json +11 -11
  3. package/build/contracts/Address.json +1 -1
  4. package/build/contracts/Admin.json +23 -23
  5. package/build/contracts/AdminImpl.json +35 -307
  6. package/build/contracts/AdvancedMath.json +7 -7
  7. package/build/contracts/AmmRebalancerProxy.json +577 -621
  8. package/build/contracts/AmmRebalancerProxyV1.json +78 -32
  9. package/build/contracts/Babylonian.json +1 -1
  10. package/build/contracts/Bits.json +9 -9
  11. package/build/contracts/Cache.json +13 -13
  12. package/build/contracts/ChainlinkPriceOracleV1.json +16 -16
  13. package/build/contracts/Context.json +1 -1
  14. package/build/contracts/CustomTestToken.json +9 -9
  15. package/build/contracts/Decimal.json +9 -9
  16. package/build/contracts/DelayedMultiSig.json +9 -9
  17. package/build/contracts/DolomiteAmmERC20.json +11 -11
  18. package/build/contracts/DolomiteAmmFactory.json +14 -52
  19. package/build/contracts/DolomiteAmmLibrary.json +24 -24
  20. package/build/contracts/DolomiteAmmPair.json +27 -27
  21. package/build/contracts/DolomiteAmmRouterProxy.json +30 -363
  22. package/build/contracts/DolomiteMargin.json +21 -67
  23. package/build/contracts/DoubleExponentInterestSetter.json +15 -21
  24. package/build/contracts/EnumerableSet.json +7 -7
  25. package/build/contracts/ErroringOmiseToken.json +9 -9
  26. package/build/contracts/ErroringToken.json +10 -10
  27. package/build/contracts/Events.json +17 -17
  28. package/build/contracts/ExcessivelySafeCall.json +35 -35
  29. package/build/contracts/Exchange.json +15 -15
  30. package/build/contracts/Expiry.json +36 -36
  31. package/build/contracts/Getters.json +33 -33
  32. package/build/contracts/IAutoTrader.json +9 -9
  33. package/build/contracts/ICallee.json +7 -7
  34. package/build/contracts/IChainlinkAggregator.json +5 -5
  35. package/build/contracts/IDolomiteAmmERC20.json +5 -5
  36. package/build/contracts/IDolomiteAmmFactory.json +9 -9
  37. package/build/contracts/IDolomiteAmmPair.json +9 -9
  38. package/build/contracts/IDolomiteMargin.json +23 -23
  39. package/build/contracts/IERC20.json +1 -1
  40. package/build/contracts/IERC20Detailed.json +5 -5
  41. package/build/contracts/IExchangeWrapper.json +5 -5
  42. package/build/contracts/IExpiry.json +9 -9
  43. package/build/contracts/IInterestSetter.json +7 -7
  44. package/build/contracts/ILiquidationCallback.json +7 -7
  45. package/build/contracts/IMakerOracle.json +5 -5
  46. package/build/contracts/IOasisDex.json +5 -5
  47. package/build/contracts/IPriceOracle.json +7 -7
  48. package/build/contracts/IRecyclable.json +9 -9
  49. package/build/contracts/ITransferProxy.json +5 -5
  50. package/build/contracts/IUniswapV2Callee.json +5 -5
  51. package/build/contracts/IUniswapV2Factory.json +5 -5
  52. package/build/contracts/IUniswapV2Pair.json +5 -5
  53. package/build/contracts/IUniswapV2Router.json +5 -5
  54. package/build/contracts/IWETH.json +5 -5
  55. package/build/contracts/Interest.json +15 -15
  56. package/build/contracts/LiquidateOrVaporizeImpl.json +32 -83
  57. package/build/contracts/LiquidatorProxyHelper.json +23 -23
  58. package/build/contracts/LiquidatorProxyV1.json +30 -36
  59. package/build/contracts/LiquidatorProxyV1WithAmm.json +49 -105
  60. package/build/contracts/Math.json +1 -1
  61. package/build/contracts/Migrations.json +8 -14
  62. package/build/contracts/Monetary.json +7 -7
  63. package/build/contracts/MultiCall.json +8 -14
  64. package/build/contracts/MultiSig.json +7 -7
  65. package/build/contracts/OmiseToken.json +8 -8
  66. package/build/contracts/OnlyDolomiteMargin.json +11 -11
  67. package/build/contracts/Operation.json +15 -15
  68. package/build/contracts/OperationImpl.json +39 -47
  69. package/build/contracts/Ownable.json +1 -1
  70. package/build/contracts/PartiallyDelayedMultiSig.json +9 -9
  71. package/build/contracts/PayableProxy.json +17 -23
  72. package/build/contracts/Permission.json +11 -11
  73. package/build/contracts/PolynomialInterestSetter.json +13 -13
  74. package/build/contracts/RecyclableTokenProxy.json +25 -25
  75. package/build/contracts/ReentrancyGuard.json +1 -1
  76. package/build/contracts/Require.json +7 -7
  77. package/build/contracts/SafeERC20.json +1 -1
  78. package/build/contracts/SafeETH.json +7 -7
  79. package/build/contracts/SafeLiquidationCallback.json +17 -17
  80. package/build/contracts/SafeMath.json +1 -1
  81. package/build/contracts/SignedOperationProxy.json +21 -104
  82. package/build/contracts/SimpleFeeOwner.json +18 -63
  83. package/build/contracts/State.json +9 -9
  84. package/build/contracts/Storage.json +37 -37
  85. package/build/contracts/TestAmmRebalancerProxy.json +32 -58
  86. package/build/contracts/TestAutoTrader.json +22 -22
  87. package/build/contracts/TestBtcUsdChainlinkAggregator.json +10 -10
  88. package/build/contracts/TestCallee.json +19 -19
  89. package/build/contracts/TestChainlinkPriceOracleV1.json +10 -94
  90. package/build/contracts/TestCounter.json +7 -7
  91. package/build/contracts/TestDaiUsdChainlinkAggregator.json +11 -11
  92. package/build/contracts/TestDolomiteMargin.json +22 -22
  93. package/build/contracts/TestDoubleExponentInterestSetter.json +10 -10
  94. package/build/contracts/TestEthUsdChainlinkAggregator.json +11 -11
  95. package/build/contracts/TestExchangeWrapper.json +28 -28
  96. package/build/contracts/TestInterestSetter.json +13 -13
  97. package/build/contracts/TestLib.json +22 -22
  98. package/build/contracts/TestLinkUsdChainlinkAggregator.json +11 -11
  99. package/build/contracts/TestLiquidateCallback.json +719 -719
  100. package/build/contracts/TestLiquidationCallback.json +13 -13
  101. package/build/contracts/TestLrcEthChainlinkAggregator.json +11 -11
  102. package/build/contracts/TestMakerOracle.json +10 -10
  103. package/build/contracts/TestMaticUsdChainlinkAggregator.json +10 -10
  104. package/build/contracts/TestOasisDex.json +12 -12
  105. package/build/contracts/TestOperationImpl.json +14 -14
  106. package/build/contracts/TestPolynomialInterestSetter.json +10 -10
  107. package/build/contracts/TestPriceAggregator.json +9 -9
  108. package/build/contracts/TestPriceOracle.json +13 -13
  109. package/build/contracts/TestRecyclableToken.json +9 -9
  110. package/build/contracts/TestSimpleCallee.json +15 -15
  111. package/build/contracts/TestToken.json +9 -9
  112. package/build/contracts/TestTrader.json +17 -17
  113. package/build/contracts/TestUniswapAmmRebalancerProxy.json +16 -16
  114. package/build/contracts/TestUsdcUsdChainlinkAggregator.json +11 -11
  115. package/build/contracts/TestWETH.json +9 -9
  116. package/build/contracts/Time.json +9 -9
  117. package/build/contracts/Token.json +9 -9
  118. package/build/contracts/TokenA.json +10 -10
  119. package/build/contracts/TokenB.json +10 -10
  120. package/build/contracts/TokenC.json +10 -10
  121. package/build/contracts/TokenD.json +10 -10
  122. package/build/contracts/TokenE.json +10 -10
  123. package/build/contracts/TokenF.json +10 -10
  124. package/build/contracts/TransferProxy.json +22 -28
  125. package/build/contracts/TypedSignature.json +9 -9
  126. package/build/contracts/Types.json +9 -9
  127. package/build/contracts/UQ112x112.json +7 -7
  128. package/build/contracts/UniswapV2ERC20.json +7 -7
  129. package/build/contracts/UniswapV2Factory.json +12 -12
  130. package/build/contracts/UniswapV2Library.json +20 -20
  131. package/build/contracts/UniswapV2Pair.json +17 -17
  132. package/build/contracts/UniswapV2Router02.json +16 -16
  133. package/build/contracts/WETH9.json +1 -1
  134. package/contracts/external/amm/DolomiteAmmERC20.sol +135 -0
  135. package/contracts/external/amm/DolomiteAmmFactory.sol +122 -0
  136. package/contracts/external/amm/DolomiteAmmPair.sol +573 -0
  137. package/contracts/external/amm/SimpleFeeOwner.sol +107 -0
  138. package/contracts/external/helpers/LiquidatorProxyHelper.sol +252 -0
  139. package/contracts/external/helpers/OnlyDolomiteMargin.sol +63 -0
  140. package/contracts/external/interestsetters/DoubleExponentInterestSetter.sol +212 -0
  141. package/contracts/external/interestsetters/PolynomialInterestSetter.sol +205 -0
  142. package/contracts/external/interfaces/IChainlinkAggregator.sol +33 -0
  143. package/contracts/external/interfaces/IDolomiteAmmERC20.sol +52 -0
  144. package/contracts/external/interfaces/IDolomiteAmmFactory.sol +42 -0
  145. package/contracts/external/interfaces/IDolomiteAmmPair.sol +116 -0
  146. package/contracts/external/interfaces/IExpiry.sol +70 -0
  147. package/contracts/external/interfaces/IMakerOracle.sol +52 -0
  148. package/contracts/external/interfaces/IOasisDex.sol +326 -0
  149. package/contracts/external/interfaces/ITransferProxy.sol +53 -0
  150. package/contracts/external/interfaces/IUniswapV2Router.sol +134 -0
  151. package/contracts/external/lib/AdvancedMath.sol +23 -0
  152. package/contracts/external/lib/DolomiteAmmLibrary.sol +323 -0
  153. package/contracts/external/lib/TypedSignature.sol +120 -0
  154. package/contracts/external/lib/UQ112x112.sol +22 -0
  155. package/contracts/external/multisig/DelayedMultiSig.sol +206 -0
  156. package/contracts/external/multisig/MultiSig.sol +571 -0
  157. package/contracts/external/multisig/PartiallyDelayedMultiSig.sol +174 -0
  158. package/contracts/external/oracles/ChainlinkPriceOracleV1.sol +197 -0
  159. package/contracts/external/oracles/TestChainlinkPriceOracleV1.sol +98 -0
  160. package/contracts/external/proxies/AmmRebalancerProxyV1.sol +465 -0
  161. package/contracts/external/proxies/DolomiteAmmRouterProxy.sol +877 -0
  162. package/contracts/external/proxies/LiquidatorProxyV1.sol +507 -0
  163. package/contracts/external/proxies/LiquidatorProxyV1WithAmm.sol +574 -0
  164. package/contracts/external/proxies/PayableProxy.sol +146 -0
  165. package/contracts/external/proxies/RecyclableTokenProxy.sol +463 -0
  166. package/contracts/external/proxies/SignedOperationProxy.sol +553 -0
  167. package/contracts/external/proxies/TransferProxy.sol +207 -0
  168. package/contracts/external/traders/Expiry.sol +532 -0
  169. package/contracts/external/uniswap-v2/UniswapV2ERC20.sol +118 -0
  170. package/contracts/external/uniswap-v2/UniswapV2Factory.sol +67 -0
  171. package/contracts/external/uniswap-v2/UniswapV2Pair.sol +283 -0
  172. package/contracts/external/uniswap-v2/UniswapV2Router02.sol +566 -0
  173. package/contracts/external/uniswap-v2/interfaces/IUniswapV2Callee.sol +13 -0
  174. package/contracts/external/uniswap-v2/interfaces/IUniswapV2Factory.sol +18 -0
  175. package/contracts/external/uniswap-v2/interfaces/IUniswapV2Pair.sol +67 -0
  176. package/contracts/external/uniswap-v2/interfaces/IWETH.sol +7 -0
  177. package/contracts/external/uniswap-v2/libraries/SafeETH.sol +29 -0
  178. package/contracts/external/uniswap-v2/libraries/UniswapV2Library.sol +117 -0
  179. package/contracts/external/utils/MultiCall.sol +95 -0
  180. package/contracts/protocol/impl/artifacts/OperationImpl.json +80 -0
  181. package/contracts/protocol/impl/artifacts/OperationImpl_metadata.json +193 -0
  182. package/dist/build/published_contracts/AdminImpl.json +2 -2
  183. package/dist/build/published_contracts/AmmRebalancerProxyV1.json +5 -0
  184. package/dist/build/published_contracts/ChainlinkPriceOracleV1.json +1 -1
  185. package/dist/build/published_contracts/DolomiteAmmFactory.json +1 -1
  186. package/dist/build/published_contracts/DolomiteAmmRouterProxy.json +1 -1
  187. package/dist/build/published_contracts/DoubleExponentInterestSetter.json +2 -2
  188. package/dist/build/published_contracts/Expiry.json +1 -1
  189. package/dist/build/published_contracts/LiquidatorProxyV1.json +1 -1
  190. package/dist/build/published_contracts/LiquidatorProxyV1WithAmm.json +1 -1
  191. package/dist/build/published_contracts/MultiCall.json +1 -1
  192. package/dist/build/published_contracts/PayableProxy.json +2 -2
  193. package/dist/build/published_contracts/SignedOperationProxy.json +2 -2
  194. package/dist/build/published_contracts/SimpleFeeOwner.json +1 -1
  195. package/dist/build/published_contracts/TestUniswapAmmRebalancerProxy.json +140 -0
  196. package/dist/build/published_contracts/TransferProxy.json +1 -1
  197. package/dist/src/lib/Contracts.d.ts +3 -1
  198. package/dist/src/lib/Contracts.js +7 -3
  199. package/dist/src/lib/Contracts.js.map +1 -1
  200. package/package.json +2 -1
@@ -0,0 +1,877 @@
1
+ /*
2
+
3
+ Copyright 2021 Dolomite.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ */
18
+
19
+ pragma solidity ^0.5.7;
20
+ pragma experimental ABIEncoderV2;
21
+
22
+ import "@openzeppelin/contracts/math/SafeMath.sol";
23
+ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
24
+
25
+ import "../../protocol/interfaces/IDolomiteMargin.sol";
26
+ import "../../protocol/lib/Events.sol";
27
+
28
+ import "../../protocol/lib/Account.sol";
29
+ import "../../protocol/lib/Actions.sol";
30
+ import "../../protocol/lib/Require.sol";
31
+ import "../../protocol/lib/Types.sol";
32
+
33
+ import "../lib/TypedSignature.sol";
34
+ import "../lib/DolomiteAmmLibrary.sol";
35
+
36
+ import "../interfaces/IExpiry.sol";
37
+ import "../interfaces/IDolomiteAmmFactory.sol";
38
+ import "../interfaces/IDolomiteAmmPair.sol";
39
+
40
+
41
+ /**
42
+ * @title DolomiteAmmRouterProxy
43
+ * @author Dolomite
44
+ *
45
+ * Contract for routing trades to the Dolomite AMM pools and potentially opening margin positions
46
+ */
47
+ contract DolomiteAmmRouterProxy is ReentrancyGuard {
48
+ using SafeMath for uint;
49
+
50
+ // ============ Constants ============
51
+
52
+ bytes32 constant internal FILE = "DolomiteAmmRouterProxy";
53
+
54
+ // ============ Structs ============
55
+
56
+ struct ModifyPositionParams {
57
+ uint accountNumber;
58
+ Types.AssetAmount amountIn;
59
+ Types.AssetAmount amountOut;
60
+ address[] tokenPath;
61
+ /// the token to be deposited/withdrawn to/from account number. To not perform any margin deposits or
62
+ /// withdrawals, simply set this to `address(0)`
63
+ address depositToken;
64
+ /// a positive number means funds are deposited to `accountNumber` from accountNumber zero
65
+ /// a negative number means funds are withdrawn from `accountNumber` and moved to accountNumber zero
66
+ bool isPositiveMarginDeposit;
67
+ /// the amount of the margin deposit/withdrawal, in wei
68
+ uint marginDeposit;
69
+ /// the amount of seconds from the time at which the position is opened to expiry. 0 for no expiration
70
+ uint expiryTimeDelta;
71
+ }
72
+
73
+ struct ModifyPositionCache {
74
+ ModifyPositionParams params;
75
+ IDolomiteMargin dolomiteMargin;
76
+ IDolomiteAmmFactory ammFactory;
77
+ address account;
78
+ uint[] marketPath;
79
+ uint[] amountsWei;
80
+ uint marginDepositDeltaWei;
81
+ }
82
+
83
+ struct PermitSignature {
84
+ bool approveMax;
85
+ uint8 v;
86
+ bytes32 r;
87
+ bytes32 s;
88
+ }
89
+
90
+ // ============ Events ============
91
+
92
+ event MarginPositionOpen(
93
+ address indexed user,
94
+ uint indexed accountIndex,
95
+ address inputToken,
96
+ address outputToken,
97
+ address depositToken,
98
+ Events.BalanceUpdate inputBalanceUpdate, // the amount of borrow amount being sold to purchase collateral
99
+ Events.BalanceUpdate outputBalanceUpdate, // the amount of collateral purchased by the borrowed amount
100
+ Events.BalanceUpdate marginDepositUpdate
101
+ );
102
+
103
+ event MarginPositionClose(
104
+ address indexed user,
105
+ uint indexed accountIndex,
106
+ address inputToken,
107
+ address outputToken,
108
+ address withdrawalToken,
109
+ Events.BalanceUpdate inputBalanceUpdate, // the amount of held amount being sold to repay debt
110
+ Events.BalanceUpdate outputBalanceUpdate, // the amount of borrow amount being repaid
111
+ Events.BalanceUpdate marginWithdrawalUpdate
112
+ );
113
+
114
+ modifier ensure(uint deadline) {
115
+ Require.that(
116
+ deadline >= block.timestamp,
117
+ FILE,
118
+ "deadline expired",
119
+ deadline,
120
+ block.timestamp
121
+ );
122
+ _;
123
+ }
124
+
125
+ // ============ State Variables ============
126
+
127
+ IDolomiteMargin public DOLOMITE_MARGIN;
128
+ IDolomiteAmmFactory public DOLOMITE_AMM_FACTORY;
129
+ address public EXPIRY;
130
+
131
+ constructor(
132
+ address dolomiteMargin,
133
+ address dolomiteAmmFactory,
134
+ address expiry
135
+ ) public {
136
+ DOLOMITE_MARGIN = IDolomiteMargin(dolomiteMargin);
137
+ DOLOMITE_AMM_FACTORY = IDolomiteAmmFactory(dolomiteAmmFactory);
138
+ EXPIRY = expiry;
139
+ }
140
+
141
+ function getPairInitCodeHash() external pure returns (bytes32) {
142
+ return DolomiteAmmLibrary.getPairInitCodeHash();
143
+ }
144
+
145
+ function addLiquidity(
146
+ address to,
147
+ uint fromAccountNumber,
148
+ address tokenA,
149
+ address tokenB,
150
+ uint amountADesired,
151
+ uint amountBDesired,
152
+ uint amountAMinWei,
153
+ uint amountBMinWei,
154
+ uint deadline
155
+ )
156
+ external
157
+ ensure(deadline)
158
+ returns (uint amountAWei, uint amountBWei, uint liquidity) {
159
+ (amountAWei, amountBWei) = _addLiquidity(
160
+ tokenA,
161
+ tokenB,
162
+ amountADesired,
163
+ amountBDesired,
164
+ amountAMinWei,
165
+ amountBMinWei
166
+ );
167
+ address pair = DolomiteAmmLibrary.pairFor(address(DOLOMITE_AMM_FACTORY), tokenA, tokenB);
168
+
169
+ // solium-disable indentation, arg-overflow
170
+ {
171
+ Account.Info[] memory accounts = new Account.Info[](2);
172
+ accounts[0] = Account.Info(msg.sender, fromAccountNumber);
173
+ accounts[1] = Account.Info(pair, 0);
174
+
175
+ uint marketIdA = DOLOMITE_MARGIN.getMarketIdByTokenAddress(tokenA);
176
+ uint marketIdB = DOLOMITE_MARGIN.getMarketIdByTokenAddress(tokenB);
177
+
178
+ Actions.ActionArgs[] memory actions = new Actions.ActionArgs[](2);
179
+ actions[0] = _encodeTransferAction(0, 1, marketIdA, amountAWei);
180
+ actions[1] = _encodeTransferAction(0, 1, marketIdB, amountBWei);
181
+ DOLOMITE_MARGIN.operate(accounts, actions);
182
+ }
183
+ // solium-enable indentation, arg-overflow
184
+
185
+ liquidity = IDolomiteAmmPair(pair).mint(to);
186
+ }
187
+
188
+ function swapExactTokensForTokens(
189
+ uint accountNumber,
190
+ uint amountInWei,
191
+ uint amountOutMinWei,
192
+ address[] calldata tokenPath,
193
+ uint deadline
194
+ )
195
+ external
196
+ ensure(deadline) {
197
+ _swapExactTokensForTokensAndModifyPosition(
198
+ ModifyPositionCache({
199
+ params : ModifyPositionParams({
200
+ accountNumber : accountNumber,
201
+ amountIn : _defaultAssetAmount(amountInWei),
202
+ amountOut : _defaultAssetAmount(amountOutMinWei),
203
+ tokenPath : tokenPath,
204
+ depositToken : address(0),
205
+ isPositiveMarginDeposit : false,
206
+ marginDeposit : 0,
207
+ expiryTimeDelta : 0
208
+ }),
209
+ dolomiteMargin : DOLOMITE_MARGIN,
210
+ ammFactory : DOLOMITE_AMM_FACTORY,
211
+ account : msg.sender,
212
+ marketPath : new uint[](0),
213
+ amountsWei : new uint[](0),
214
+ marginDepositDeltaWei : 0
215
+ })
216
+ );
217
+ }
218
+
219
+ function getParamsForSwapExactTokensForTokens(
220
+ address account,
221
+ uint accountNumber,
222
+ uint amountInWei,
223
+ uint amountOutMinWei,
224
+ address[] calldata tokenPath
225
+ )
226
+ external view returns (Account.Info[] memory, Actions.ActionArgs[] memory) {
227
+ return _getParamsForSwapExactTokensForTokens(
228
+ ModifyPositionCache({
229
+ params : ModifyPositionParams({
230
+ accountNumber : accountNumber,
231
+ amountIn : _defaultAssetAmount(amountInWei),
232
+ amountOut : _defaultAssetAmount(amountOutMinWei),
233
+ tokenPath : tokenPath,
234
+ depositToken : address(0),
235
+ isPositiveMarginDeposit : false,
236
+ marginDeposit : 0,
237
+ expiryTimeDelta : 0
238
+ }),
239
+ dolomiteMargin : DOLOMITE_MARGIN,
240
+ ammFactory : DOLOMITE_AMM_FACTORY,
241
+ account : account,
242
+ marketPath : new uint[](0),
243
+ amountsWei : new uint[](0),
244
+ marginDepositDeltaWei : 0
245
+ })
246
+ );
247
+ }
248
+
249
+ function swapTokensForExactTokens(
250
+ uint accountNumber,
251
+ uint amountInMaxWei,
252
+ uint amountOutWei,
253
+ address[] calldata tokenPath,
254
+ uint deadline
255
+ )
256
+ external
257
+ ensure(deadline) {
258
+ _swapTokensForExactTokensAndModifyPosition(
259
+ ModifyPositionCache({
260
+ params : ModifyPositionParams({
261
+ accountNumber : accountNumber,
262
+ amountIn : _defaultAssetAmount(amountInMaxWei),
263
+ amountOut : _defaultAssetAmount(amountOutWei),
264
+ tokenPath : tokenPath,
265
+ depositToken : address(0),
266
+ isPositiveMarginDeposit : false,
267
+ marginDeposit : 0,
268
+ expiryTimeDelta : 0
269
+ }),
270
+ dolomiteMargin : DOLOMITE_MARGIN,
271
+ ammFactory : DOLOMITE_AMM_FACTORY,
272
+ account : msg.sender,
273
+ marketPath : new uint[](0),
274
+ amountsWei : new uint[](0),
275
+ marginDepositDeltaWei : 0
276
+ })
277
+ );
278
+ }
279
+
280
+ function getParamsForSwapTokensForExactTokens(
281
+ address account,
282
+ uint accountNumber,
283
+ uint amountInMaxWei,
284
+ uint amountOutWei,
285
+ address[] calldata tokenPath
286
+ )
287
+ external view returns (Account.Info[] memory, Actions.ActionArgs[] memory) {
288
+ return _getParamsForSwapTokensForExactTokens(
289
+ ModifyPositionCache({
290
+ params : ModifyPositionParams({
291
+ accountNumber : accountNumber,
292
+ amountIn : _defaultAssetAmount(amountInMaxWei),
293
+ amountOut : _defaultAssetAmount(amountOutWei),
294
+ tokenPath : tokenPath,
295
+ depositToken : address(0),
296
+ isPositiveMarginDeposit : false,
297
+ marginDeposit : 0,
298
+ expiryTimeDelta : 0
299
+ }),
300
+ dolomiteMargin : DOLOMITE_MARGIN,
301
+ ammFactory : DOLOMITE_AMM_FACTORY,
302
+ account : account,
303
+ marketPath : new uint[](0),
304
+ amountsWei : new uint[](0),
305
+ marginDepositDeltaWei : 0
306
+ })
307
+ );
308
+ }
309
+
310
+ function removeLiquidity(
311
+ address to,
312
+ uint toAccountNumber,
313
+ address tokenA,
314
+ address tokenB,
315
+ uint liquidity,
316
+ uint amountAMinWei,
317
+ uint amountBMinWei,
318
+ uint deadline
319
+ ) public ensure(deadline) returns (uint amountAWei, uint amountBWei) {
320
+ address pair = DolomiteAmmLibrary.pairFor(address(DOLOMITE_AMM_FACTORY), tokenA, tokenB);
321
+ // send liquidity to pair
322
+ IDolomiteAmmPair(pair).transferFrom(msg.sender, pair, liquidity);
323
+
324
+ (uint amount0Wei, uint amount1Wei) = IDolomiteAmmPair(pair).burn(to, toAccountNumber);
325
+ (address token0,) = DolomiteAmmLibrary.sortTokens(tokenA, tokenB);
326
+ (amountAWei, amountBWei) = tokenA == token0 ? (amount0Wei, amount1Wei) : (amount1Wei, amount0Wei);
327
+ Require.that(
328
+ amountAWei >= amountAMinWei,
329
+ FILE,
330
+ "insufficient A amount",
331
+ amountAWei,
332
+ amountAMinWei
333
+ );
334
+ Require.that(
335
+ amountBWei >= amountBMinWei,
336
+ FILE,
337
+ "insufficient B amount",
338
+ amountBWei,
339
+ amountBMinWei
340
+ );
341
+ }
342
+
343
+ function removeLiquidityWithPermit(
344
+ address to,
345
+ uint toAccountNumber,
346
+ address tokenA,
347
+ address tokenB,
348
+ uint liquidity,
349
+ uint amountAMinWei,
350
+ uint amountBMinWei,
351
+ uint deadline,
352
+ PermitSignature memory permit
353
+ ) public returns (uint amountAWei, uint amountBWei) {
354
+ address pair = DolomiteAmmLibrary.pairFor(address(DOLOMITE_AMM_FACTORY), tokenA, tokenB);
355
+ uint value = permit.approveMax ? uint(- 1) : liquidity;
356
+ IDolomiteAmmPair(pair).permit(
357
+ msg.sender,
358
+ address(this),
359
+ value,
360
+ deadline,
361
+ permit.v,
362
+ permit.r,
363
+ permit.s
364
+ );
365
+
366
+ (amountAWei, amountBWei) = removeLiquidity(
367
+ to,
368
+ toAccountNumber,
369
+ tokenA,
370
+ tokenB,
371
+ liquidity,
372
+ amountAMinWei,
373
+ amountBMinWei,
374
+ deadline
375
+ );
376
+ }
377
+
378
+ function swapExactTokensForTokensAndModifyPosition(
379
+ ModifyPositionParams memory params,
380
+ uint deadline
381
+ ) public ensure(deadline) {
382
+ _swapExactTokensForTokensAndModifyPosition(
383
+ ModifyPositionCache({
384
+ params : params,
385
+ dolomiteMargin : DOLOMITE_MARGIN,
386
+ ammFactory : DOLOMITE_AMM_FACTORY,
387
+ account : msg.sender,
388
+ marketPath : new uint[](0),
389
+ amountsWei : new uint[](0),
390
+ marginDepositDeltaWei : 0
391
+ })
392
+ );
393
+ }
394
+
395
+ function swapTokensForExactTokensAndModifyPosition(
396
+ ModifyPositionParams memory params,
397
+ uint deadline
398
+ ) public ensure(deadline) {
399
+ _swapTokensForExactTokensAndModifyPosition(
400
+ ModifyPositionCache({
401
+ params : params,
402
+ dolomiteMargin : DOLOMITE_MARGIN,
403
+ ammFactory : DOLOMITE_AMM_FACTORY,
404
+ account : msg.sender,
405
+ marketPath : new uint[](0),
406
+ amountsWei : new uint[](0),
407
+ marginDepositDeltaWei : 0
408
+ })
409
+ );
410
+ }
411
+
412
+ // *************************
413
+ // ***** Internal Functions
414
+ // *************************
415
+
416
+ function _swapExactTokensForTokensAndModifyPosition(
417
+ ModifyPositionCache memory cache
418
+ ) internal {
419
+ (
420
+ Account.Info[] memory accounts,
421
+ Actions.ActionArgs[] memory actions
422
+ ) = _getParamsForSwapExactTokensForTokens(cache);
423
+
424
+ cache.dolomiteMargin.operate(accounts, actions);
425
+
426
+ _logEvents(cache, accounts);
427
+ }
428
+
429
+ function _swapTokensForExactTokensAndModifyPosition(
430
+ ModifyPositionCache memory cache
431
+ ) internal {
432
+ (
433
+ Account.Info[] memory accounts,
434
+ Actions.ActionArgs[] memory actions
435
+ ) = _getParamsForSwapTokensForExactTokens(cache);
436
+
437
+ cache.dolomiteMargin.operate(accounts, actions);
438
+
439
+ _logEvents(cache, accounts);
440
+ }
441
+
442
+ function _getParamsForSwapExactTokensForTokens(
443
+ ModifyPositionCache memory cache
444
+ ) internal view returns (
445
+ Account.Info[] memory,
446
+ Actions.ActionArgs[] memory
447
+ ) {
448
+ cache.marketPath = _getMarketPathFromTokenPath(cache);
449
+
450
+ // Convert from par to wei, if necessary
451
+ uint amountInWei = _convertAssetAmountToWei(cache.params.amountIn, cache.marketPath[0], cache);
452
+
453
+ // Convert from par to wei, if necessary
454
+ uint amountOutMinWei = _convertAssetAmountToWei(
455
+ cache.params.amountOut,
456
+ cache.marketPath[cache.marketPath.length - 1],
457
+ cache
458
+ );
459
+
460
+ // amountsWei[0] == amountInWei
461
+ // amountsWei[amountsWei.length - 1] == amountOutWei
462
+ cache.amountsWei = DolomiteAmmLibrary.getAmountsOutWei(
463
+ address(cache.ammFactory),
464
+ amountInWei,
465
+ cache.params.tokenPath
466
+ );
467
+
468
+ Require.that(
469
+ cache.amountsWei[cache.amountsWei.length - 1] >= amountOutMinWei,
470
+ FILE,
471
+ "insufficient output amount",
472
+ cache.amountsWei[cache.amountsWei.length - 1],
473
+ amountOutMinWei
474
+ );
475
+
476
+ return _getParamsForSwap(cache);
477
+ }
478
+
479
+ function _getParamsForSwapTokensForExactTokens(
480
+ ModifyPositionCache memory cache
481
+ ) internal view returns (
482
+ Account.Info[] memory,
483
+ Actions.ActionArgs[] memory
484
+ ) {
485
+ cache.marketPath = _getMarketPathFromTokenPath(cache);
486
+
487
+ // Convert from par to wei, if necessary
488
+ uint amountInMaxWei = _convertAssetAmountToWei(cache.params.amountIn, cache.marketPath[0], cache);
489
+
490
+ // Convert from par to wei, if necessary
491
+ uint amountOutWei = _convertAssetAmountToWei(
492
+ cache.params.amountOut,
493
+ cache.marketPath[cache.marketPath.length - 1],
494
+ cache
495
+ );
496
+
497
+ // cache.amountsWei[0] == amountInWei
498
+ // cache.amountsWei[amountsWei.length - 1] == amountOutWei
499
+ cache.amountsWei = DolomiteAmmLibrary.getAmountsInWei(
500
+ address(cache.ammFactory),
501
+ amountOutWei,
502
+ cache.params.tokenPath
503
+ );
504
+ Require.that(
505
+ cache.amountsWei[0] <= amountInMaxWei,
506
+ FILE,
507
+ "excessive input amount",
508
+ cache.amountsWei[0],
509
+ amountInMaxWei
510
+ );
511
+
512
+ return _getParamsForSwap(cache);
513
+ }
514
+
515
+ function _getParamsForSwap(
516
+ ModifyPositionCache memory cache
517
+ ) internal view returns (
518
+ Account.Info[] memory,
519
+ Actions.ActionArgs[] memory
520
+ ) {
521
+ Require.that(
522
+ cache.params.amountIn.ref == Types.AssetReference.Delta &&
523
+ cache.params.amountOut.ref == Types.AssetReference.Delta,
524
+ FILE,
525
+ "invalid asset reference"
526
+ );
527
+
528
+ // pools.length == cache.params.tokenPath.length - 1
529
+ address[] memory pools = DolomiteAmmLibrary.getPools(address(cache.ammFactory), cache.params.tokenPath);
530
+
531
+ Account.Info[] memory accounts = _getAccountsForModifyPosition(cache, pools);
532
+ Actions.ActionArgs[] memory actions = _getActionArgsForModifyPosition(cache, accounts, pools);
533
+
534
+ if (cache.params.depositToken != address(0) && cache.params.marginDeposit == uint(- 1)) {
535
+ uint expiryActionCount = cache.params.expiryTimeDelta == 0 ? 0 : 1;
536
+ uint marketId = actions[actions.length - 1 - expiryActionCount].primaryMarketId;
537
+ if (cache.params.isPositiveMarginDeposit) {
538
+ // the marginDeposit is equal to the amount of `marketId` in account 0 (which is at accounts.length - 1)
539
+ cache.marginDepositDeltaWei = cache.dolomiteMargin.getAccountWei(accounts[accounts.length - 1], marketId).value;
540
+ } else {
541
+ if (cache.marketPath[0] == marketId) {
542
+ // the trade downsizes the potential withdrawal
543
+ cache.marginDepositDeltaWei = cache.dolomiteMargin.getAccountWei(accounts[0], marketId).value.sub(cache.amountsWei[0]);
544
+ } else if (cache.marketPath[cache.marketPath.length - 1] == marketId) {
545
+ // the trade upsizes the withdrawal
546
+ cache.marginDepositDeltaWei = cache.dolomiteMargin.getAccountWei(accounts[0], marketId).value.add(cache.amountsWei[cache.amountsWei.length - 1]);
547
+ } else {
548
+ // the trade doesn't impact the withdrawal
549
+ cache.marginDepositDeltaWei = cache.dolomiteMargin.getAccountWei(accounts[0], marketId).value;
550
+ }
551
+ }
552
+ } else {
553
+ cache.marginDepositDeltaWei = cache.params.marginDeposit;
554
+ }
555
+
556
+ return (accounts, actions);
557
+ }
558
+
559
+ function _getMarketPathFromTokenPath(
560
+ ModifyPositionCache memory cache
561
+ ) internal view returns (uint[] memory) {
562
+ uint[] memory marketPath = new uint[](cache.params.tokenPath.length);
563
+ for (uint i = 0; i < cache.params.tokenPath.length; i++) {
564
+ marketPath[i] = cache.dolomiteMargin.getMarketIdByTokenAddress(cache.params.tokenPath[i]);
565
+ }
566
+ return marketPath;
567
+ }
568
+
569
+ function _encodeTransferAction(
570
+ uint fromAccountIndex,
571
+ uint toAccountIndex,
572
+ uint marketId,
573
+ uint amount
574
+ ) internal pure returns (Actions.ActionArgs memory) {
575
+ Types.AssetAmount memory assetAmount;
576
+ if (amount == uint(- 1)) {
577
+ assetAmount = Types.AssetAmount(
578
+ true,
579
+ Types.AssetDenomination.Wei,
580
+ Types.AssetReference.Target,
581
+ 0
582
+ );
583
+ } else {
584
+ assetAmount = Types.AssetAmount(
585
+ false,
586
+ Types.AssetDenomination.Wei,
587
+ Types.AssetReference.Delta,
588
+ amount
589
+ );
590
+ }
591
+ return Actions.ActionArgs({
592
+ actionType : Actions.ActionType.Transfer,
593
+ accountId : fromAccountIndex,
594
+ amount : assetAmount,
595
+ primaryMarketId : marketId,
596
+ secondaryMarketId : uint(- 1),
597
+ otherAddress : address(0),
598
+ otherAccountId : toAccountIndex,
599
+ data : bytes("")
600
+ });
601
+ }
602
+
603
+ function _encodeExpirationAction(
604
+ ModifyPositionParams memory params,
605
+ Account.Info memory account,
606
+ uint accountIndex,
607
+ uint owedMarketId
608
+ ) internal view returns (Actions.ActionArgs memory) {
609
+ Require.that(
610
+ params.expiryTimeDelta == uint32(params.expiryTimeDelta),
611
+ FILE,
612
+ "invalid expiry time"
613
+ );
614
+
615
+ IExpiry.SetExpiryArg[] memory expiryArgs = new IExpiry.SetExpiryArg[](1);
616
+ expiryArgs[0] = IExpiry.SetExpiryArg({
617
+ account : account,
618
+ marketId : owedMarketId,
619
+ timeDelta : uint32(params.expiryTimeDelta),
620
+ forceUpdate : true
621
+ });
622
+
623
+ return Actions.ActionArgs({
624
+ actionType : Actions.ActionType.Call,
625
+ accountId : accountIndex,
626
+ // solium-disable-next-line arg-overflow
627
+ amount : Types.AssetAmount(true, Types.AssetDenomination.Wei, Types.AssetReference.Delta, 0),
628
+ primaryMarketId : uint(- 1),
629
+ secondaryMarketId : uint(- 1),
630
+ otherAddress : EXPIRY,
631
+ otherAccountId : uint(- 1),
632
+ data : abi.encode(IExpiry.CallFunctionType.SetExpiry, expiryArgs)
633
+ });
634
+ }
635
+
636
+ function _encodeTradeAction(
637
+ uint fromAccountIndex,
638
+ uint toAccountIndex,
639
+ uint primaryMarketId,
640
+ uint secondaryMarketId,
641
+ address traderAddress,
642
+ uint amountInWei,
643
+ uint amountOutWei
644
+ ) internal pure returns (Actions.ActionArgs memory) {
645
+ return Actions.ActionArgs({
646
+ actionType : Actions.ActionType.Trade,
647
+ accountId : fromAccountIndex,
648
+ // solium-disable-next-line arg-overflow
649
+ amount : Types.AssetAmount(true, Types.AssetDenomination.Wei, Types.AssetReference.Delta, amountInWei),
650
+ primaryMarketId : primaryMarketId,
651
+ secondaryMarketId : secondaryMarketId,
652
+ otherAddress : traderAddress,
653
+ otherAccountId : toAccountIndex,
654
+ data : abi.encode(amountOutWei)
655
+ });
656
+ }
657
+
658
+ function _addLiquidity(
659
+ address tokenA,
660
+ address tokenB,
661
+ uint amountADesiredWei,
662
+ uint amountBDesiredWei,
663
+ uint amountAMinWei,
664
+ uint amountBMinWei
665
+ ) internal returns (uint amountAWei, uint amountBWei) {
666
+ IDolomiteAmmFactory dolomiteAmmFactory = DOLOMITE_AMM_FACTORY;
667
+ // create the pair if it doesn't exist yet
668
+ if (dolomiteAmmFactory.getPair(tokenA, tokenB) == address(0)) {
669
+ dolomiteAmmFactory.createPair(tokenA, tokenB);
670
+ }
671
+ (uint reserveAWei, uint reserveBWei) = DolomiteAmmLibrary.getReservesWei(
672
+ address(dolomiteAmmFactory),
673
+ tokenA,
674
+ tokenB
675
+ );
676
+ if (reserveAWei == 0 && reserveBWei == 0) {
677
+ (amountAWei, amountBWei) = (amountADesiredWei, amountBDesiredWei);
678
+ } else {
679
+ uint amountBOptimal = DolomiteAmmLibrary.quote(amountADesiredWei, reserveAWei, reserveBWei);
680
+ if (amountBOptimal <= amountBDesiredWei) {
681
+ Require.that(
682
+ amountBOptimal >= amountBMinWei,
683
+ FILE,
684
+ "insufficient B amount",
685
+ amountBOptimal,
686
+ amountBMinWei
687
+ );
688
+ (amountAWei, amountBWei) = (amountADesiredWei, amountBOptimal);
689
+ } else {
690
+ uint amountAOptimal = DolomiteAmmLibrary.quote(amountBDesiredWei, reserveBWei, reserveAWei);
691
+ assert(amountAOptimal <= amountADesiredWei);
692
+ Require.that(
693
+ amountAOptimal >= amountAMinWei,
694
+ FILE,
695
+ "insufficient A amount",
696
+ amountAOptimal,
697
+ amountAMinWei
698
+ );
699
+ (amountAWei, amountBWei) = (amountAOptimal, amountBDesiredWei);
700
+ }
701
+ }
702
+ }
703
+
704
+ function _getAccountsForModifyPosition(
705
+ ModifyPositionCache memory cache,
706
+ address[] memory pools
707
+ ) internal pure returns (Account.Info[] memory) {
708
+ Account.Info[] memory accounts;
709
+ if (cache.params.depositToken == address(0)) {
710
+ accounts = new Account.Info[](1 + pools.length);
711
+ } else {
712
+ accounts = new Account.Info[](2 + pools.length);
713
+ accounts[accounts.length - 1] = Account.Info(cache.account, 0);
714
+ }
715
+
716
+ accounts[0] = Account.Info(cache.account, cache.params.accountNumber);
717
+
718
+ for (uint i = 0; i < pools.length; i++) {
719
+ accounts[i + 1] = Account.Info(pools[i], 0);
720
+ }
721
+
722
+ return accounts;
723
+ }
724
+
725
+ function _getActionArgsForModifyPosition(
726
+ ModifyPositionCache memory cache,
727
+ Account.Info[] memory accounts,
728
+ address[] memory pools
729
+ ) internal view returns (Actions.ActionArgs[] memory) {
730
+ Actions.ActionArgs[] memory actions;
731
+ if (cache.params.depositToken == address(0)) {
732
+ actions = new Actions.ActionArgs[](pools.length);
733
+ } else {
734
+ Require.that(
735
+ cache.params.marginDeposit != 0,
736
+ FILE,
737
+ "invalid margin deposit"
738
+ );
739
+
740
+ uint expiryActionCount = cache.params.expiryTimeDelta == 0 ? 0 : 1;
741
+ actions = new Actions.ActionArgs[](pools.length + 1 + expiryActionCount);
742
+
743
+ // `accountNumber` `0` is at index `accountsLength - 1`
744
+
745
+ bool isWithdrawal = !cache.params.isPositiveMarginDeposit;
746
+ // solium-disable indentation
747
+ actions[actions.length - 1 - expiryActionCount] = _encodeTransferAction(
748
+ /* from */ isWithdrawal ? 0 : accounts.length - 1,
749
+ /* to */ isWithdrawal ? accounts.length - 1 : 0,
750
+ cache.dolomiteMargin.getMarketIdByTokenAddress(cache.params.depositToken),
751
+ cache.params.marginDeposit
752
+ );
753
+ // solium-enable indentation
754
+ if (expiryActionCount == 1) {
755
+ actions[actions.length - 1] = _encodeExpirationAction(
756
+ cache.params,
757
+ accounts[0],
758
+ 0,
759
+ cache.marketPath[0] /* the market at index 0 is being borrowed and traded */
760
+ );
761
+ }
762
+ }
763
+
764
+ for (uint i = 0; i < pools.length; i++) {
765
+ Require.that(
766
+ accounts[i + 1].owner == pools[i],
767
+ FILE,
768
+ "invalid other address"
769
+ );
770
+ actions[i] = _encodeTradeAction(
771
+ 0,
772
+ i + 1,
773
+ cache.marketPath[i],
774
+ cache.marketPath[i + 1],
775
+ pools[i],
776
+ cache.amountsWei[i],
777
+ cache.amountsWei[i + 1]
778
+ );
779
+ }
780
+
781
+ return actions;
782
+ }
783
+
784
+ function _defaultAssetAmount(uint value) internal pure returns (Types.AssetAmount memory) {
785
+ return Types.AssetAmount({
786
+ sign : true,
787
+ denomination : Types.AssetDenomination.Wei,
788
+ ref : Types.AssetReference.Delta,
789
+ value : value
790
+ });
791
+ }
792
+
793
+ function _convertAssetAmountToWei(
794
+ Types.AssetAmount memory amount,
795
+ uint marketId,
796
+ ModifyPositionCache memory cache
797
+ ) internal view returns (uint) {
798
+ if (amount.denomination == Types.AssetDenomination.Wei) {
799
+ return amount.value;
800
+ } else {
801
+ Require.that(
802
+ uint128(amount.value) == amount.value,
803
+ FILE,
804
+ "invalid asset amount"
805
+ );
806
+ return Interest.parToWei(
807
+ Types.Par({sign : amount.sign, value : uint128(amount.value)}),
808
+ cache.dolomiteMargin.getMarketCurrentIndex(marketId)
809
+ ).value;
810
+ }
811
+ }
812
+
813
+ function _logEvents(
814
+ ModifyPositionCache memory cache,
815
+ Account.Info[] memory accounts
816
+ ) internal {
817
+ if (cache.params.isPositiveMarginDeposit && cache.params.accountNumber > 0) {
818
+ Types.Par memory newOutputPar = cache.dolomiteMargin.getAccountPar(
819
+ accounts[0],
820
+ cache.marketPath[cache.marketPath.length - 1]
821
+ );
822
+
823
+ emit MarginPositionOpen(
824
+ msg.sender,
825
+ cache.params.accountNumber,
826
+ cache.params.tokenPath[0],
827
+ cache.params.tokenPath[cache.params.tokenPath.length - 1],
828
+ cache.params.depositToken,
829
+ Events.BalanceUpdate({
830
+ deltaWei : Types.Wei(false, cache.amountsWei[0]),
831
+ newPar : cache.dolomiteMargin.getAccountPar(accounts[0], cache.marketPath[0])
832
+ }),
833
+ Events.BalanceUpdate({
834
+ deltaWei : Types.Wei(true, cache.amountsWei[cache.amountsWei.length - 1]),
835
+ newPar : newOutputPar
836
+ }),
837
+ Events.BalanceUpdate({
838
+ deltaWei : Types.Wei(true, cache.marginDepositDeltaWei),
839
+ newPar : newOutputPar
840
+ })
841
+ );
842
+ } else if (cache.params.accountNumber > 0) {
843
+ Types.Par memory newInputPar = cache.dolomiteMargin.getAccountPar(accounts[0], cache.marketPath[0]);
844
+
845
+ emit MarginPositionClose(
846
+ msg.sender,
847
+ cache.params.accountNumber,
848
+ cache.params.tokenPath[0],
849
+ cache.params.tokenPath[cache.params.tokenPath.length - 1],
850
+ cache.params.depositToken,
851
+ Events.BalanceUpdate({
852
+ deltaWei : Types.Wei(false, cache.amountsWei[0]),
853
+ newPar : newInputPar
854
+ }),
855
+ Events.BalanceUpdate({
856
+ deltaWei : Types.Wei(true, cache.amountsWei[cache.amountsWei.length - 1]),
857
+ newPar : _getOutputPar(cache, accounts[0])
858
+ }),
859
+ Events.BalanceUpdate({
860
+ deltaWei : Types.Wei(false, cache.marginDepositDeltaWei),
861
+ newPar : newInputPar
862
+ })
863
+ );
864
+ }
865
+ }
866
+
867
+ function _getOutputPar(
868
+ ModifyPositionCache memory cache,
869
+ Account.Info memory account
870
+ ) internal view returns (Types.Par memory) {
871
+ return cache.dolomiteMargin.getAccountPar(
872
+ account,
873
+ cache.marketPath[cache.marketPath.length - 1]
874
+ );
875
+ }
876
+
877
+ }