@dhedge/v2-sdk 1.10.2 → 1.10.4
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/dist/entities/pool.d.ts +22 -2
- package/dist/services/compound/lending.d.ts +3 -0
- package/dist/services/uniswap/V3Liquidity.d.ts +2 -2
- package/dist/services/velodrome/liquidity.d.ts +2 -1
- package/dist/test/constants.d.ts +9 -1
- package/dist/types.d.ts +2 -1
- package/dist/v2-sdk.cjs.development.js +590 -427
- 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 +590 -427
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/abi/compound/ICompoundV3Comet.json +51 -0
- package/src/config.ts +2 -1
- package/src/entities/pool.ts +69 -7
- package/src/services/compound/lending.ts +20 -0
- package/src/services/uniswap/V3Liquidity.ts +13 -5
- package/src/services/velodrome/liquidity.ts +2 -1
- package/src/test/aerodromeCL.test.ts +188 -0
- package/src/test/compoundV3.test.ts +90 -0
- package/src/test/constants.ts +14 -6
- package/src/types.ts +2 -1
package/package.json
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"inputs": [],
|
|
4
|
+
"name": "baseToken",
|
|
5
|
+
"outputs": [
|
|
6
|
+
{
|
|
7
|
+
"internalType": "address",
|
|
8
|
+
"name": "",
|
|
9
|
+
"type": "address"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"stateMutability": "view",
|
|
13
|
+
"type": "function"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"inputs": [
|
|
17
|
+
{
|
|
18
|
+
"internalType": "address",
|
|
19
|
+
"name": "asset",
|
|
20
|
+
"type": "address"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"internalType": "uint256",
|
|
24
|
+
"name": "amount",
|
|
25
|
+
"type": "uint256"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"name": "supply",
|
|
29
|
+
"outputs": [],
|
|
30
|
+
"stateMutability": "nonpayable",
|
|
31
|
+
"type": "function"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"inputs": [
|
|
35
|
+
{
|
|
36
|
+
"internalType": "address",
|
|
37
|
+
"name": "asset",
|
|
38
|
+
"type": "address"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"internalType": "uint256",
|
|
42
|
+
"name": "amount",
|
|
43
|
+
"type": "uint256"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"name": "withdraw",
|
|
47
|
+
"outputs": [],
|
|
48
|
+
"stateMutability": "nonpayable",
|
|
49
|
+
"type": "function"
|
|
50
|
+
}
|
|
51
|
+
]
|
package/src/config.ts
CHANGED
|
@@ -113,7 +113,8 @@ export const nonfungiblePositionManagerAddress: AddressDappNetworkMap = {
|
|
|
113
113
|
[Dapp.UNISWAPV3]: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88"
|
|
114
114
|
},
|
|
115
115
|
[Network.BASE]: {
|
|
116
|
-
[Dapp.UNISWAPV3]: "0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1"
|
|
116
|
+
[Dapp.UNISWAPV3]: "0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1",
|
|
117
|
+
[Dapp.AERODROMECL]: "0x827922686190790b37229fd06084350e74485b72"
|
|
117
118
|
}
|
|
118
119
|
};
|
|
119
120
|
|
package/src/entities/pool.ts
CHANGED
|
@@ -72,6 +72,10 @@ import {
|
|
|
72
72
|
mintUnitViaFlatMoney,
|
|
73
73
|
redeemUnitViaFlatMoney
|
|
74
74
|
} from "../services/flatmoney/stableLp";
|
|
75
|
+
import {
|
|
76
|
+
getCompoundV3LendTxData,
|
|
77
|
+
getCompoundV3WithdrawTxData
|
|
78
|
+
} from "../services/compound/lending";
|
|
75
79
|
|
|
76
80
|
export class Pool {
|
|
77
81
|
public readonly poolLogic: Contract;
|
|
@@ -570,6 +574,7 @@ export class Pool {
|
|
|
570
574
|
case Dapp.VELODROMEV2:
|
|
571
575
|
case Dapp.AERODROME:
|
|
572
576
|
case Dapp.VELODROMECL:
|
|
577
|
+
case Dapp.AERODROMECL:
|
|
573
578
|
stakeTxData = getVelodromeStakeTxData(amount, true);
|
|
574
579
|
break;
|
|
575
580
|
default:
|
|
@@ -665,6 +670,7 @@ export class Pool {
|
|
|
665
670
|
this.address,
|
|
666
671
|
referralCode
|
|
667
672
|
]);
|
|
673
|
+
|
|
668
674
|
const tx = await getPoolTxOrGasEstimate(
|
|
669
675
|
this,
|
|
670
676
|
[routerAddress[this.network][dapp], depositTxData, options],
|
|
@@ -673,6 +679,32 @@ export class Pool {
|
|
|
673
679
|
return tx;
|
|
674
680
|
}
|
|
675
681
|
|
|
682
|
+
/**
|
|
683
|
+
* Lend asset to a Compound V3 style lending pool
|
|
684
|
+
* @param {string} market Address of market e.g cUSDCv3 address
|
|
685
|
+
* @param {string} asset Asset
|
|
686
|
+
* @param {BigNumber | string} amount Amount of asset to lend
|
|
687
|
+
* @param {any} options Transaction options
|
|
688
|
+
* @param {boolean} estimateGas Simulate/estimate gas
|
|
689
|
+
* @returns {Promise<any>} Transaction
|
|
690
|
+
*/
|
|
691
|
+
async lendCompoundV3(
|
|
692
|
+
market: string,
|
|
693
|
+
asset: string,
|
|
694
|
+
amount: BigNumber | string,
|
|
695
|
+
options: any = null,
|
|
696
|
+
estimateGas = false
|
|
697
|
+
): Promise<any> {
|
|
698
|
+
const supplyTxData = getCompoundV3LendTxData(asset, amount);
|
|
699
|
+
|
|
700
|
+
const tx = await getPoolTxOrGasEstimate(
|
|
701
|
+
this,
|
|
702
|
+
[market, supplyTxData, options],
|
|
703
|
+
estimateGas
|
|
704
|
+
);
|
|
705
|
+
return tx;
|
|
706
|
+
}
|
|
707
|
+
|
|
676
708
|
/**
|
|
677
709
|
* Witdraw asset from a lending pool
|
|
678
710
|
* @param {Dapp} dapp Platform like Aave
|
|
@@ -694,6 +726,7 @@ export class Pool {
|
|
|
694
726
|
Transaction.WITHDRAW,
|
|
695
727
|
[asset, amount, this.address]
|
|
696
728
|
);
|
|
729
|
+
|
|
697
730
|
const tx = await getPoolTxOrGasEstimate(
|
|
698
731
|
this,
|
|
699
732
|
[routerAddress[this.network][dapp], withdrawTxData, options],
|
|
@@ -702,6 +735,32 @@ export class Pool {
|
|
|
702
735
|
return tx;
|
|
703
736
|
}
|
|
704
737
|
|
|
738
|
+
/**
|
|
739
|
+
* Witdraw asset from a COmpound V3 style lending pool
|
|
740
|
+
* @param {string} market Address of market e.g cUSDCv3 address
|
|
741
|
+
* @param {string} asset Asset
|
|
742
|
+
* @param {BigNumber | string} amount Amount of asset to withdraw
|
|
743
|
+
* @param {any} options Transaction options
|
|
744
|
+
* @param {boolean} estimateGas Simulate/estimate gas
|
|
745
|
+
* @returns {Promise<any>} Transaction
|
|
746
|
+
*/
|
|
747
|
+
async withdrawCompoundV3(
|
|
748
|
+
market: string,
|
|
749
|
+
asset: string,
|
|
750
|
+
amount: BigNumber | string,
|
|
751
|
+
options: any = null,
|
|
752
|
+
estimateGas = false
|
|
753
|
+
): Promise<any> {
|
|
754
|
+
const withdrawTxData = getCompoundV3WithdrawTxData(asset, amount);
|
|
755
|
+
|
|
756
|
+
const tx = await getPoolTxOrGasEstimate(
|
|
757
|
+
this,
|
|
758
|
+
[market, withdrawTxData, options],
|
|
759
|
+
estimateGas
|
|
760
|
+
);
|
|
761
|
+
return tx;
|
|
762
|
+
}
|
|
763
|
+
|
|
705
764
|
/**
|
|
706
765
|
* Borrow asset from a lending pool
|
|
707
766
|
* @param {Dapp} dapp Platform like Aave
|
|
@@ -979,7 +1038,7 @@ export class Pool {
|
|
|
979
1038
|
|
|
980
1039
|
/**
|
|
981
1040
|
* Create UniswapV3 liquidity pool
|
|
982
|
-
* @param {dapp} Platform
|
|
1041
|
+
* @param {dapp} Platform UniswapV3, VelodromeCL or AerodromeCL
|
|
983
1042
|
* @param {string} assetA First asset
|
|
984
1043
|
* @param {string} assetB Second asset
|
|
985
1044
|
* @param {BigNumber | string} amountA Amount first asset
|
|
@@ -994,7 +1053,7 @@ export class Pool {
|
|
|
994
1053
|
* @returns {Promise<any>} Transaction
|
|
995
1054
|
*/
|
|
996
1055
|
async addLiquidityUniswapV3(
|
|
997
|
-
dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL,
|
|
1056
|
+
dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL,
|
|
998
1057
|
assetA: string,
|
|
999
1058
|
assetB: string,
|
|
1000
1059
|
amountA: BigNumber | string,
|
|
@@ -1012,8 +1071,8 @@ export class Pool {
|
|
|
1012
1071
|
(minTick === null || maxTick === null)
|
|
1013
1072
|
)
|
|
1014
1073
|
throw new Error("Need to provide price or tick range");
|
|
1015
|
-
if ((minPrice || maxPrice) && dapp
|
|
1016
|
-
throw new Error("no price conversion for Velodrome CL");
|
|
1074
|
+
if ((minPrice || maxPrice) && dapp !== Dapp.UNISWAPV3)
|
|
1075
|
+
throw new Error("no price conversion for Aerodrome/Velodrome CL");
|
|
1017
1076
|
|
|
1018
1077
|
const mintTxData = await getUniswapV3MintTxData(
|
|
1019
1078
|
dapp,
|
|
@@ -1065,7 +1124,8 @@ export class Pool {
|
|
|
1065
1124
|
dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
|
|
1066
1125
|
break;
|
|
1067
1126
|
case Dapp.VELODROMECL:
|
|
1068
|
-
|
|
1127
|
+
case Dapp.AERODROMECL:
|
|
1128
|
+
const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
|
|
1069
1129
|
if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
|
|
1070
1130
|
dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
|
|
1071
1131
|
} else {
|
|
@@ -1121,7 +1181,8 @@ export class Pool {
|
|
|
1121
1181
|
dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
|
|
1122
1182
|
break;
|
|
1123
1183
|
case Dapp.VELODROMECL:
|
|
1124
|
-
|
|
1184
|
+
case Dapp.AERODROMECL:
|
|
1185
|
+
const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
|
|
1125
1186
|
if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
|
|
1126
1187
|
dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
|
|
1127
1188
|
} else {
|
|
@@ -1201,7 +1262,8 @@ export class Pool {
|
|
|
1201
1262
|
txData = getVelodromeClaimTxData(this, tokenId, true);
|
|
1202
1263
|
break;
|
|
1203
1264
|
case Dapp.VELODROMECL:
|
|
1204
|
-
|
|
1265
|
+
case Dapp.AERODROMECL:
|
|
1266
|
+
const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
|
|
1205
1267
|
if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
|
|
1206
1268
|
contractAddress =
|
|
1207
1269
|
nonfungiblePositionManagerAddress[this.network][dapp];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ethers } from "../..";
|
|
2
|
+
import ICompoundV3Comet from "../../abi/compound/ICompoundV3Comet.json";
|
|
3
|
+
|
|
4
|
+
export function getCompoundV3LendTxData(
|
|
5
|
+
asset: string,
|
|
6
|
+
amount: ethers.BigNumber | string
|
|
7
|
+
): string {
|
|
8
|
+
return new ethers.utils.Interface(
|
|
9
|
+
ICompoundV3Comet
|
|
10
|
+
).encodeFunctionData("supply", [asset, amount]);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getCompoundV3WithdrawTxData(
|
|
14
|
+
asset: string,
|
|
15
|
+
amount: ethers.BigNumber | string
|
|
16
|
+
): string {
|
|
17
|
+
return new ethers.utils.Interface(
|
|
18
|
+
ICompoundV3Comet
|
|
19
|
+
).encodeFunctionData("withdraw", [asset, amount]);
|
|
20
|
+
}
|
|
@@ -70,7 +70,7 @@ export function tryParseTick(
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export async function getUniswapV3MintTxData(
|
|
73
|
-
dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL,
|
|
73
|
+
dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL,
|
|
74
74
|
pool: Pool,
|
|
75
75
|
assetA: string,
|
|
76
76
|
assetB: string,
|
|
@@ -147,7 +147,7 @@ export async function getUniswapV3MintTxData(
|
|
|
147
147
|
INonfungiblePositionManager.abi
|
|
148
148
|
);
|
|
149
149
|
|
|
150
|
-
if (dapp === Dapp.VELODROMECL) {
|
|
150
|
+
if (dapp === Dapp.VELODROMECL || dapp === Dapp.AERODROMECL) {
|
|
151
151
|
iNonfungiblePositionManager = new ethers.utils.Interface(
|
|
152
152
|
IVeldodromePositionManager.abi
|
|
153
153
|
);
|
|
@@ -162,7 +162,7 @@ export async function getUniswapV3MintTxData(
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
export async function getUniswapV3Liquidity(
|
|
165
|
-
dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL,
|
|
165
|
+
dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL,
|
|
166
166
|
tokenId: string,
|
|
167
167
|
pool: Pool
|
|
168
168
|
): Promise<BigNumber> {
|
|
@@ -184,7 +184,11 @@ export async function getIncreaseLiquidityTxData(
|
|
|
184
184
|
amountB: ethers.BigNumber | string
|
|
185
185
|
): Promise<any> {
|
|
186
186
|
let txData;
|
|
187
|
-
if (
|
|
187
|
+
if (
|
|
188
|
+
dapp === Dapp.UNISWAPV3 ||
|
|
189
|
+
dapp === Dapp.VELODROMECL ||
|
|
190
|
+
dapp === Dapp.AERODROMECL
|
|
191
|
+
) {
|
|
188
192
|
const abi = new ethers.utils.Interface(INonfungiblePositionManager.abi);
|
|
189
193
|
txData = abi.encodeFunctionData(Transaction.INCREASE_LIQUIDITY, [
|
|
190
194
|
[tokenId, amountA, amountB, 0, 0, await getDeadline(pool)]
|
|
@@ -214,7 +218,11 @@ export async function getDecreaseLiquidityTxData(
|
|
|
214
218
|
amount = 100
|
|
215
219
|
): Promise<any> {
|
|
216
220
|
let txData;
|
|
217
|
-
if (
|
|
221
|
+
if (
|
|
222
|
+
dapp === Dapp.UNISWAPV3 ||
|
|
223
|
+
dapp === Dapp.VELODROMECL ||
|
|
224
|
+
dapp === Dapp.AERODROMECL
|
|
225
|
+
) {
|
|
218
226
|
const abi = new ethers.utils.Interface(INonfungiblePositionManager.abi);
|
|
219
227
|
const liquidity = (await getUniswapV3Liquidity(dapp, tokenId, pool))
|
|
220
228
|
.times(amount)
|
|
@@ -51,11 +51,12 @@ export async function getVelodromeRemoveLiquidityTxData(
|
|
|
51
51
|
|
|
52
52
|
export async function getVelodromeClOwner(
|
|
53
53
|
pool: Pool,
|
|
54
|
+
dapp: Dapp.VELODROMECL | Dapp.AERODROMECL,
|
|
54
55
|
tokenId: string
|
|
55
56
|
): Promise<string> {
|
|
56
57
|
const iNonfungiblePositionManager = new ethers.Contract(
|
|
57
58
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
58
|
-
nonfungiblePositionManagerAddress[pool.network][
|
|
59
|
+
nonfungiblePositionManagerAddress[pool.network][dapp]!,
|
|
59
60
|
INonfungiblePositionManager.abi,
|
|
60
61
|
pool.signer
|
|
61
62
|
);
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { Dhedge, Pool, ethers } from "..";
|
|
2
|
+
|
|
3
|
+
import { nonfungiblePositionManagerAddress } from "../config";
|
|
4
|
+
import { AssetEnabled, Dapp, Network } from "../types";
|
|
5
|
+
import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
|
|
6
|
+
import {
|
|
7
|
+
TestingRunParams,
|
|
8
|
+
beforeAfterReset,
|
|
9
|
+
setChainlinkTimeout,
|
|
10
|
+
testingHelper
|
|
11
|
+
} from "./utils/testingHelper";
|
|
12
|
+
import { allowanceDelta, balanceDelta } from "./utils/token";
|
|
13
|
+
import INonfungiblePositionManager from "../abi/INonfungiblePositionManager.json";
|
|
14
|
+
|
|
15
|
+
const testAerodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
17
|
+
const AERODROME_POSITION_MANGER = nonfungiblePositionManagerAddress[network][
|
|
18
|
+
Dapp.AERODROMECL
|
|
19
|
+
]!;
|
|
20
|
+
|
|
21
|
+
const USDC = CONTRACT_ADDRESS[network].USDC;
|
|
22
|
+
const USDT = CONTRACT_ADDRESS[network].USDT;
|
|
23
|
+
const USDC_USDT_CL_GAUGE = "0xBd85D45f1636fCEB2359d9Dcf839f12b3cF5AF3F";
|
|
24
|
+
const AERO = CONTRACT_ADDRESS[network].VELO;
|
|
25
|
+
|
|
26
|
+
let dhedge: Dhedge;
|
|
27
|
+
let pool: Pool;
|
|
28
|
+
let velodromePositionManager: ethers.Contract;
|
|
29
|
+
let tokenId: string;
|
|
30
|
+
jest.setTimeout(100000);
|
|
31
|
+
|
|
32
|
+
describe(`[${network}] Aerodrome CL tests`, () => {
|
|
33
|
+
beforeAll(async () => {
|
|
34
|
+
// top up ETH (gas)
|
|
35
|
+
await provider.send("hardhat_setBalance", [
|
|
36
|
+
wallet.address,
|
|
37
|
+
"0x100000000000000"
|
|
38
|
+
]);
|
|
39
|
+
dhedge = new Dhedge(wallet, network);
|
|
40
|
+
pool = await dhedge.loadPool(TEST_POOL[network]);
|
|
41
|
+
|
|
42
|
+
// setChainlinkTimeout
|
|
43
|
+
await setChainlinkTimeout({ pool, provider }, 86400 * 365);
|
|
44
|
+
|
|
45
|
+
const newAssets: AssetEnabled[] = [
|
|
46
|
+
{ asset: USDC, isDeposit: true },
|
|
47
|
+
{ asset: USDT, isDeposit: true },
|
|
48
|
+
{
|
|
49
|
+
asset: AERODROME_POSITION_MANGER,
|
|
50
|
+
isDeposit: false
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
asset: AERO,
|
|
54
|
+
isDeposit: false
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
await pool.managerLogic.changeAssets(newAssets, []);
|
|
58
|
+
|
|
59
|
+
velodromePositionManager = new ethers.Contract(
|
|
60
|
+
AERODROME_POSITION_MANGER,
|
|
61
|
+
INonfungiblePositionManager.abi,
|
|
62
|
+
pool.signer
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
beforeAfterReset({ beforeAll, afterAll, provider });
|
|
67
|
+
|
|
68
|
+
describe("Liquidity", () => {
|
|
69
|
+
it("approves unlimited USDC and USDT on for Aerodrome CL", async () => {
|
|
70
|
+
await pool.approveSpender(AERODROME_POSITION_MANGER, USDC, MAX_AMOUNT);
|
|
71
|
+
await pool.approveSpender(AERODROME_POSITION_MANGER, USDT, MAX_AMOUNT);
|
|
72
|
+
const UsdcAllowanceDelta = await allowanceDelta(
|
|
73
|
+
pool.address,
|
|
74
|
+
USDC,
|
|
75
|
+
AERODROME_POSITION_MANGER,
|
|
76
|
+
pool.signer
|
|
77
|
+
);
|
|
78
|
+
await expect(UsdcAllowanceDelta.gt(0));
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("adds USDC and WETH to a CL (mint position)", async () => {
|
|
82
|
+
const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
|
|
83
|
+
const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
|
|
84
|
+
await pool.addLiquidityUniswapV3(
|
|
85
|
+
Dapp.AERODROMECL,
|
|
86
|
+
USDC,
|
|
87
|
+
USDT,
|
|
88
|
+
usdcBalance.div(2),
|
|
89
|
+
usdtBalance.div(2),
|
|
90
|
+
null,
|
|
91
|
+
null,
|
|
92
|
+
-2,
|
|
93
|
+
4,
|
|
94
|
+
1
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
tokenId = (
|
|
98
|
+
await velodromePositionManager.tokenOfOwnerByIndex(pool.address, 0)
|
|
99
|
+
).toString();
|
|
100
|
+
expect(tokenId).not.toBe(null);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("increases liquidity in a CL position", async () => {
|
|
104
|
+
const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
|
|
105
|
+
const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
|
|
106
|
+
const positionBefore = await velodromePositionManager.positions(
|
|
107
|
+
tokenId
|
|
108
|
+
);
|
|
109
|
+
await pool.increaseLiquidity(
|
|
110
|
+
Dapp.AERODROMECL,
|
|
111
|
+
tokenId,
|
|
112
|
+
usdcBalance.div(2),
|
|
113
|
+
usdtBalance.div(2)
|
|
114
|
+
);
|
|
115
|
+
const positionAfter = await velodromePositionManager.positions(tokenId);
|
|
116
|
+
expect(positionAfter.liquidity.gt(positionBefore.liquidity));
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("decreases liquidity from a CL position", async () => {
|
|
120
|
+
const positionBefore = await velodromePositionManager.positions(
|
|
121
|
+
tokenId
|
|
122
|
+
);
|
|
123
|
+
await pool.decreaseLiquidity(Dapp.AERODROMECL, tokenId, 50);
|
|
124
|
+
const positionAfter = await velodromePositionManager.positions(tokenId);
|
|
125
|
+
expect(positionAfter.liquidity.lt(positionBefore.liquidity));
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("collects fess of a CL position", async () => {
|
|
129
|
+
await provider.send("evm_increaseTime", [24 * 3600 * 3]); // 1 day
|
|
130
|
+
await provider.send("evm_mine", []);
|
|
131
|
+
await pool.claimFees(Dapp.AERODROMECL, tokenId);
|
|
132
|
+
expect((await balanceDelta(pool.address, USDC, pool.signer)).gt(0));
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe("Liquidity staking", () => {
|
|
136
|
+
it("stakes a CL position in gauge", async () => {
|
|
137
|
+
await pool.approveSpender(AERODROME_POSITION_MANGER, USDC, MAX_AMOUNT);
|
|
138
|
+
await pool.approveSpender(AERODROME_POSITION_MANGER, USDT, MAX_AMOUNT);
|
|
139
|
+
const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
|
|
140
|
+
const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
|
|
141
|
+
await pool.addLiquidityUniswapV3(
|
|
142
|
+
Dapp.AERODROMECL,
|
|
143
|
+
USDC,
|
|
144
|
+
USDT,
|
|
145
|
+
usdcBalance.div(2),
|
|
146
|
+
usdtBalance.div(2),
|
|
147
|
+
null,
|
|
148
|
+
null,
|
|
149
|
+
-2,
|
|
150
|
+
4,
|
|
151
|
+
1
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
tokenId = (
|
|
155
|
+
await velodromePositionManager.tokenOfOwnerByIndex(pool.address, 0)
|
|
156
|
+
).toString();
|
|
157
|
+
await pool.approveSpenderNFT(
|
|
158
|
+
USDC_USDT_CL_GAUGE,
|
|
159
|
+
AERODROME_POSITION_MANGER,
|
|
160
|
+
tokenId
|
|
161
|
+
);
|
|
162
|
+
await pool.stakeInGauge(Dapp.AERODROMECL, USDC_USDT_CL_GAUGE, tokenId);
|
|
163
|
+
expect(await velodromePositionManager.ownerOf(tokenId)).toBe(
|
|
164
|
+
USDC_USDT_CL_GAUGE
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("collects fess of a staked CL position", async () => {
|
|
169
|
+
await provider.send("evm_increaseTime", [24 * 3600]); // 1 day
|
|
170
|
+
await provider.send("evm_mine", []);
|
|
171
|
+
await pool.claimFees(Dapp.AERODROMECL, tokenId);
|
|
172
|
+
expect((await balanceDelta(pool.address, AERO, pool.signer)).gt(0));
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("unstakes a CL position from a gauge", async () => {
|
|
176
|
+
await pool.unstakeFromGauge(USDC_USDT_CL_GAUGE, tokenId);
|
|
177
|
+
expect(
|
|
178
|
+
(await velodromePositionManager.ownerOf(tokenId)).toLowerCase()
|
|
179
|
+
).toBe(pool.address.toLowerCase());
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
testingHelper({
|
|
186
|
+
network: Network.BASE,
|
|
187
|
+
testingRun: testAerodromeCL
|
|
188
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
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 { AssetEnabled, Network } from "../types";
|
|
6
|
+
import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
|
|
7
|
+
import {
|
|
8
|
+
TestingRunParams,
|
|
9
|
+
beforeAfterReset,
|
|
10
|
+
setWETHAmount,
|
|
11
|
+
testingHelper
|
|
12
|
+
} from "./utils/testingHelper";
|
|
13
|
+
import { allowanceDelta, balanceDelta } from "./utils/token";
|
|
14
|
+
import { getWalletData } from "./wallet";
|
|
15
|
+
|
|
16
|
+
const testCompoundV3 = ({ network, provider }: TestingRunParams) => {
|
|
17
|
+
const WETH = CONTRACT_ADDRESS[network].WETH;
|
|
18
|
+
const COMPOUNDV3_WETH = CONTRACT_ADDRESS[network].COMPOUNDV3_WETH;
|
|
19
|
+
|
|
20
|
+
let dhedge: Dhedge;
|
|
21
|
+
let pool: Pool;
|
|
22
|
+
jest.setTimeout(100000);
|
|
23
|
+
|
|
24
|
+
describe(`[${network}] compound V3 tests`, () => {
|
|
25
|
+
beforeAll(async () => {
|
|
26
|
+
const { wallet } = getWalletData(network);
|
|
27
|
+
// top up ETH (gas)
|
|
28
|
+
await provider.send("hardhat_setBalance", [
|
|
29
|
+
wallet.address,
|
|
30
|
+
"0x100000000000000"
|
|
31
|
+
]);
|
|
32
|
+
dhedge = new Dhedge(wallet, network);
|
|
33
|
+
pool = await dhedge.loadPool(TEST_POOL[network]);
|
|
34
|
+
await setWETHAmount({
|
|
35
|
+
amount: new BigNumber(1e18).toFixed(0),
|
|
36
|
+
userAddress: pool.address,
|
|
37
|
+
network,
|
|
38
|
+
provider
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const newAssets: AssetEnabled[] = [
|
|
42
|
+
{ asset: WETH, isDeposit: true },
|
|
43
|
+
{
|
|
44
|
+
asset: COMPOUNDV3_WETH,
|
|
45
|
+
isDeposit: false
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
await pool.managerLogic.changeAssets(newAssets, []);
|
|
49
|
+
});
|
|
50
|
+
beforeAfterReset({ beforeAll, afterAll, provider });
|
|
51
|
+
|
|
52
|
+
it("approves unlimited WETH for cWETHv3 market", async () => {
|
|
53
|
+
await pool.approveSpender(COMPOUNDV3_WETH, WETH, MAX_AMOUNT);
|
|
54
|
+
const UsdcAllowanceDelta = await allowanceDelta(
|
|
55
|
+
pool.address,
|
|
56
|
+
WETH,
|
|
57
|
+
COMPOUNDV3_WETH,
|
|
58
|
+
pool.signer
|
|
59
|
+
);
|
|
60
|
+
await expect(UsdcAllowanceDelta.gt(0));
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("lends WETH to CompundV3 WETH market", async () => {
|
|
64
|
+
const wethBalance = await pool.utils.getBalance(WETH, pool.address);
|
|
65
|
+
await pool.lendCompoundV3(COMPOUNDV3_WETH, WETH, wethBalance);
|
|
66
|
+
|
|
67
|
+
const cWETHTokenDelta = await balanceDelta(
|
|
68
|
+
pool.address,
|
|
69
|
+
COMPOUNDV3_WETH,
|
|
70
|
+
pool.signer
|
|
71
|
+
);
|
|
72
|
+
expect(cWETHTokenDelta.gt(0));
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("withdraw WETH from CompundV3 WETH market", async () => {
|
|
76
|
+
const cWETHBalance = await pool.utils.getBalance(
|
|
77
|
+
COMPOUNDV3_WETH,
|
|
78
|
+
pool.address
|
|
79
|
+
);
|
|
80
|
+
await pool.withdrawCompoundV3(COMPOUNDV3_WETH, WETH, cWETHBalance);
|
|
81
|
+
const wethBalance = await balanceDelta(pool.address, WETH, pool.signer);
|
|
82
|
+
expect(wethBalance.gt(0));
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
testingHelper({
|
|
88
|
+
network: Network.ARBITRUM,
|
|
89
|
+
testingRun: testCompoundV3
|
|
90
|
+
});
|
package/src/test/constants.ts
CHANGED
|
@@ -48,6 +48,7 @@ export const TEST_POOL = {
|
|
|
48
48
|
export const CONTRACT_ADDRESS = {
|
|
49
49
|
[Network.POLYGON]: {
|
|
50
50
|
USDC: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
|
|
51
|
+
USDT: "",
|
|
51
52
|
SWETH: "",
|
|
52
53
|
WETH: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
|
|
53
54
|
WBTC: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6",
|
|
@@ -58,13 +59,15 @@ export const CONTRACT_ADDRESS = {
|
|
|
58
59
|
nonfungiblePositionManager: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88"
|
|
59
60
|
},
|
|
60
61
|
VELODROME_CL_USDC_WETH_GAUGE: "",
|
|
61
|
-
VELO: ""
|
|
62
|
+
VELO: "",
|
|
63
|
+
COMPOUNDV3_WETH: ""
|
|
62
64
|
},
|
|
63
65
|
|
|
64
66
|
[Network.OPTIMISM]: {
|
|
65
67
|
USDC: "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
|
|
66
|
-
|
|
68
|
+
USDT: "",
|
|
67
69
|
SWETH: "",
|
|
70
|
+
SUSD: "0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9",
|
|
68
71
|
WETH: "0x4200000000000000000000000000000000000006",
|
|
69
72
|
WBTC: "0x68f180fcCe6836688e9084f035309E29Bf0A2095",
|
|
70
73
|
KWENTA_ETH_PERP_V2: "0x2b3bb4c683bfc5239b029131eef3b1d214478d93",
|
|
@@ -77,10 +80,12 @@ export const CONTRACT_ADDRESS = {
|
|
|
77
80
|
ARRAKIS_USDC_WETH_GAUGE: "",
|
|
78
81
|
ARRAKIS_USDC_WETH_LP: "",
|
|
79
82
|
VELODROME_CL_USDC_WETH_GAUGE: "0xa75127121d28a9BF848F3B70e7Eea26570aa7700",
|
|
80
|
-
VELO: "0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db"
|
|
83
|
+
VELO: "0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db",
|
|
84
|
+
COMPOUNDV3_WETH: ""
|
|
81
85
|
},
|
|
82
86
|
[Network.ARBITRUM]: {
|
|
83
87
|
USDC: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
88
|
+
USDT: "",
|
|
84
89
|
SWETH: "0xbc011A12Da28e8F0f528d9eE5E7039E22F91cf18",
|
|
85
90
|
WETH: "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
|
|
86
91
|
WBTC: "0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f",
|
|
@@ -97,10 +102,12 @@ export const CONTRACT_ADDRESS = {
|
|
|
97
102
|
ARRAKIS_USDC_WETH_LP: "",
|
|
98
103
|
WMATIC: "",
|
|
99
104
|
VELODROME_CL_USDC_WETH_GAUGE: "",
|
|
100
|
-
VELO: ""
|
|
105
|
+
VELO: "",
|
|
106
|
+
COMPOUNDV3_WETH: "0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486"
|
|
101
107
|
},
|
|
102
108
|
[Network.BASE]: {
|
|
103
109
|
USDC: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
110
|
+
USDT: "0xfde4c96c8593536e31f229ea8f37b2ada2699bb2",
|
|
104
111
|
WETH: "0x4200000000000000000000000000000000000006",
|
|
105
112
|
WBTC: "",
|
|
106
113
|
SWETH: "",
|
|
@@ -111,8 +118,9 @@ export const CONTRACT_ADDRESS = {
|
|
|
111
118
|
ARRAKIS_USDC_WETH_GAUGE: "",
|
|
112
119
|
ARRAKIS_USDC_WETH_LP: "",
|
|
113
120
|
WMATIC: "",
|
|
114
|
-
VELODROME_CL_USDC_WETH_GAUGE: "",
|
|
115
|
-
VELO: ""
|
|
121
|
+
VELODROME_CL_USDC_WETH_GAUGE: "0xF33a96b5932D9E9B9A0eDA447AbD8C9d48d2e0c8",
|
|
122
|
+
VELO: "0x940181a94A35A4569E4529A3CDfB74e38FD98631",
|
|
123
|
+
COMPOUNDV3_WETH: ""
|
|
116
124
|
}
|
|
117
125
|
};
|
|
118
126
|
|