@paraswap/dex-lib 2.13.1 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/config.js +5 -23
- package/build/config.js.map +1 -1
- package/build/dex/curve-v1/config.js +0 -2
- package/build/dex/curve-v1/config.js.map +1 -1
- package/build/dex/curve-v1/curve-v1.js +0 -2
- package/build/dex/curve-v1/curve-v1.js.map +1 -1
- package/build/dex/curve-v1/types.d.ts +0 -1
- package/build/dex/curve-v1/types.js.map +1 -1
- package/build/dex/generic-rfq/rate-fetcher.js +0 -2
- package/build/dex/generic-rfq/rate-fetcher.js.map +1 -1
- package/build/dex/generic-rfq/validators.d.ts +1 -1
- package/build/dex/generic-rfq/validators.js +26 -36
- package/build/dex/generic-rfq/validators.js.map +1 -1
- package/build/dex/index.js +2 -2
- package/build/dex/index.js.map +1 -1
- package/build/dex/simple-exchange.d.ts +0 -1
- package/build/dex/simple-exchange.js +0 -2
- package/build/dex/simple-exchange.js.map +1 -1
- package/build/lib/decoders.d.ts +1 -2
- package/build/lib/decoders.js +1 -8
- package/build/lib/decoders.js.map +1 -1
- package/build/lib/fetcher/fetcher.js +0 -3
- package/build/lib/fetcher/fetcher.js.map +1 -1
- package/build/lib/multi-wrapper.d.ts +1 -2
- package/build/lib/multi-wrapper.js.map +1 -1
- package/build/lib/tokens/balancer-fetcher.js +5 -4
- package/build/lib/tokens/balancer-fetcher.js.map +1 -1
- package/build/lib/tokens/utils.d.ts +2 -2
- package/build/lib/tokens/utils.js +1 -1
- package/build/lib/tokens/utils.js.map +1 -1
- package/build/types.d.ts +0 -3
- package/dex-template/__DexName__-e2e.test.ts.template +0 -1
- package/dex-template/__DexName__-events.test.ts.template +0 -1
- package/dex-template/__DexName__-integration.test.ts.template +0 -1
- package/dex-template/__DexName__-pool.ts.template +5 -8
- package/package.json +1 -1
- package/scripts/generate-bytecode.ts +0 -2
- package/src/abi/woo-fi/WooFeeManager.abi.json +318 -0
- package/src/abi/{woo-fi-v2/WooPPV2.abi.json → woo-fi/WooPP.abi.json} +169 -201
- package/src/abi/{woo-fi-v2/WooOracleV2.abi.json → woo-fi/Wooracle.abi.json} +50 -148
- package/src/config.ts +5 -27
- package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +1 -0
- package/src/dex/curve-v1/config.ts +0 -2
- package/src/dex/curve-v1/curve-v1-e2e.test.ts +37 -18
- package/src/dex/curve-v1/curve-v1.ts +0 -2
- package/src/dex/curve-v1/types.ts +0 -1
- package/src/dex/generic-rfq/generic-rfq-e2e.test.ts +258 -63
- package/src/dex/generic-rfq/rate-fetcher.ts +0 -2
- package/src/dex/generic-rfq/validators.test.ts +32 -6
- package/src/dex/generic-rfq/validators.ts +32 -57
- package/src/dex/index.ts +2 -2
- package/src/dex/simple-exchange.ts +0 -3
- package/src/dex/woo-fi/config.ts +141 -0
- package/src/dex/woo-fi/constants.ts +21 -0
- package/src/dex/woo-fi/types.ts +55 -0
- package/src/dex/woo-fi/woo-fi-decimal-math.ts +45 -0
- package/src/dex/woo-fi/woo-fi-e2e.test.ts +183 -0
- package/src/dex/woo-fi/woo-fi-integration.test.ts +416 -0
- package/src/dex/woo-fi/woo-fi-math.ts +527 -0
- package/src/dex/woo-fi/woo-fi.ts +693 -0
- package/src/lib/decoders.ts +1 -12
- package/src/lib/fetcher/fetcher.ts +0 -6
- package/src/lib/multi-wrapper.ts +1 -2
- package/src/lib/tokens/balancer-fetcher.ts +6 -5
- package/src/lib/tokens/utils.ts +3 -5
- package/src/types.ts +0 -4
- package/tests/constants-e2e.ts +9 -11
- package/tests/tenderly-simulation.ts +1 -1
- package/tests/utils-e2e.ts +48 -61
- package/tests/utils.ts +0 -2
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
- package/.vscode/launch.json +0 -21
- package/build/dex/aave-v3/tokens/arbitrum.json +0 -50
- package/build/dex/aave-v3/tokens/avalanche.json +0 -50
- package/build/dex/aave-v3/tokens/fantom.json +0 -62
- package/build/dex/aave-v3/tokens/mainnet.json +0 -44
- package/build/dex/aave-v3/tokens/optimism.json +0 -50
- package/build/dex/aave-v3/tokens/polygon.json +0 -98
- package/build/dex/balancer-v2/VirtualBoostedPool.d.ts +0 -79
- package/build/dex/balancer-v2/VirtualBoostedPool.js +0 -382
- package/build/dex/balancer-v2/VirtualBoostedPool.js.map +0 -1
- package/build/dex/generic-rfq/e2e-test-config.d.ts +0 -9
- package/build/dex/generic-rfq/e2e-test-config.js +0 -33
- package/build/dex/generic-rfq/e2e-test-config.js.map +0 -1
- package/build/dex/test-aave-v3/config.d.ts +0 -4
- package/build/dex/test-aave-v3/config.js +0 -15
- package/build/dex/test-aave-v3/config.js.map +0 -1
- package/build/dex/test-aave-v3/test-aave-v3-pool.d.ts +0 -39
- package/build/dex/test-aave-v3/test-aave-v3-pool.js +0 -63
- package/build/dex/test-aave-v3/test-aave-v3-pool.js.map +0 -1
- package/build/dex/test-aave-v3/test-aave-v3.d.ts +0 -37
- package/build/dex/test-aave-v3/test-aave-v3.js +0 -126
- package/build/dex/test-aave-v3/test-aave-v3.js.map +0 -1
- package/build/dex/test-aave-v3/types.d.ts +0 -6
- package/build/dex/test-aave-v3/types.js +0 -3
- package/build/dex/test-aave-v3/types.js.map +0 -1
- package/src/abi/woo-fi-v2/IntegrationHelper.abi.json +0 -116
- package/src/dex/generic-rfq/e2e-test-config.ts +0 -37
- package/src/dex/generic-rfq/generic-rfq-local-e2e.test.ts +0 -121
- package/src/dex/woo-fi-v2/config.ts +0 -87
- package/src/dex/woo-fi-v2/constants.ts +0 -22
- package/src/dex/woo-fi-v2/decoders.ts +0 -45
- package/src/dex/woo-fi-v2/types.ts +0 -63
- package/src/dex/woo-fi-v2/utils.ts +0 -19
- package/src/dex/woo-fi-v2/woo-fi-v2-e2e.test.ts +0 -216
- package/src/dex/woo-fi-v2/woo-fi-v2-integration.test.ts +0 -495
- package/src/dex/woo-fi-v2/woo-fi-v2-math.ts +0 -195
- package/src/dex/woo-fi-v2/woo-fi-v2-pool.ts +0 -112
- package/src/dex/woo-fi-v2/woo-fi-v2.ts +0 -487
- package/src/lib/log-messages-suppressor.ts +0 -173
- package/src/lib/stateful-rpc-poller/state-polling-manager.ts +0 -320
- package/src/lib/stateful-rpc-poller/stateful-rpc-poller.ts +0 -604
- package/src/lib/stateful-rpc-poller/types.ts +0 -66
- package/src/lib/stateful-rpc-poller/utils.ts +0 -23
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
import { PoolState, TokenInfo } from './types';
|
|
2
|
+
import { wooFiDecimalMath } from './woo-fi-decimal-math';
|
|
3
|
+
import { Address, Logger } from '../../types';
|
|
4
|
+
import { BI_MAX_UINT96, BI_POWS } from '../../bigint-constants';
|
|
5
|
+
import { _require } from '../../utils';
|
|
6
|
+
import { NULL_STATE } from './constants';
|
|
7
|
+
import { NULL_ADDRESS } from '../../constants';
|
|
8
|
+
|
|
9
|
+
function handleMathError(e: unknown, logger: Logger) {
|
|
10
|
+
if (e instanceof Error && e.message.startsWith('WooGuardian:')) {
|
|
11
|
+
logger.warn('WooFi Guardian check Error:', e);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
logger.error('Unexpected error in WooFi math:', e);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class WooFiMath {
|
|
18
|
+
// dMath = decimalMath
|
|
19
|
+
readonly dMath: typeof wooFiDecimalMath = wooFiDecimalMath;
|
|
20
|
+
|
|
21
|
+
private readonly _MIN_INPUT_DEFAULT = BI_POWS[16]; // 0.01 xToken
|
|
22
|
+
|
|
23
|
+
private readonly _MAX_INPUT_DEFAULT = BI_POWS[20]; // 100 xToken
|
|
24
|
+
|
|
25
|
+
state: PoolState = NULL_STATE;
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
private readonly logger: Logger,
|
|
29
|
+
private readonly _quoteToken: Address,
|
|
30
|
+
) {}
|
|
31
|
+
|
|
32
|
+
querySellBase(baseToken: Address, baseAmounts: bigint[]): bigint[] | null {
|
|
33
|
+
try {
|
|
34
|
+
const _baseAmounts = baseAmounts.map(baseAmount => {
|
|
35
|
+
try {
|
|
36
|
+
this._checkInputAmount(baseToken, baseAmount);
|
|
37
|
+
return baseAmount;
|
|
38
|
+
} catch (e) {
|
|
39
|
+
if (
|
|
40
|
+
e instanceof Error &&
|
|
41
|
+
e.message.includes('WooGuardian: inputAmount')
|
|
42
|
+
) {
|
|
43
|
+
return 0n;
|
|
44
|
+
}
|
|
45
|
+
throw e;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
this._autoUpdate(this._quoteToken, baseToken);
|
|
50
|
+
|
|
51
|
+
const quoteAmounts = this._getQuoteAmountSellBase(
|
|
52
|
+
baseToken,
|
|
53
|
+
_baseAmounts,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const feeRate = this.state.feeRates[baseToken];
|
|
57
|
+
return this._takeFee(quoteAmounts, feeRate);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
handleMathError(e, this.logger);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
querySellQuote(baseToken: Address, quoteAmounts: bigint[]): bigint[] | null {
|
|
65
|
+
try {
|
|
66
|
+
let _quoteAmounts = quoteAmounts.map(quoteAmount => {
|
|
67
|
+
try {
|
|
68
|
+
this._checkInputAmount(this._quoteToken, quoteAmount);
|
|
69
|
+
return quoteAmount;
|
|
70
|
+
} catch (e) {
|
|
71
|
+
if (
|
|
72
|
+
e instanceof Error &&
|
|
73
|
+
e.message.startsWith('Error message: WooGuardian: inputAmount')
|
|
74
|
+
) {
|
|
75
|
+
return 0n;
|
|
76
|
+
}
|
|
77
|
+
throw e;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
this._autoUpdate(this._quoteToken, baseToken);
|
|
82
|
+
|
|
83
|
+
const feeRate = this.state.feeRates[baseToken];
|
|
84
|
+
_quoteAmounts = this._takeFee(_quoteAmounts, feeRate);
|
|
85
|
+
|
|
86
|
+
return this._getBaseAmountSellQuote(baseToken, _quoteAmounts);
|
|
87
|
+
} catch (e) {
|
|
88
|
+
handleMathError(e, this.logger);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
protected _takeFee(amounts: bigint[], feeRate: bigint): bigint[] {
|
|
94
|
+
return amounts.map(amount => {
|
|
95
|
+
const lpFee = this.dMath.mulCeil(amount, feeRate);
|
|
96
|
+
return amount === 0n ? 0n : amount - lpFee;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
protected _getQuoteAmountSellBase(
|
|
101
|
+
baseToken: Address,
|
|
102
|
+
baseAmounts: bigint[],
|
|
103
|
+
): bigint[] {
|
|
104
|
+
const quoteInfo = this.state.tokenInfos[this._quoteToken];
|
|
105
|
+
const baseInfo = this.state.tokenInfos[baseToken];
|
|
106
|
+
|
|
107
|
+
let {
|
|
108
|
+
priceNow: p,
|
|
109
|
+
spreadNow: s,
|
|
110
|
+
coeffNow: k,
|
|
111
|
+
} = this.state.tokenStates[baseToken];
|
|
112
|
+
|
|
113
|
+
this.checkSwapPrice(p, baseToken, this._quoteToken);
|
|
114
|
+
|
|
115
|
+
// price: p * (1 - s / 2)
|
|
116
|
+
p = this.dMath.mulFloor(
|
|
117
|
+
p,
|
|
118
|
+
this.dMath.ONE - this.dMath.divCeil(s, this.dMath.TWO),
|
|
119
|
+
);
|
|
120
|
+
const { baseBought, quoteBought } = this._getBoughtAmount(
|
|
121
|
+
baseInfo,
|
|
122
|
+
quoteInfo,
|
|
123
|
+
p,
|
|
124
|
+
k,
|
|
125
|
+
true,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return baseAmounts.map(baseAmount => {
|
|
129
|
+
if (baseAmount === 0n) return 0n;
|
|
130
|
+
|
|
131
|
+
let quoteAmount: bigint;
|
|
132
|
+
|
|
133
|
+
if (baseBought > 0n) {
|
|
134
|
+
const quoteSold = this._getQuoteAmountLowBaseSide(
|
|
135
|
+
p,
|
|
136
|
+
k,
|
|
137
|
+
baseInfo.R,
|
|
138
|
+
baseBought,
|
|
139
|
+
);
|
|
140
|
+
if (baseAmount > baseBought) {
|
|
141
|
+
const newBaseSold = baseAmount - baseBought;
|
|
142
|
+
quoteAmount =
|
|
143
|
+
quoteSold +
|
|
144
|
+
this._getQuoteAmountLowQuoteSide(p, k, this.dMath.ONE, newBaseSold);
|
|
145
|
+
} else {
|
|
146
|
+
const newBaseBought = baseBought - baseAmount;
|
|
147
|
+
quoteAmount =
|
|
148
|
+
quoteSold -
|
|
149
|
+
this._getQuoteAmountLowBaseSide(p, k, baseInfo.R, newBaseBought);
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
const baseSold = this._getBaseAmountLowQuoteSide(
|
|
153
|
+
p,
|
|
154
|
+
k,
|
|
155
|
+
this.dMath.ONE,
|
|
156
|
+
quoteBought,
|
|
157
|
+
);
|
|
158
|
+
const newBaseSold = baseAmount + baseSold;
|
|
159
|
+
const newQuoteBought = this._getQuoteAmountLowQuoteSide(
|
|
160
|
+
p,
|
|
161
|
+
k,
|
|
162
|
+
this.dMath.ONE,
|
|
163
|
+
newBaseSold,
|
|
164
|
+
);
|
|
165
|
+
quoteAmount =
|
|
166
|
+
newQuoteBought > quoteBought ? newQuoteBought - quoteBought : 0n;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this._checkSwapAmount(
|
|
170
|
+
baseToken,
|
|
171
|
+
this._quoteToken,
|
|
172
|
+
baseAmount,
|
|
173
|
+
quoteAmount,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
if (quoteAmount > this.state.wooPPBalances[this._quoteToken]) {
|
|
177
|
+
// require(quoteAmount <= IERC20(quoteToken).balanceOf(address(this)), 'WooPP: INSUFF_QUOTE');
|
|
178
|
+
return 0n;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return quoteAmount;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
protected _getBaseAmountSellQuote(
|
|
186
|
+
baseToken: string,
|
|
187
|
+
quoteAmounts: bigint[],
|
|
188
|
+
): bigint[] {
|
|
189
|
+
const quoteInfo = this.state.tokenInfos[this._quoteToken];
|
|
190
|
+
const baseInfo = this.state.tokenInfos[baseToken];
|
|
191
|
+
|
|
192
|
+
let {
|
|
193
|
+
priceNow: p,
|
|
194
|
+
spreadNow: s,
|
|
195
|
+
coeffNow: k,
|
|
196
|
+
} = this.state.tokenStates[baseToken];
|
|
197
|
+
|
|
198
|
+
this.checkSwapPrice(p, baseToken, this._quoteToken);
|
|
199
|
+
|
|
200
|
+
// price: p * (1 + s / 2)
|
|
201
|
+
p = this.dMath.mulCeil(
|
|
202
|
+
p,
|
|
203
|
+
this.dMath.ONE + this.dMath.divCeil(s, this.dMath.TWO),
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const { baseBought, quoteBought } = this._getBoughtAmount(
|
|
207
|
+
baseInfo,
|
|
208
|
+
quoteInfo,
|
|
209
|
+
p,
|
|
210
|
+
k,
|
|
211
|
+
false,
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
return quoteAmounts.map(quoteAmount => {
|
|
215
|
+
if (quoteAmount === 0n) return 0n;
|
|
216
|
+
|
|
217
|
+
let baseAmount: bigint;
|
|
218
|
+
if (quoteBought > 0) {
|
|
219
|
+
const baseSold = this._getBaseAmountLowQuoteSide(
|
|
220
|
+
p,
|
|
221
|
+
k,
|
|
222
|
+
baseInfo.R,
|
|
223
|
+
quoteBought,
|
|
224
|
+
);
|
|
225
|
+
if (quoteAmount > quoteBought) {
|
|
226
|
+
const newQuoteSold = quoteAmount - quoteBought;
|
|
227
|
+
baseAmount =
|
|
228
|
+
baseSold +
|
|
229
|
+
this._getBaseAmountLowBaseSide(p, k, this.dMath.ONE, newQuoteSold);
|
|
230
|
+
} else {
|
|
231
|
+
const newQuoteBought = quoteBought - quoteAmount;
|
|
232
|
+
baseAmount =
|
|
233
|
+
baseSold -
|
|
234
|
+
this._getBaseAmountLowQuoteSide(p, k, baseInfo.R, newQuoteBought);
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
const quoteSold = this._getQuoteAmountLowBaseSide(
|
|
238
|
+
p,
|
|
239
|
+
k,
|
|
240
|
+
this.dMath.ONE,
|
|
241
|
+
baseBought,
|
|
242
|
+
);
|
|
243
|
+
const newQuoteSold = quoteAmount + quoteSold;
|
|
244
|
+
const newBaseBought = this._getBaseAmountLowBaseSide(
|
|
245
|
+
p,
|
|
246
|
+
k,
|
|
247
|
+
this.dMath.ONE,
|
|
248
|
+
newQuoteSold,
|
|
249
|
+
);
|
|
250
|
+
baseAmount =
|
|
251
|
+
newBaseBought > baseBought ? newBaseBought - baseBought : 0n;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
this._checkSwapAmount(
|
|
255
|
+
this._quoteToken,
|
|
256
|
+
baseToken,
|
|
257
|
+
quoteAmount,
|
|
258
|
+
baseAmount,
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
if (baseAmount > this.state.wooPPBalances[baseToken]) {
|
|
262
|
+
// require(baseAmount <= IERC20(baseToken).balanceOf(address(this)), 'WooPP: INSUFF_BASE');
|
|
263
|
+
return 0n;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return baseAmount;
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
protected _getBoughtAmount(
|
|
271
|
+
baseInfo: TokenInfo,
|
|
272
|
+
quoteInfo: TokenInfo,
|
|
273
|
+
p: bigint,
|
|
274
|
+
k: bigint,
|
|
275
|
+
isSellBase: boolean,
|
|
276
|
+
) {
|
|
277
|
+
let baseBought = 0n;
|
|
278
|
+
let quoteBought = 0n;
|
|
279
|
+
|
|
280
|
+
let baseSold = 0n;
|
|
281
|
+
if (baseInfo.reserve < baseInfo.target) {
|
|
282
|
+
baseBought = baseInfo.target - baseInfo.reserve;
|
|
283
|
+
} else {
|
|
284
|
+
baseSold = baseInfo.reserve - baseInfo.target;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
let quoteSold = 0n;
|
|
288
|
+
if (quoteInfo.reserve < quoteInfo.target) {
|
|
289
|
+
quoteBought = quoteInfo.target - quoteInfo.reserve;
|
|
290
|
+
} else {
|
|
291
|
+
quoteSold = quoteInfo.reserve - quoteInfo.target;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (this.dMath.mulCeil(baseSold, p) > quoteSold) {
|
|
295
|
+
baseSold = baseSold - this.dMath.divFloor(quoteSold, p);
|
|
296
|
+
quoteSold = 0n;
|
|
297
|
+
} else {
|
|
298
|
+
quoteSold = quoteSold - this.dMath.mulCeil(baseSold, p);
|
|
299
|
+
baseSold = 0n;
|
|
300
|
+
}
|
|
301
|
+
const virtualBaseBought = this._getBaseAmountLowBaseSide(
|
|
302
|
+
p,
|
|
303
|
+
k,
|
|
304
|
+
this.dMath.ONE,
|
|
305
|
+
quoteSold,
|
|
306
|
+
);
|
|
307
|
+
if (isSellBase === virtualBaseBought < baseBought) {
|
|
308
|
+
baseBought = virtualBaseBought;
|
|
309
|
+
}
|
|
310
|
+
const virtualQuoteBought = this._getQuoteAmountLowQuoteSide(
|
|
311
|
+
p,
|
|
312
|
+
k,
|
|
313
|
+
this.dMath.ONE,
|
|
314
|
+
baseSold,
|
|
315
|
+
);
|
|
316
|
+
if (isSellBase === virtualQuoteBought > quoteBought) {
|
|
317
|
+
quoteBought = virtualQuoteBought;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return { baseBought, quoteBought };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
protected _getBaseAmountLowBaseSide(
|
|
324
|
+
p: bigint,
|
|
325
|
+
k: bigint,
|
|
326
|
+
r: bigint,
|
|
327
|
+
quoteAmount: bigint,
|
|
328
|
+
) {
|
|
329
|
+
// priceFactor = 1 + k * quoteAmount * r;
|
|
330
|
+
const priceFactor =
|
|
331
|
+
this.dMath.ONE +
|
|
332
|
+
this.dMath.mulCeil(this.dMath.mulCeil(k, quoteAmount), r);
|
|
333
|
+
|
|
334
|
+
// quoteAmount / p / priceFactor;
|
|
335
|
+
return this.dMath.divFloor(
|
|
336
|
+
this.dMath.divFloor(quoteAmount, p),
|
|
337
|
+
priceFactor,
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
protected _getQuoteAmountLowQuoteSide(
|
|
342
|
+
p: bigint,
|
|
343
|
+
k: bigint,
|
|
344
|
+
r: bigint,
|
|
345
|
+
baseAmount: bigint,
|
|
346
|
+
) {
|
|
347
|
+
// priceFactor = 1 + k * baseAmount * p * r;
|
|
348
|
+
const priceFactor =
|
|
349
|
+
this.dMath.ONE +
|
|
350
|
+
this.dMath.mulCeil(
|
|
351
|
+
this.dMath.mulCeil(this.dMath.mulCeil(k, baseAmount), p),
|
|
352
|
+
r,
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
// baseAmount * p / priceFactor;
|
|
356
|
+
return this.dMath.divFloor(this.dMath.mulFloor(baseAmount, p), priceFactor);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
protected _getBaseAmountLowQuoteSide(
|
|
360
|
+
p: bigint,
|
|
361
|
+
k: bigint,
|
|
362
|
+
r: bigint,
|
|
363
|
+
quoteAmount: bigint,
|
|
364
|
+
) {
|
|
365
|
+
// priceFactor = (1 - k * quoteAmount * r);
|
|
366
|
+
const priceFactor =
|
|
367
|
+
this.dMath.ONE -
|
|
368
|
+
this.dMath.mulFloor(this.dMath.mulFloor(k, quoteAmount), r);
|
|
369
|
+
|
|
370
|
+
// quoteAmount / p / priceFactor;
|
|
371
|
+
return this.dMath.divFloor(
|
|
372
|
+
this.dMath.divFloor(quoteAmount, p),
|
|
373
|
+
priceFactor,
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
protected _getQuoteAmountLowBaseSide(
|
|
378
|
+
p: bigint,
|
|
379
|
+
k: bigint,
|
|
380
|
+
r: bigint,
|
|
381
|
+
baseAmount: bigint,
|
|
382
|
+
) {
|
|
383
|
+
// priceFactor = 1 - k * baseAmount * p * r;
|
|
384
|
+
const priceFactor =
|
|
385
|
+
this.dMath.ONE -
|
|
386
|
+
this.dMath.mulFloor(
|
|
387
|
+
this.dMath.mulFloor(this.dMath.mulFloor(k, baseAmount), p),
|
|
388
|
+
r,
|
|
389
|
+
);
|
|
390
|
+
// baseAmount * p / priceFactor;
|
|
391
|
+
return this.dMath.divFloor(this.dMath.mulFloor(baseAmount, p), priceFactor);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
protected _autoUpdate(quoteTokenAddress: string, baseTokenAddress: string) {
|
|
395
|
+
const quoteInfo = this.state.tokenInfos[quoteTokenAddress];
|
|
396
|
+
const baseInfo = this.state.tokenInfos[baseTokenAddress];
|
|
397
|
+
|
|
398
|
+
if (this.state.oracleTimestamp !== baseInfo.lastResetTimestamp) {
|
|
399
|
+
baseInfo.target =
|
|
400
|
+
baseInfo.threshold > baseInfo.reserve
|
|
401
|
+
? baseInfo.threshold
|
|
402
|
+
: baseInfo.reserve;
|
|
403
|
+
baseInfo.lastResetTimestamp = this.state.oracleTimestamp;
|
|
404
|
+
}
|
|
405
|
+
if (this.state.oracleTimestamp !== quoteInfo.lastResetTimestamp) {
|
|
406
|
+
quoteInfo.target =
|
|
407
|
+
quoteInfo.threshold > quoteInfo.reserve
|
|
408
|
+
? quoteInfo.threshold
|
|
409
|
+
: quoteInfo.reserve;
|
|
410
|
+
quoteInfo.lastResetTimestamp = this.state.oracleTimestamp;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
private _checkInputAmount(token: Address, inputAmount: bigint) {
|
|
415
|
+
_require(
|
|
416
|
+
inputAmount < BI_MAX_UINT96,
|
|
417
|
+
`WooGuardian: inputAmount_uint96_OVERFLOW in _checkInputAmount for ${token}`,
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
const info = this.state.guardian.refInfos[token];
|
|
421
|
+
const minInputAmount =
|
|
422
|
+
info.minInputAmount != 0n ? info.minInputAmount : this._MIN_INPUT_DEFAULT;
|
|
423
|
+
const maxInputAmount =
|
|
424
|
+
info.maxInputAmount != 0n ? info.maxInputAmount : this._MAX_INPUT_DEFAULT;
|
|
425
|
+
|
|
426
|
+
_require(
|
|
427
|
+
inputAmount >= minInputAmount,
|
|
428
|
+
`WooGuardian: inputAmount_LTM in _checkInputAmount for ${token}`,
|
|
429
|
+
);
|
|
430
|
+
_require(
|
|
431
|
+
inputAmount <= maxInputAmount,
|
|
432
|
+
`WooGuardian: inputAmount_GTM in _checkInputAmount for ${token}`,
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
private _checkSwapAmount(
|
|
437
|
+
fromToken: Address,
|
|
438
|
+
toToken: Address,
|
|
439
|
+
fromAmount: bigint,
|
|
440
|
+
toAmount: bigint,
|
|
441
|
+
) {
|
|
442
|
+
if (
|
|
443
|
+
this.state.guardian.refInfos[fromToken].chainlinkRefOracle ===
|
|
444
|
+
NULL_ADDRESS ||
|
|
445
|
+
this.state.guardian.refInfos[toToken].chainlinkRefOracle === NULL_ADDRESS
|
|
446
|
+
) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const refPrice = this._refPrice(fromToken, toToken);
|
|
451
|
+
const refToAmount = this.dMath.mulFloor(fromAmount, refPrice);
|
|
452
|
+
|
|
453
|
+
const bound = this._boundForTokens(fromToken, toToken);
|
|
454
|
+
|
|
455
|
+
_require(
|
|
456
|
+
this.dMath.mulFloor(refToAmount, BI_POWS[18] - bound) <= toAmount &&
|
|
457
|
+
toAmount <= this.dMath.mulCeil(refToAmount, BI_POWS[18] + bound),
|
|
458
|
+
`WooGuardian: TO_AMOUNT_UNRELIABLE in _checkSwapAmount for ${toToken}`,
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
checkSwapPrice(price: bigint, fromToken: Address, toToken: Address) {
|
|
463
|
+
if (
|
|
464
|
+
this.state.guardian.refInfos[fromToken].chainlinkRefOracle ===
|
|
465
|
+
NULL_ADDRESS ||
|
|
466
|
+
this.state.guardian.refInfos[toToken].chainlinkRefOracle === NULL_ADDRESS
|
|
467
|
+
) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const refPrice = this._refPrice(fromToken, toToken);
|
|
472
|
+
const bound = this._boundForTokens(fromToken, toToken);
|
|
473
|
+
|
|
474
|
+
_require(
|
|
475
|
+
this.dMath.mulFloor(refPrice, BI_POWS[18] - bound) <= price &&
|
|
476
|
+
price <= this.dMath.mulCeil(refPrice, BI_POWS[18] + bound),
|
|
477
|
+
`WooGuardian: PRICE_UNRELIABLE in checkSwapPrice fromToken=${fromToken} and toToken=${toToken}`,
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
private _refPrice(fromToken: Address, toToken: Address) {
|
|
482
|
+
const baseInfo = this.state.guardian.refInfos[fromToken];
|
|
483
|
+
const quoteInfo = this.state.guardian.refInfos[toToken];
|
|
484
|
+
|
|
485
|
+
_require(
|
|
486
|
+
baseInfo.chainlinkRefOracle !== NULL_ADDRESS,
|
|
487
|
+
`WooGuardian: fromToken_RefOracle_INVALID: ${fromToken}`,
|
|
488
|
+
);
|
|
489
|
+
_require(
|
|
490
|
+
quoteInfo.chainlinkRefOracle !== NULL_ADDRESS,
|
|
491
|
+
`WooGuardian: toToken_RefOracle_INVALID: ${toToken}`,
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
const { answer: rawBaseRefPrice } =
|
|
495
|
+
this.state.chainlink.latestRoundDatas[baseInfo.chainlinkRefOracle];
|
|
496
|
+
|
|
497
|
+
_require(
|
|
498
|
+
rawBaseRefPrice >= 0,
|
|
499
|
+
`WooGuardian: INVALID_CHAINLINK_PRICE in _refPrice for ${fromToken}`,
|
|
500
|
+
);
|
|
501
|
+
|
|
502
|
+
const { answer: rawQuoteRefPrice } =
|
|
503
|
+
this.state.chainlink.latestRoundDatas[quoteInfo.chainlinkRefOracle];
|
|
504
|
+
|
|
505
|
+
_require(
|
|
506
|
+
rawQuoteRefPrice >= 0,
|
|
507
|
+
`WooGuardian: INVALID_CHAINLINK_QUOTE_PRICE in _refPrice for ${toToken}`,
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
const baseRefPrice = rawBaseRefPrice * baseInfo.refPriceFixCoeff;
|
|
511
|
+
const quoteRefPrice = rawQuoteRefPrice * quoteInfo.refPriceFixCoeff;
|
|
512
|
+
|
|
513
|
+
return this.dMath.divFloor(baseRefPrice, quoteRefPrice);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
private _boundForTokens(token1: Address, token2: Address) {
|
|
517
|
+
const info1 = this.state.guardian.refInfos[token1];
|
|
518
|
+
const bound1 =
|
|
519
|
+
info1.bound !== 0n ? info1.bound : this.state.guardian.globalBound;
|
|
520
|
+
|
|
521
|
+
const info2 = this.state.guardian.refInfos[token2];
|
|
522
|
+
const bound2 =
|
|
523
|
+
info2.bound != 0n ? info2.bound : this.state.guardian.globalBound;
|
|
524
|
+
|
|
525
|
+
return bound1 > bound2 ? bound1 : bound2;
|
|
526
|
+
}
|
|
527
|
+
}
|