@dhedge/v2-sdk 1.9.7 → 1.9.9
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/README.md +38 -4
- package/dist/config.d.ts +7 -1
- package/dist/entities/pool.d.ts +26 -5
- package/dist/services/flatmoney/keeperFee.d.ts +6 -0
- package/dist/services/flatmoney/stableLp.d.ts +9 -0
- package/dist/services/flatmoney/stableModule.d.ts +4 -0
- package/dist/test/utils/testingHelper.d.ts +2 -1
- package/dist/test/wallet.d.ts +1 -0
- package/dist/types.d.ts +2 -1
- package/dist/v2-sdk.cjs.development.js +2901 -6
- package/dist/v2-sdk.cjs.development.js.map +1 -1
- package/dist/v2-sdk.cjs.production.min.js +1 -1
- package/dist/v2-sdk.cjs.production.min.js.map +1 -1
- package/dist/v2-sdk.esm.js +2901 -6
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/abi/flatmoney/DelayedOrder.json +547 -0
- package/src/abi/flatmoney/IFlatcoinVault.json +570 -0
- package/src/abi/flatmoney/KeeperFee.json +364 -0
- package/src/abi/flatmoney/StableModule.json +770 -0
- package/src/config.ts +22 -1
- package/src/entities/pool.ts +73 -4
- package/src/services/flatmoney/keeperFee.ts +84 -0
- package/src/services/flatmoney/stableLp.ts +135 -0
- package/src/services/flatmoney/stableModule.ts +43 -0
- package/src/test/aerodrome.test.ts +154 -0
- package/src/test/flatmoney.test.ts +164 -0
- package/src/test/utils/testingHelper.ts +4 -3
- package/src/test/wallet.ts +4 -1
- package/src/types.ts +2 -1
package/src/config.ts
CHANGED
|
@@ -54,7 +54,9 @@ export const routerAddress: AddressDappNetworkMap = {
|
|
|
54
54
|
},
|
|
55
55
|
[Network.BASE]: {
|
|
56
56
|
[Dapp.ONEINCH]: "0x1111111254EEB25477B68fb85Ed929f73A960582",
|
|
57
|
-
[Dapp.ZEROEX]: "0xdef1c0ded9bec7f1a1670819833240f027b25eff"
|
|
57
|
+
[Dapp.ZEROEX]: "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
|
58
|
+
[Dapp.AERODROME]: "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43",
|
|
59
|
+
[Dapp.AAVEV3]: "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5"
|
|
58
60
|
}
|
|
59
61
|
};
|
|
60
62
|
|
|
@@ -136,3 +138,22 @@ export const UNISWAPV3_QUOTER_ADDRESS =
|
|
|
136
138
|
|
|
137
139
|
export const SYNTHETIX_TRACKING_CODE =
|
|
138
140
|
"0x4448454447450000000000000000000000000000000000000000000000000000";
|
|
141
|
+
|
|
142
|
+
export const flatMoneyContractAddresses: Readonly<Partial<
|
|
143
|
+
Record<
|
|
144
|
+
Network,
|
|
145
|
+
{
|
|
146
|
+
DelayedOrder: string;
|
|
147
|
+
FlatcoinVault: string;
|
|
148
|
+
StableModule: string;
|
|
149
|
+
RETH: string;
|
|
150
|
+
}
|
|
151
|
+
>
|
|
152
|
+
>> = {
|
|
153
|
+
[Network.BASE]: {
|
|
154
|
+
DelayedOrder: "0x6D857e9D24a7566bB72a3FB0847A3E0e4E1c2879",
|
|
155
|
+
FlatcoinVault: "0x95Fa1ddc9a78273f795e67AbE8f1Cd2Cd39831fF",
|
|
156
|
+
StableModule: "0xb95fB324b8A2fAF8ec4f76e3dF46C718402736e2",
|
|
157
|
+
RETH: "0xb6fe221fe9eef5aba221c348ba20a1bf5e73624c"
|
|
158
|
+
}
|
|
159
|
+
};
|
package/src/entities/pool.ts
CHANGED
|
@@ -64,6 +64,11 @@ import {
|
|
|
64
64
|
getExitVestTxData
|
|
65
65
|
} from "../services/ramses/vesting";
|
|
66
66
|
import { getPoolTxOrGasEstimate } from "../utils/contract";
|
|
67
|
+
import {
|
|
68
|
+
cancelOrderViaFlatMoney,
|
|
69
|
+
mintUnitViaFlatMoney,
|
|
70
|
+
redeemUnitViaFlatMoney
|
|
71
|
+
} from "../services/flatmoney/stableLp";
|
|
67
72
|
|
|
68
73
|
export class Pool {
|
|
69
74
|
public readonly poolLogic: Contract;
|
|
@@ -531,6 +536,7 @@ export class Pool {
|
|
|
531
536
|
stakeTxData = getVelodromeStakeTxData(amount, false);
|
|
532
537
|
break;
|
|
533
538
|
case Dapp.VELODROMEV2:
|
|
539
|
+
case Dapp.AERODROME:
|
|
534
540
|
stakeTxData = getVelodromeStakeTxData(amount, true);
|
|
535
541
|
break;
|
|
536
542
|
default:
|
|
@@ -1153,6 +1159,7 @@ export class Pool {
|
|
|
1153
1159
|
txData = getVelodromeClaimTxData(this, tokenId, false);
|
|
1154
1160
|
break;
|
|
1155
1161
|
case Dapp.VELODROMEV2:
|
|
1162
|
+
case Dapp.AERODROME:
|
|
1156
1163
|
contractAddress = tokenId;
|
|
1157
1164
|
txData = getVelodromeClaimTxData(this, tokenId, true);
|
|
1158
1165
|
break;
|
|
@@ -1356,7 +1363,7 @@ export class Pool {
|
|
|
1356
1363
|
|
|
1357
1364
|
/**
|
|
1358
1365
|
* Add liquidity to Velodrome V2 or Ramses pool
|
|
1359
|
-
* @param {Dapp} dapp VelodromeV2 or
|
|
1366
|
+
* @param {Dapp} dapp VelodromeV2, Ramses or Aerodrome
|
|
1360
1367
|
* @param {string} assetA First asset
|
|
1361
1368
|
* @param {string} assetB Second asset
|
|
1362
1369
|
* @param {BigNumber | string} amountA Amount first asset
|
|
@@ -1367,7 +1374,7 @@ export class Pool {
|
|
|
1367
1374
|
* @returns {Promise<any>} Transaction
|
|
1368
1375
|
*/
|
|
1369
1376
|
async addLiquidityV2(
|
|
1370
|
-
dapp: Dapp.VELODROMEV2 | Dapp.RAMSES,
|
|
1377
|
+
dapp: Dapp.VELODROMEV2 | Dapp.RAMSES | Dapp.AERODROME,
|
|
1371
1378
|
assetA: string,
|
|
1372
1379
|
assetB: string,
|
|
1373
1380
|
amountA: BigNumber | string,
|
|
@@ -1397,7 +1404,7 @@ export class Pool {
|
|
|
1397
1404
|
|
|
1398
1405
|
/**
|
|
1399
1406
|
* Remove liquidity from Velodrome V2 or Ramses pool
|
|
1400
|
-
* @param {Dapp} dapp VelodromeV2 or
|
|
1407
|
+
* @param {Dapp} dapp VelodromeV2, Ramses or Aerodrome
|
|
1401
1408
|
* @param {string} assetA First asset
|
|
1402
1409
|
* @param {string} assetB Second asset
|
|
1403
1410
|
* @param {BigNumber | string} amount Amount of LP tokens
|
|
@@ -1407,7 +1414,7 @@ export class Pool {
|
|
|
1407
1414
|
* @returns {Promise<any>} Transaction
|
|
1408
1415
|
*/
|
|
1409
1416
|
async removeLiquidityV2(
|
|
1410
|
-
dapp: Dapp.VELODROMEV2 | Dapp.RAMSES,
|
|
1417
|
+
dapp: Dapp.VELODROMEV2 | Dapp.RAMSES | Dapp.AERODROME,
|
|
1411
1418
|
assetA: string,
|
|
1412
1419
|
assetB: string,
|
|
1413
1420
|
amount: BigNumber | string,
|
|
@@ -1627,4 +1634,66 @@ export class Pool {
|
|
|
1627
1634
|
);
|
|
1628
1635
|
return tx;
|
|
1629
1636
|
}
|
|
1637
|
+
|
|
1638
|
+
/** deposit rETH to mint UNIT via the Flat Money protocol
|
|
1639
|
+
*
|
|
1640
|
+
* @param { BigNumber | string } depositAmount Amount of rETH to deposit
|
|
1641
|
+
* @param { number } slippage slippage, 0.5 represents 0.5%
|
|
1642
|
+
* @param { number | null } maxKeeperFeeInUsd 5 represents $5; null will skip the maxKeeperFee check
|
|
1643
|
+
* @param {any} options Transaction options
|
|
1644
|
+
* @param {boolean} estimateGas Simulate/estimate gas
|
|
1645
|
+
* @returns {Promise<any>} Transaction
|
|
1646
|
+
*/
|
|
1647
|
+
async mintUnitViaFlatMoney(
|
|
1648
|
+
depositAmount: ethers.BigNumber | string,
|
|
1649
|
+
slippage = 0.5,
|
|
1650
|
+
maxKeeperFeeInUsd: number | null,
|
|
1651
|
+
options: any = null,
|
|
1652
|
+
estimateGas = false
|
|
1653
|
+
): Promise<any> {
|
|
1654
|
+
const tx = await mintUnitViaFlatMoney(
|
|
1655
|
+
this,
|
|
1656
|
+
depositAmount,
|
|
1657
|
+
slippage,
|
|
1658
|
+
maxKeeperFeeInUsd,
|
|
1659
|
+
options,
|
|
1660
|
+
estimateGas
|
|
1661
|
+
);
|
|
1662
|
+
return tx;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
/** redeem UNIT via the Flat Money protocol
|
|
1666
|
+
*
|
|
1667
|
+
* @param { BigNumber | string } depositAmount Amount of UNIT to withdraw
|
|
1668
|
+
* @param { number } slippage slippage, 0.5 represents 0.5%
|
|
1669
|
+
* @param { number | null } maxKeeperFeeInUsd 5 represents $5; null will skip the maxKeeperFee check
|
|
1670
|
+
* @param {any} options Transaction options
|
|
1671
|
+
* @param {boolean} estimateGas Simulate/estimate gas
|
|
1672
|
+
* @returns {Promise<any>} Transaction
|
|
1673
|
+
*/
|
|
1674
|
+
async redeemUnitViaFlatMoney(
|
|
1675
|
+
withdrawAmount: ethers.BigNumber | string,
|
|
1676
|
+
slippage = 0.5,
|
|
1677
|
+
maxKeeperFeeInUsd: number | null,
|
|
1678
|
+
options: any = null,
|
|
1679
|
+
estimateGas = false
|
|
1680
|
+
): Promise<any> {
|
|
1681
|
+
const tx = await redeemUnitViaFlatMoney(
|
|
1682
|
+
this,
|
|
1683
|
+
withdrawAmount,
|
|
1684
|
+
slippage,
|
|
1685
|
+
maxKeeperFeeInUsd,
|
|
1686
|
+
options,
|
|
1687
|
+
estimateGas
|
|
1688
|
+
);
|
|
1689
|
+
return tx;
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
async cancelOrderViaFlatMoney(
|
|
1693
|
+
options: any = null,
|
|
1694
|
+
estimateGas = false
|
|
1695
|
+
): Promise<any> {
|
|
1696
|
+
const tx = await cancelOrderViaFlatMoney(this, options, estimateGas);
|
|
1697
|
+
return tx;
|
|
1698
|
+
}
|
|
1630
1699
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Contract, ethers } from "ethers";
|
|
2
|
+
import { Pool } from "../../entities";
|
|
3
|
+
import IFlatcoinVaultAbi from "../../abi/flatmoney/IFlatcoinVault.json";
|
|
4
|
+
import KeeperFeeAbi from "../../abi/flatmoney/KeeperFee.json";
|
|
5
|
+
import { flatMoneyContractAddresses } from "../../config";
|
|
6
|
+
import BigNumber from "bignumber.js";
|
|
7
|
+
|
|
8
|
+
export const getKeeperFeeContract = async (pool: Pool): Promise<Contract> => {
|
|
9
|
+
const flatMoneyContracts = flatMoneyContractAddresses[pool.network];
|
|
10
|
+
if (!flatMoneyContracts) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
`getStableModuleContract: network of ${pool.network} not supported`
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
const flatcoinVaultContract = new Contract(
|
|
16
|
+
flatMoneyContracts.FlatcoinVault,
|
|
17
|
+
IFlatcoinVaultAbi,
|
|
18
|
+
pool.signer
|
|
19
|
+
);
|
|
20
|
+
const key = ethers.utils.formatBytes32String("keeperFee");
|
|
21
|
+
const keeperFeeContractAddress: string = await flatcoinVaultContract.callStatic.moduleAddress(
|
|
22
|
+
key
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const keeperFeeContract = new ethers.Contract(
|
|
26
|
+
keeperFeeContractAddress,
|
|
27
|
+
KeeperFeeAbi,
|
|
28
|
+
pool.signer
|
|
29
|
+
);
|
|
30
|
+
return keeperFeeContract;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const getKeeperFee = async (
|
|
34
|
+
pool: Pool,
|
|
35
|
+
maxKeeperFeeInUsd: number | null
|
|
36
|
+
): Promise<ethers.BigNumber> => {
|
|
37
|
+
const keeperFeeContract = await getKeeperFeeContract(pool);
|
|
38
|
+
const gasPrice = await pool.signer.provider.getGasPrice();
|
|
39
|
+
|
|
40
|
+
let keeperfee: ethers.BigNumber;
|
|
41
|
+
if (gasPrice) {
|
|
42
|
+
keeperfee = await keeperFeeContract["getKeeperFee(uint256)"](
|
|
43
|
+
new BigNumber(gasPrice.toString()).times(1.2).toFixed(0)
|
|
44
|
+
);
|
|
45
|
+
} else {
|
|
46
|
+
keeperfee = await keeperFeeContract["getKeeperFee()"]();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const keeperFeeInUsd = await getKeeperFeeInUsd(pool, keeperfee);
|
|
50
|
+
|
|
51
|
+
if (
|
|
52
|
+
Number.isFinite(maxKeeperFeeInUsd) &&
|
|
53
|
+
keeperFeeInUsd.gt(ethers.BigNumber.from(maxKeeperFeeInUsd).toString())
|
|
54
|
+
) {
|
|
55
|
+
throw new Error("mintUnitViaFlatMoney: keeperFee too large");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return keeperfee;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const getKeeperFeeInUsd = async (
|
|
62
|
+
pool: Pool,
|
|
63
|
+
keeperFee: ethers.BigNumber
|
|
64
|
+
): Promise<BigNumber> => {
|
|
65
|
+
const flatMoneyContracts = flatMoneyContractAddresses[pool.network];
|
|
66
|
+
if (!flatMoneyContracts) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`getKeeperFeeInUsd: network of ${pool.network} not supported`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const fundComposition = await pool.getComposition();
|
|
72
|
+
const filteredFc = fundComposition.filter(
|
|
73
|
+
fc =>
|
|
74
|
+
fc.asset.toLocaleLowerCase() ===
|
|
75
|
+
flatMoneyContracts.RETH.toLocaleLowerCase()
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (!filteredFc[0])
|
|
79
|
+
throw new Error(`getKeeperFeeInUsd: required asset not enabled yet`);
|
|
80
|
+
|
|
81
|
+
const rateD1 = new BigNumber(filteredFc[0].rate.toString()).div(1e18);
|
|
82
|
+
|
|
83
|
+
return rateD1.times(keeperFee.toString()).div(1e18);
|
|
84
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
|
|
3
|
+
import BigNumber from "bignumber.js";
|
|
4
|
+
import { Pool, ethers } from "../..";
|
|
5
|
+
import DelayedOrderAbi from "../../abi/flatmoney/DelayedOrder.json";
|
|
6
|
+
import { flatMoneyContractAddresses } from "../../config";
|
|
7
|
+
import { getPoolTxOrGasEstimate } from "../../utils/contract";
|
|
8
|
+
import { getStableDepositQuote, getStableWithdrawQuote } from "./stableModule";
|
|
9
|
+
import { getKeeperFee } from "./keeperFee";
|
|
10
|
+
|
|
11
|
+
export function getAnnounceStableDepositTxData(
|
|
12
|
+
depositAmount: ethers.BigNumber | string,
|
|
13
|
+
minAmountOut: ethers.BigNumber | string,
|
|
14
|
+
keeperFee: ethers.BigNumber | string
|
|
15
|
+
): string {
|
|
16
|
+
return new ethers.utils.Interface(
|
|
17
|
+
DelayedOrderAbi
|
|
18
|
+
).encodeFunctionData("announceStableDeposit", [
|
|
19
|
+
depositAmount,
|
|
20
|
+
minAmountOut,
|
|
21
|
+
keeperFee
|
|
22
|
+
]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getAnnounceStableWithdrawTxData(
|
|
26
|
+
withdrawAmount: ethers.BigNumber | string,
|
|
27
|
+
minAmountOut: ethers.BigNumber | string,
|
|
28
|
+
keeperFee: ethers.BigNumber | string
|
|
29
|
+
): string {
|
|
30
|
+
return new ethers.utils.Interface(
|
|
31
|
+
DelayedOrderAbi
|
|
32
|
+
).encodeFunctionData("announceStableWithdraw", [
|
|
33
|
+
withdrawAmount,
|
|
34
|
+
minAmountOut,
|
|
35
|
+
keeperFee
|
|
36
|
+
]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getCancelExistingOrderTxData(account: string): string {
|
|
40
|
+
return new ethers.utils.Interface(
|
|
41
|
+
DelayedOrderAbi
|
|
42
|
+
).encodeFunctionData("cancelExistingOrder", [account]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function mintUnitViaFlatMoney(
|
|
46
|
+
pool: Pool,
|
|
47
|
+
depositAmount: ethers.BigNumber | string,
|
|
48
|
+
slippage: number, // 0.5 means 0.5%
|
|
49
|
+
maxKeeperFeeInUsd: number | null,
|
|
50
|
+
options: any = null,
|
|
51
|
+
estimateGas = false
|
|
52
|
+
): Promise<any> {
|
|
53
|
+
const flatMoneyContracts = flatMoneyContractAddresses[pool.network];
|
|
54
|
+
if (!flatMoneyContracts) {
|
|
55
|
+
throw new Error("mintUnitViaFlatMoney: network not supported");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const keeperfee = await getKeeperFee(pool, maxKeeperFeeInUsd); // in RETH
|
|
59
|
+
|
|
60
|
+
const adjustedDepositAmount = new BigNumber(depositAmount.toString()).minus(
|
|
61
|
+
keeperfee.toString() // keeper fee deducted from amountIn
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const amountOut = await getStableDepositQuote(
|
|
65
|
+
pool,
|
|
66
|
+
adjustedDepositAmount.toFixed(0)
|
|
67
|
+
);
|
|
68
|
+
const minAmountOut = new BigNumber(amountOut.toString())
|
|
69
|
+
.times(1 - slippage / 100)
|
|
70
|
+
.toFixed(0);
|
|
71
|
+
|
|
72
|
+
const mintUnitTxData = await getAnnounceStableDepositTxData(
|
|
73
|
+
adjustedDepositAmount.toFixed(0),
|
|
74
|
+
minAmountOut,
|
|
75
|
+
keeperfee
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const tx = await getPoolTxOrGasEstimate(
|
|
79
|
+
pool,
|
|
80
|
+
[flatMoneyContracts.DelayedOrder, mintUnitTxData, options],
|
|
81
|
+
estimateGas
|
|
82
|
+
);
|
|
83
|
+
return tx;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function redeemUnitViaFlatMoney(
|
|
87
|
+
pool: Pool,
|
|
88
|
+
withdrawAmount: ethers.BigNumber | string,
|
|
89
|
+
slippage: number, // 0.5 means 0.5%
|
|
90
|
+
maxKeeperFeeInUsd: number | null,
|
|
91
|
+
options: any = null,
|
|
92
|
+
estimateGas = false
|
|
93
|
+
): Promise<any> {
|
|
94
|
+
const flatMoneyContracts = flatMoneyContractAddresses[pool.network];
|
|
95
|
+
if (!flatMoneyContracts) {
|
|
96
|
+
throw new Error("redeemUnitViaFlatMoney: network not supported");
|
|
97
|
+
}
|
|
98
|
+
const keeperfee = await getKeeperFee(pool, maxKeeperFeeInUsd); // in RETH
|
|
99
|
+
|
|
100
|
+
const amountOut = await getStableWithdrawQuote(pool, withdrawAmount);
|
|
101
|
+
const minAmountOut = new BigNumber(amountOut.toString())
|
|
102
|
+
.times(1 - slippage / 100)
|
|
103
|
+
.minus(keeperfee.toString()) // keeper fee deducted from amountOut
|
|
104
|
+
.toFixed(0);
|
|
105
|
+
|
|
106
|
+
const redeemUnitTxData = await getAnnounceStableWithdrawTxData(
|
|
107
|
+
withdrawAmount,
|
|
108
|
+
minAmountOut,
|
|
109
|
+
keeperfee
|
|
110
|
+
);
|
|
111
|
+
const tx = await getPoolTxOrGasEstimate(
|
|
112
|
+
pool,
|
|
113
|
+
[flatMoneyContracts.DelayedOrder, redeemUnitTxData, options],
|
|
114
|
+
estimateGas
|
|
115
|
+
);
|
|
116
|
+
return tx;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export async function cancelOrderViaFlatMoney(
|
|
120
|
+
pool: Pool,
|
|
121
|
+
options: any = null,
|
|
122
|
+
estimateGas = false
|
|
123
|
+
): Promise<any> {
|
|
124
|
+
const flatMoneyContracts = flatMoneyContractAddresses[pool.network];
|
|
125
|
+
if (!flatMoneyContracts) {
|
|
126
|
+
throw new Error("cancelOrderViaFlatMoney: network not supported");
|
|
127
|
+
}
|
|
128
|
+
const cancelOrderTxData = await getCancelExistingOrderTxData(pool.address);
|
|
129
|
+
const tx = await getPoolTxOrGasEstimate(
|
|
130
|
+
pool,
|
|
131
|
+
[flatMoneyContracts.DelayedOrder, cancelOrderTxData, options],
|
|
132
|
+
estimateGas
|
|
133
|
+
);
|
|
134
|
+
return tx;
|
|
135
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BigNumber, Contract } from "ethers";
|
|
2
|
+
import { flatMoneyContractAddresses } from "../../config";
|
|
3
|
+
import { Pool } from "../../entities";
|
|
4
|
+
import StableModuleAbi from "../../abi/flatmoney/StableModule.json";
|
|
5
|
+
|
|
6
|
+
const getStableModuleContract = (pool: Pool): Contract => {
|
|
7
|
+
const flatMoneyContracts = flatMoneyContractAddresses[pool.network];
|
|
8
|
+
if (!flatMoneyContracts) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`getStableModuleContract: network of ${pool.network} not supported`
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
const stableModuleContract = new Contract(
|
|
14
|
+
flatMoneyContracts.StableModule,
|
|
15
|
+
StableModuleAbi,
|
|
16
|
+
pool.signer
|
|
17
|
+
);
|
|
18
|
+
return stableModuleContract;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/// @notice Quoter function for getting the stable deposit amount out.
|
|
22
|
+
export const getStableDepositQuote = async (
|
|
23
|
+
pool: Pool,
|
|
24
|
+
depositAmount: string | BigNumber
|
|
25
|
+
): Promise<BigNumber> => {
|
|
26
|
+
const stableModuleContract = getStableModuleContract(pool);
|
|
27
|
+
const amountOut: BigNumber = await stableModuleContract.stableDepositQuote(
|
|
28
|
+
depositAmount.toString()
|
|
29
|
+
);
|
|
30
|
+
return amountOut;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/// @notice Quoter function for getting the stable withdraw amount out.
|
|
34
|
+
export const getStableWithdrawQuote = async (
|
|
35
|
+
pool: Pool,
|
|
36
|
+
withdrawAmount: string | BigNumber
|
|
37
|
+
): Promise<BigNumber> => {
|
|
38
|
+
const stableModuleContract = getStableModuleContract(pool);
|
|
39
|
+
const amountOut: BigNumber = await stableModuleContract.stableWithdrawQuote(
|
|
40
|
+
withdrawAmount.toString()
|
|
41
|
+
);
|
|
42
|
+
return amountOut;
|
|
43
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
import BigNumber from "bignumber.js";
|
|
4
|
+
import { Dhedge, Pool } from "..";
|
|
5
|
+
import { routerAddress } from "../config";
|
|
6
|
+
import { Dapp, Network } from "../types";
|
|
7
|
+
import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
|
|
8
|
+
import {
|
|
9
|
+
TestingRunParams,
|
|
10
|
+
beforeAfterReset,
|
|
11
|
+
setUSDCAmount,
|
|
12
|
+
testingHelper
|
|
13
|
+
} from "./utils/testingHelper";
|
|
14
|
+
import { allowanceDelta, balanceDelta } from "./utils/token";
|
|
15
|
+
import { getWalletData } from "./wallet";
|
|
16
|
+
|
|
17
|
+
const testAerodrome = ({ network, provider }: TestingRunParams) => {
|
|
18
|
+
const WETH_USDC_Lp = "0xcDAC0d6c6C59727a65F871236188350531885C43";
|
|
19
|
+
const WETH_USDC__Gauge = "0x519BBD1Dd8C6A94C46080E24f316c14Ee758C025";
|
|
20
|
+
|
|
21
|
+
const USDC = CONTRACT_ADDRESS[network].USDC;
|
|
22
|
+
const WETH = CONTRACT_ADDRESS[network].WETH;
|
|
23
|
+
const AERO = "0x940181a94A35A4569E4529A3CDfB74e38FD98631";
|
|
24
|
+
|
|
25
|
+
let dhedge: Dhedge;
|
|
26
|
+
let pool: Pool;
|
|
27
|
+
jest.setTimeout(100000);
|
|
28
|
+
|
|
29
|
+
describe(`[${network}] aerodrome tests`, () => {
|
|
30
|
+
beforeAll(async () => {
|
|
31
|
+
const { wallet } = getWalletData(network);
|
|
32
|
+
// top up ETH (gas)
|
|
33
|
+
await provider.send("hardhat_setBalance", [
|
|
34
|
+
wallet.address,
|
|
35
|
+
"0x100000000000000"
|
|
36
|
+
]);
|
|
37
|
+
dhedge = new Dhedge(wallet, network);
|
|
38
|
+
pool = await dhedge.loadPool(TEST_POOL[network]);
|
|
39
|
+
await setUSDCAmount({
|
|
40
|
+
amount: new BigNumber(10).times(1e6).toFixed(0),
|
|
41
|
+
userAddress: pool.address,
|
|
42
|
+
network,
|
|
43
|
+
provider
|
|
44
|
+
});
|
|
45
|
+
await pool.approve(Dapp.ONEINCH, USDC, MAX_AMOUNT);
|
|
46
|
+
await pool.trade(Dapp.ONEINCH, USDC, WETH, (5 * 1e6).toString());
|
|
47
|
+
});
|
|
48
|
+
beforeAfterReset({ beforeAll, afterAll, provider });
|
|
49
|
+
|
|
50
|
+
it("approves unlimited USDC and swETH on for Aerodrome", async () => {
|
|
51
|
+
await pool.approve(Dapp.AERODROME, USDC, MAX_AMOUNT);
|
|
52
|
+
await pool.approve(Dapp.AERODROME, WETH, MAX_AMOUNT);
|
|
53
|
+
const UsdcAllowanceDelta = await allowanceDelta(
|
|
54
|
+
pool.address,
|
|
55
|
+
USDC,
|
|
56
|
+
routerAddress[network].aerodrome!,
|
|
57
|
+
pool.signer
|
|
58
|
+
);
|
|
59
|
+
await expect(UsdcAllowanceDelta.gt(0));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("adds USDC and WETH to a Aerodrome volatile pool", async () => {
|
|
63
|
+
const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
|
|
64
|
+
const wethBalance = await pool.utils.getBalance(WETH, pool.address);
|
|
65
|
+
await pool.addLiquidityV2(
|
|
66
|
+
Dapp.AERODROME,
|
|
67
|
+
WETH,
|
|
68
|
+
USDC,
|
|
69
|
+
wethBalance,
|
|
70
|
+
usdcBalance,
|
|
71
|
+
false
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const lpTokenDelta = await balanceDelta(
|
|
75
|
+
pool.address,
|
|
76
|
+
WETH_USDC_Lp,
|
|
77
|
+
pool.signer
|
|
78
|
+
);
|
|
79
|
+
expect(lpTokenDelta.gt(0));
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should stake WETH-USDC LP in a gauge", async () => {
|
|
83
|
+
const balance = await dhedge.utils.getBalance(WETH_USDC_Lp, pool.address);
|
|
84
|
+
await pool.approveSpender(WETH_USDC__Gauge, WETH_USDC_Lp, MAX_AMOUNT);
|
|
85
|
+
await pool.stakeInGauge(Dapp.AERODROME, WETH_USDC__Gauge, balance);
|
|
86
|
+
const gaugeBalance = await balanceDelta(
|
|
87
|
+
pool.address,
|
|
88
|
+
WETH_USDC__Gauge,
|
|
89
|
+
pool.signer
|
|
90
|
+
);
|
|
91
|
+
expect(gaugeBalance.gt(0));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("should claim rewards from Gauge", async () => {
|
|
95
|
+
await provider.send("evm_increaseTime", [24 * 60 * 60]); // 1 day
|
|
96
|
+
await provider.send("evm_mine", []);
|
|
97
|
+
const claimTx = await pool.claimFees(Dapp.AERODROME, WETH_USDC__Gauge);
|
|
98
|
+
expect(claimTx).not.toBe(null);
|
|
99
|
+
const aeroBalanceDelta = await balanceDelta(
|
|
100
|
+
pool.address,
|
|
101
|
+
AERO,
|
|
102
|
+
pool.signer
|
|
103
|
+
);
|
|
104
|
+
expect(aeroBalanceDelta.gt(0));
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("should unStakeWETH-USDC LP from a gauge", async () => {
|
|
108
|
+
const gaugeBalance = await dhedge.utils.getBalance(
|
|
109
|
+
WETH_USDC__Gauge,
|
|
110
|
+
pool.address
|
|
111
|
+
);
|
|
112
|
+
await pool.unstakeFromGauge(WETH_USDC__Gauge, gaugeBalance);
|
|
113
|
+
const lpTokenDelta = await balanceDelta(
|
|
114
|
+
pool.address,
|
|
115
|
+
WETH_USDC_Lp,
|
|
116
|
+
pool.signer
|
|
117
|
+
);
|
|
118
|
+
expect(lpTokenDelta.gt(0));
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("approves unlimited WETH-USDC LP for Aerodrome", async () => {
|
|
122
|
+
await pool.approve(Dapp.AERODROME, WETH_USDC_Lp, MAX_AMOUNT);
|
|
123
|
+
const lpAllowanceDelta = await allowanceDelta(
|
|
124
|
+
pool.address,
|
|
125
|
+
WETH_USDC_Lp,
|
|
126
|
+
routerAddress[network].aerodrome!,
|
|
127
|
+
pool.signer
|
|
128
|
+
);
|
|
129
|
+
expect(lpAllowanceDelta.gt(0));
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should remove all liquidity from an existing pool ", async () => {
|
|
133
|
+
const balance = await dhedge.utils.getBalance(WETH_USDC_Lp, pool.address);
|
|
134
|
+
await pool.removeLiquidityV2(Dapp.AERODROME, WETH, USDC, balance, false);
|
|
135
|
+
const usdcBalanceDelta = await balanceDelta(
|
|
136
|
+
pool.address,
|
|
137
|
+
USDC,
|
|
138
|
+
pool.signer
|
|
139
|
+
);
|
|
140
|
+
const wethBalanceDelta = await balanceDelta(
|
|
141
|
+
pool.address,
|
|
142
|
+
WETH,
|
|
143
|
+
pool.signer
|
|
144
|
+
);
|
|
145
|
+
expect(usdcBalanceDelta.gt(0));
|
|
146
|
+
expect(wethBalanceDelta.gt(0));
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
testingHelper({
|
|
152
|
+
network: Network.BASE,
|
|
153
|
+
testingRun: testAerodrome
|
|
154
|
+
});
|