@enzymefinance/testutils 4.0.0-next.6 → 4.0.0-next.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 (34) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/declarations/src/deployment.d.ts +19 -16
  3. package/dist/declarations/src/scaffolding/assets.d.ts +1 -1
  4. package/dist/declarations/src/scaffolding/core.d.ts +2 -3
  5. package/dist/declarations/src/scaffolding/extensions/external-positions/actions.d.ts +2 -1
  6. package/dist/declarations/src/scaffolding/extensions/external-positions/mocks.d.ts +4 -1
  7. package/dist/declarations/src/scaffolding/extensions/external-positions/uniswap-v3-liquidity.d.ts +12 -11
  8. package/dist/declarations/src/scaffolding/extensions/fees.d.ts +3 -3
  9. package/dist/declarations/src/scaffolding/extensions/integrations/aave.d.ts +2 -2
  10. package/dist/declarations/src/scaffolding/extensions/integrations/compound.d.ts +30 -2
  11. package/dist/declarations/src/scaffolding/extensions/integrations/curve.d.ts +13 -71
  12. package/dist/declarations/src/scaffolding/extensions/integrations/idle.d.ts +3 -3
  13. package/dist/declarations/src/scaffolding/extensions/integrations/olympusV2.d.ts +2 -2
  14. package/dist/declarations/src/scaffolding/extensions/integrations/synthetix.d.ts +5 -10
  15. package/dist/declarations/src/scaffolding/extensions/integrations/yearn.d.ts +2 -2
  16. package/dist/declarations/src/scaffolding/extensions/integrations/zeroExV2.d.ts +1 -1
  17. package/dist/declarations/src/scaffolding/extensions/policies.d.ts +8 -8
  18. package/dist/declarations/src/whales.d.ts +6 -3
  19. package/dist/enzymefinance-testutils.browser.cjs.js +403 -344
  20. package/dist/enzymefinance-testutils.browser.esm.js +402 -338
  21. package/dist/enzymefinance-testutils.cjs.dev.js +403 -344
  22. package/dist/enzymefinance-testutils.cjs.prod.js +403 -344
  23. package/dist/enzymefinance-testutils.esm.js +402 -338
  24. package/package.json +6 -6
  25. package/src/deployment.ts +19 -15
  26. package/src/scaffolding/core.ts +1 -9
  27. package/src/scaffolding/extensions/external-positions/actions.ts +6 -1
  28. package/src/scaffolding/extensions/external-positions/mocks.ts +7 -10
  29. package/src/scaffolding/extensions/external-positions/uniswap-v3-liquidity.ts +18 -24
  30. package/src/scaffolding/extensions/integrations/compound.ts +163 -2
  31. package/src/scaffolding/extensions/integrations/curve.ts +21 -238
  32. package/src/scaffolding/extensions/integrations/synthetix.ts +6 -25
  33. package/src/types.d.ts +1 -0
  34. package/src/whales.ts +8 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enzymefinance/testutils",
3
- "version": "4.0.0-next.6",
3
+ "version": "4.0.0-next.7",
4
4
  "main": "dist/enzymefinance-testutils.cjs.js",
5
5
  "module": "dist/enzymefinance-testutils.esm.js",
6
6
  "browser": {
@@ -8,10 +8,10 @@
8
8
  "./dist/enzymefinance-testutils.esm.js": "./dist/enzymefinance-testutils.browser.esm.js"
9
9
  },
10
10
  "dependencies": {
11
- "@babel/runtime": "^7.15.4",
12
- "@enzymefinance/ethers": "^1.0.11",
13
- "@enzymefinance/hardhat": "^1.0.12",
14
- "@enzymefinance/protocol": "^4.0.0-next.6",
15
- "ethers": "^5.5.3"
11
+ "@babel/runtime": "^7.16.7",
12
+ "@enzymefinance/ethers": "^1.0.16",
13
+ "@enzymefinance/hardhat": "^1.0.16",
14
+ "@enzymefinance/protocol": "^4.0.0-next.7",
15
+ "ethers": "^5.5.4"
16
16
  }
17
17
  }
package/src/deployment.ts CHANGED
@@ -8,17 +8,18 @@ import {
8
8
  AllowedDepositRecipientsPolicy,
9
9
  AllowedExternalPositionTypesPolicy,
10
10
  AllowedSharesTransferRecipientsPolicy,
11
- AssetFinalityResolver,
12
11
  CompoundAdapter,
13
12
  CompoundDebtPositionLib,
14
13
  CompoundDebtPositionParser,
15
14
  CompoundPriceFeed,
16
15
  ComptrollerLib,
16
+ ConvexCurveLpStakingAdapter,
17
+ ConvexCurveLpStakingWrapperFactory,
18
+ ConvexCurveLpStakingWrapperPriceFeed,
17
19
  CumulativeSlippageTolerancePolicy,
18
20
  CurveExchangeAdapter,
19
21
  CurveLiquidityAaveAdapter,
20
22
  CurveLiquidityAdapter,
21
- CurveLiquidityEursAdapter,
22
23
  CurveLiquiditySethAdapter,
23
24
  CurveLiquidityStethAdapter,
24
25
  CurvePriceFeed,
@@ -35,8 +36,9 @@ import {
35
36
  FundValueCalculator,
36
37
  FundValueCalculatorRouter,
37
38
  FundValueCalculatorUsdWrapper,
39
+ FuseAdapter,
40
+ FusePriceFeed,
38
41
  GasRelayPaymasterFactory,
39
- GuaranteedRedemptionPolicy,
40
42
  IdleAdapter,
41
43
  IdlePriceFeed,
42
44
  IntegrationManager,
@@ -58,7 +60,6 @@ import {
58
60
  RevertingPriceFeed,
59
61
  StakehoundEthPriceFeed,
60
62
  SynthetixAdapter,
61
- SynthetixPriceFeed,
62
63
  UniswapV2ExchangeAdapter,
63
64
  UniswapV2LiquidityAdapter,
64
65
  UniswapV2PoolPriceFeed,
@@ -103,17 +104,18 @@ export async function deployProtocolFixture() {
103
104
  allowedDepositRecipientsPolicy: new AllowedDepositRecipientsPolicy(fixture['AllowedDepositRecipientsPolicy'].address, deployer),
104
105
  allowedExternalPositionTypesPolicy: new AllowedExternalPositionTypesPolicy(fixture['AllowedExternalPositionTypesPolicy'].address, deployer),
105
106
  allowedSharesTransferRecipientsPolicy: new AllowedSharesTransferRecipientsPolicy(fixture['AllowedSharesTransferRecipientsPolicy'].address, deployer),
106
- assetFinalityResolver: new AssetFinalityResolver(fixture['AssetFinalityResolver'].address, deployer),
107
107
  compoundAdapter: new CompoundAdapter(fixture['CompoundAdapter'].address, deployer),
108
108
  compoundDebtPositionLib: new CompoundDebtPositionLib(fixture['CompoundDebtPositionLib'].address, deployer),
109
109
  compoundDebtPositionParser: new CompoundDebtPositionParser(fixture['CompoundDebtPositionParser'].address, deployer),
110
110
  compoundPriceFeed: new CompoundPriceFeed(fixture['CompoundPriceFeed'].address, deployer),
111
111
  comptrollerLib: new ComptrollerLib(fixture['ComptrollerLib'].address, deployer),
112
+ convexCurveLpStakingAdapter: new ConvexCurveLpStakingAdapter(fixture['ConvexCurveLpStakingAdapter'].address, deployer),
113
+ convexCurveLpStakingWrapperFactory: new ConvexCurveLpStakingWrapperFactory(fixture['ConvexCurveLpStakingWrapperFactory'].address, deployer),
114
+ convexCurveLpStakingWrapperPriceFeed: new ConvexCurveLpStakingWrapperPriceFeed(fixture['ConvexCurveLpStakingWrapperPriceFeed'].address, deployer),
112
115
  cumulativeSlippageTolerancePolicy: new CumulativeSlippageTolerancePolicy(fixture['CumulativeSlippageTolerancePolicy'].address, deployer),
113
116
  curveExchangeAdapter: new CurveExchangeAdapter(fixture['CurveExchangeAdapter'].address, deployer),
114
117
  curveLiquidityAaveAdapter: new CurveLiquidityAaveAdapter(fixture['CurveLiquidityAaveAdapter'].address, deployer),
115
118
  curveLiquidityAdapter: new CurveLiquidityAdapter(fixture['CurveLiquidityAdapter'].address, deployer),
116
- curveLiquidityEursAdapter: new CurveLiquidityEursAdapter(fixture['CurveLiquidityEursAdapter'].address, deployer),
117
119
  curveLiquiditySethAdapter: new CurveLiquiditySethAdapter(fixture['CurveLiquiditySethAdapter'].address, deployer),
118
120
  curveLiquidityStethAdapter: new CurveLiquidityStethAdapter(fixture['CurveLiquidityStethAdapter'].address, deployer),
119
121
  curvePriceFeed: new CurvePriceFeed(fixture['CurvePriceFeed'].address, deployer),
@@ -130,8 +132,9 @@ export async function deployProtocolFixture() {
130
132
  fundValueCalculator: new FundValueCalculator(fixture['FundValueCalculator'].address, deployer),
131
133
  fundValueCalculatorRouter: new FundValueCalculatorRouter(fixture['FundValueCalculatorRouter'].address, deployer),
132
134
  fundValueCalculatorUsdWrapper: new FundValueCalculatorUsdWrapper(fixture['FundValueCalculatorUsdWrapper'].address, deployer),
135
+ fuseAdapter: new FuseAdapter(fixture['FuseAdapter'].address, deployer),
136
+ fusePriceFeed: new FusePriceFeed(fixture['FusePriceFeed'].address, deployer),
133
137
  gasRelayPaymasterFactory: new GasRelayPaymasterFactory(fixture['GasRelayPaymasterFactory'].address, deployer),
134
- guaranteedRedemptionPolicy: new GuaranteedRedemptionPolicy(fixture['GuaranteedRedemptionPolicy'].address, deployer),
135
138
  idleAdapter: new IdleAdapter(fixture['IdleAdapter'].address, deployer),
136
139
  idlePriceFeed: new IdlePriceFeed(fixture['IdlePriceFeed'].address, deployer),
137
140
  integrationManager: new IntegrationManager(fixture['IntegrationManager'].address, deployer),
@@ -154,7 +157,6 @@ export async function deployProtocolFixture() {
154
157
  revertingPriceFeed: new RevertingPriceFeed(fixture['RevertingPriceFeed'].address, deployer),
155
158
  stakehoundEthPriceFeed: new StakehoundEthPriceFeed(fixture['StakehoundEthPriceFeed'].address, deployer),
156
159
  synthetixAdapter: new SynthetixAdapter(fixture['SynthetixAdapter'].address, deployer),
157
- synthetixPriceFeed: new SynthetixPriceFeed(fixture['SynthetixPriceFeed'].address, deployer),
158
160
  uniswapV2ExchangeAdapter: new UniswapV2ExchangeAdapter(fixture['UniswapV2ExchangeAdapter'].address, deployer),
159
161
  uniswapV2LiquidityAdapter: new UniswapV2LiquidityAdapter(fixture['UniswapV2LiquidityAdapter'].address, deployer),
160
162
  uniswapV2PoolPriceFeed: new UniswapV2PoolPriceFeed(fixture['UniswapV2PoolPriceFeed'].address, deployer),
@@ -203,13 +205,16 @@ export interface DeploymentConfig {
203
205
  synthetix: {
204
206
  snx: string;
205
207
  susd: string;
206
- synths: Record<string, string>;
207
- addressResolver: string;
208
208
  delegateApprovals: string;
209
209
  originator: string;
210
210
  redeemer: string;
211
211
  trackingCode: string;
212
212
  };
213
+ convex: {
214
+ booster: string;
215
+ crvToken: string;
216
+ cvxToken: string;
217
+ };
213
218
  curve: {
214
219
  addressProvider: string;
215
220
  minter: string;
@@ -225,6 +230,10 @@ export interface DeploymentConfig {
225
230
  comptroller: string;
226
231
  ctokens: Record<string, string>;
227
232
  };
233
+ fuse: {
234
+ fetherTokens: Record<string, string>;
235
+ ftokens: Record<string, string>;
236
+ };
228
237
  idle: {
229
238
  bestYieldIdleDai: string;
230
239
  bestYieldIdleUsdc: string;
@@ -277,9 +286,4 @@ export interface DeploymentConfig {
277
286
  exchange: string;
278
287
  allowedMakers: string[];
279
288
  };
280
- policies: {
281
- guaranteedRedemption: {
282
- redemptionWindowBuffer: number;
283
- };
284
- };
285
289
  }
@@ -1,9 +1,4 @@
1
- import type {
2
- AssetFinalityResolver,
3
- Dispatcher,
4
- GasRelayPaymasterFactory,
5
- ValueInterpreter,
6
- } from '@enzymefinance/protocol';
1
+ import type { Dispatcher, GasRelayPaymasterFactory, ValueInterpreter } from '@enzymefinance/protocol';
7
2
  import {
8
3
  ComptrollerLib,
9
4
  ExternalPositionManager,
@@ -20,7 +15,6 @@ import type { Signer } from 'ethers';
20
15
  // unless overrides are passed-in
21
16
  export async function createFundDeployer({
22
17
  deployer,
23
- assetFinalityResolver,
24
18
  externalPositionManager,
25
19
  dispatcher,
26
20
  gasRelayPaymasterFactory,
@@ -30,7 +24,6 @@ export async function createFundDeployer({
30
24
  setReleaseLive = true,
31
25
  }: {
32
26
  deployer: Signer;
33
- assetFinalityResolver: AssetFinalityResolver;
34
27
  externalPositionManager: ExternalPositionManager;
35
28
  dispatcher: Dispatcher;
36
29
  feeManager: FeeManager;
@@ -76,7 +69,6 @@ export async function createFundDeployer({
76
69
  nextFeeManager,
77
70
  nextIntegrationManager,
78
71
  nextPolicyManager,
79
- assetFinalityResolver,
80
72
  gasRelayPaymasterFactory,
81
73
  mlnToken,
82
74
  wethToken,
@@ -44,19 +44,24 @@ export async function createExternalPosition({
44
44
  externalPositionManager,
45
45
  externalPositionTypeId,
46
46
  initializationData = '0x',
47
+ callOnExternalPositionData = '0x',
47
48
  }: {
48
49
  signer: SignerWithAddress;
49
50
  comptrollerProxy: ComptrollerLib;
50
51
  externalPositionManager: ExternalPositionManager;
51
52
  externalPositionTypeId: BigNumberish;
52
53
  initializationData?: BytesLike;
54
+ callOnExternalPositionData?: BytesLike;
53
55
  }) {
54
56
  const receipt = await comptrollerProxy
55
57
  .connect(signer)
56
58
  .callOnExtension(
57
59
  externalPositionManager,
58
60
  ExternalPositionManagerActionId.CreateExternalPosition,
59
- encodeArgs(['uint256', 'bytes'], [externalPositionTypeId, initializationData]),
61
+ encodeArgs(
62
+ ['uint256', 'bytes', 'bytes'],
63
+ [externalPositionTypeId, initializationData, callOnExternalPositionData],
64
+ ),
60
65
  );
61
66
 
62
67
  const event = extractEvent(receipt, externalPositionManager.abi.getEvent('ExternalPositionDeployedForFund'));
@@ -2,8 +2,6 @@ import type { AddressLike } from '@enzymefinance/ethers';
2
2
  import type { SignerWithAddress } from '@enzymefinance/hardhat';
3
3
  import type { ComptrollerLib, ExternalPositionFactory, ExternalPositionManager } from '@enzymefinance/protocol';
4
4
  import {
5
- encodeArgs,
6
- ExternalPositionManagerActionId,
7
5
  mockGenericExternalPositionActionArgs,
8
6
  MockGenericExternalPositionActionId,
9
7
  MockGenericExternalPositionLib,
@@ -12,7 +10,7 @@ import {
12
10
  } from '@enzymefinance/protocol';
13
11
  import type { BigNumberish } from 'ethers';
14
12
 
15
- import { callOnExternalPosition } from './actions';
13
+ import { callOnExternalPosition, createExternalPosition } from './actions';
16
14
 
17
15
  export async function createMockExternalPosition({
18
16
  comptrollerProxy,
@@ -54,13 +52,12 @@ export async function createMockExternalPosition({
54
52
  [mockExternalPositionParser],
55
53
  );
56
54
 
57
- const receipt = await comptrollerProxy
58
- .connect(fundOwner)
59
- .callOnExtension(
60
- externalPositionManager,
61
- ExternalPositionManagerActionId.CreateExternalPosition,
62
- encodeArgs(['uint256', 'bytes'], [typeId, '0x']),
63
- );
55
+ const receipt = await createExternalPosition({
56
+ comptrollerProxy,
57
+ externalPositionManager,
58
+ externalPositionTypeId: typeId,
59
+ signer: fundOwner,
60
+ });
64
61
 
65
62
  const externalPositionProxy = (await vaultProxy.getActiveExternalPositions())[0];
66
63
 
@@ -4,20 +4,19 @@ import type { SignerWithAddress } from '@enzymefinance/hardhat';
4
4
  import type { ComptrollerLib, ExternalPositionManager } from '@enzymefinance/protocol';
5
5
  import {
6
6
  callOnExternalPositionArgs,
7
- encodeArgs,
8
7
  ExternalPositionManagerActionId,
9
8
  ExternalPositionType,
10
9
  UniswapV3LiquidityPositionActionId,
11
10
  uniswapV3LiquidityPositionAddLiquidityArgs,
12
11
  uniswapV3LiquidityPositionCollectArgs,
13
- uniswapV3LiquidityPositionInitArgs,
14
12
  UniswapV3LiquidityPositionLib,
15
13
  uniswapV3LiquidityPositionMintArgs,
16
14
  uniswapV3LiquidityPositionPurgeArgs,
17
15
  uniswapV3LiquidityPositionRemoveLiquidityArgs,
18
- VaultLib,
19
16
  } from '@enzymefinance/protocol';
20
- import type { BigNumber, BigNumberish } from 'ethers';
17
+ import type { BigNumber, BigNumberish, BytesLike } from 'ethers';
18
+
19
+ import { createExternalPosition } from './actions';
21
20
 
22
21
  export enum UniswapV3FeeAmount {
23
22
  LOW = 500,
@@ -58,33 +57,22 @@ export async function createUniswapV3LiquidityPosition({
58
57
  signer,
59
58
  comptrollerProxy,
60
59
  externalPositionManager,
61
- token0,
62
- token1,
60
+ callOnExternalPositionData = '0x',
63
61
  }: {
64
62
  signer: SignerWithAddress;
65
63
  comptrollerProxy: ComptrollerLib;
66
64
  externalPositionManager: ExternalPositionManager;
67
- token0: AddressLike;
68
- token1: AddressLike;
65
+ callOnExternalPositionData?: BytesLike;
69
66
  }) {
70
- const initArgs = uniswapV3LiquidityPositionInitArgs({
71
- token0,
72
- token1,
67
+ const { externalPositionProxy: externalPositionProxyContract, receipt } = await createExternalPosition({
68
+ callOnExternalPositionData,
69
+ comptrollerProxy,
70
+ externalPositionManager,
71
+ externalPositionTypeId: ExternalPositionType.UniswapV3LiquidityPosition,
72
+ signer,
73
73
  });
74
74
 
75
- const receipt = await comptrollerProxy
76
- .connect(signer)
77
- .callOnExtension(
78
- externalPositionManager,
79
- ExternalPositionManagerActionId.CreateExternalPosition,
80
- encodeArgs(['uint256', 'bytes'], [ExternalPositionType.UniswapV3LiquidityPosition, initArgs]),
81
- );
82
-
83
- const vaultProxy = new VaultLib(await comptrollerProxy.getVaultProxy(), signer);
84
- const externalPositions = await vaultProxy.getActiveExternalPositions.call();
85
- const externalPositionProxyAddress = externalPositions[externalPositions.length - 1];
86
-
87
- return { externalPositionProxyAddress, receipt };
75
+ return { externalPositionProxyAddress: externalPositionProxyContract.address, receipt };
88
76
  }
89
77
 
90
78
  export async function uniswapV3LiquidityPositionAddLiquidity({
@@ -160,6 +148,8 @@ export async function uniswapV3LiquidityPositionMint({
160
148
  comptrollerProxy,
161
149
  externalPositionManager,
162
150
  externalPositionProxy,
151
+ token0,
152
+ token1,
163
153
  fee,
164
154
  tickLower,
165
155
  tickUpper,
@@ -172,6 +162,8 @@ export async function uniswapV3LiquidityPositionMint({
172
162
  comptrollerProxy: ComptrollerLib;
173
163
  externalPositionManager: ExternalPositionManager;
174
164
  externalPositionProxy: AddressLike;
165
+ token0: AddressLike;
166
+ token1: AddressLike;
175
167
  fee: BigNumberish;
176
168
  tickLower: BigNumberish;
177
169
  tickUpper: BigNumberish;
@@ -188,6 +180,8 @@ export async function uniswapV3LiquidityPositionMint({
188
180
  fee,
189
181
  tickLower,
190
182
  tickUpper,
183
+ token0,
184
+ token1,
191
185
  });
192
186
 
193
187
  const callArgs = callOnExternalPositionArgs({
@@ -1,16 +1,28 @@
1
1
  import type { AddressLike, Contract, Send } from '@enzymefinance/ethers';
2
2
  import { contract, resolveAddress } from '@enzymefinance/ethers';
3
3
  import type { SignerWithAddress } from '@enzymefinance/hardhat';
4
- import type { CompoundAdapter, ComptrollerLib, IntegrationManager, VaultLib } from '@enzymefinance/protocol';
4
+ import type {
5
+ CompoundAdapter,
6
+ CompoundPriceFeed,
7
+ ComptrollerLib,
8
+ ICERC20,
9
+ IntegrationManager,
10
+ VaultLib,
11
+ } from '@enzymefinance/protocol';
5
12
  import {
6
13
  callOnIntegrationArgs,
14
+ claimRewardsSelector,
7
15
  compoundArgs,
16
+ compoundClaimRewardsArgs,
8
17
  IntegrationManagerActionId,
9
18
  lendSelector,
10
19
  redeemSelector,
20
+ StandardToken,
11
21
  } from '@enzymefinance/protocol';
12
22
  import type { BigNumberish } from 'ethers';
13
- import { utils } from 'ethers';
23
+ import { BigNumber, utils } from 'ethers';
24
+
25
+ import { getAssetBalances } from '../../common';
14
26
 
15
27
  export interface ICompoundComptroller extends Contract<ICompoundComptroller> {
16
28
  claimComp: Send<(_account: AddressLike) => void>;
@@ -20,6 +32,155 @@ export const ICompoundComptroller = contract<ICompoundComptroller>()`
20
32
  function claimComp(address)
21
33
  `;
22
34
 
35
+ export async function assertCompoundLend({
36
+ tokenWhale,
37
+ comptrollerProxy,
38
+ vaultProxy,
39
+ integrationManager,
40
+ fundOwner,
41
+ compoundAdapter,
42
+ tokenAmount = utils.parseEther('1'),
43
+ cToken,
44
+ compoundPriceFeed,
45
+ }: {
46
+ tokenWhale: SignerWithAddress;
47
+ comptrollerProxy: ComptrollerLib;
48
+ vaultProxy: VaultLib;
49
+ integrationManager: IntegrationManager;
50
+ fundOwner: SignerWithAddress;
51
+ compoundAdapter: CompoundAdapter;
52
+ tokenAmount?: BigNumber;
53
+ cToken: ICERC20;
54
+ compoundPriceFeed: CompoundPriceFeed;
55
+ }) {
56
+ const token = new StandardToken(await compoundPriceFeed.getTokenFromCToken.args(cToken).call(), tokenWhale);
57
+ await token.connect(tokenWhale).transfer(vaultProxy, tokenAmount);
58
+ const rateBefore = await cToken.exchangeRateStored.call();
59
+
60
+ // Exchange rate stored can have a small deviation from exchangeRateStored
61
+ const minIncomingCTokenAmount = tokenAmount
62
+ .mul(utils.parseEther('1'))
63
+ .div(rateBefore)
64
+ .mul(BigNumber.from('999'))
65
+ .div(BigNumber.from('1000'));
66
+
67
+ const [preTxIncomingAssetBalance, preTxOutgoingAssetBalance] = await getAssetBalances({
68
+ account: vaultProxy,
69
+ assets: [cToken as any, token],
70
+ });
71
+
72
+ const lendReceipt = await compoundLend({
73
+ cToken,
74
+ cTokenAmount: minIncomingCTokenAmount,
75
+ compoundAdapter,
76
+ comptrollerProxy,
77
+ fundOwner,
78
+ integrationManager,
79
+ tokenAmount,
80
+ });
81
+
82
+ // Get exchange rate after tx (the rate is updated right after)
83
+ const rate = await cToken.exchangeRateStored();
84
+ const [postTxIncomingAssetBalance, postTxOutgoingAssetBalance] = await getAssetBalances({
85
+ account: vaultProxy,
86
+ assets: [cToken as any, token],
87
+ });
88
+
89
+ const expectedCTokenAmount = tokenAmount.mul(utils.parseEther('1')).div(rate);
90
+ expect(postTxIncomingAssetBalance).toEqBigNumber(preTxIncomingAssetBalance.add(expectedCTokenAmount));
91
+ expect(postTxOutgoingAssetBalance).toEqBigNumber(preTxOutgoingAssetBalance.sub(tokenAmount));
92
+
93
+ return lendReceipt;
94
+ }
95
+
96
+ export async function assertCompoundRedeem({
97
+ comptrollerProxy,
98
+ vaultProxy,
99
+ integrationManager,
100
+ fundOwner,
101
+ compoundAdapter,
102
+ cToken,
103
+ compoundPriceFeed,
104
+ }: {
105
+ comptrollerProxy: ComptrollerLib;
106
+ vaultProxy: VaultLib;
107
+ integrationManager: IntegrationManager;
108
+ fundOwner: SignerWithAddress;
109
+ compoundAdapter: CompoundAdapter;
110
+ cToken: ICERC20;
111
+ compoundPriceFeed: CompoundPriceFeed;
112
+ }) {
113
+ const cTokenAmount = utils.parseUnits('1', await cToken.decimals());
114
+ await cToken.transfer(vaultProxy, cTokenAmount);
115
+
116
+ const token = new StandardToken(await compoundPriceFeed.getTokenFromCToken.args(cToken).call(), provider);
117
+ const [preTxIncomingAssetBalance, preTxOutgoingAssetBalance] = await getAssetBalances({
118
+ account: vaultProxy,
119
+ assets: [token, cToken as any],
120
+ });
121
+
122
+ const rateBefore = await cToken.exchangeRateStored();
123
+ const minIncomingTokenAmount = cTokenAmount.mul(rateBefore).div(utils.parseEther('1'));
124
+
125
+ const redeemReceipt = await compoundRedeem({
126
+ cToken,
127
+ cTokenAmount,
128
+ compoundAdapter,
129
+ comptrollerProxy,
130
+ fundOwner,
131
+ integrationManager,
132
+ tokenAmount: minIncomingTokenAmount,
133
+ vaultProxy,
134
+ });
135
+
136
+ const [postTxIncomingAssetBalance, postTxOutgoingAssetBalance] = await getAssetBalances({
137
+ account: vaultProxy,
138
+ assets: [token, cToken as any],
139
+ });
140
+
141
+ // Get exchange rate after tx (the rate is updated right after)
142
+ const rate = await cToken.exchangeRateStored();
143
+ const expectedTokenAmount = cTokenAmount.mul(rate).div(utils.parseEther('1'));
144
+
145
+ expect(postTxIncomingAssetBalance).toEqBigNumber(preTxIncomingAssetBalance.add(expectedTokenAmount));
146
+ expect(postTxOutgoingAssetBalance).toEqBigNumber(preTxOutgoingAssetBalance.sub(cTokenAmount));
147
+
148
+ return redeemReceipt;
149
+ }
150
+
151
+ export async function compoundClaim({
152
+ comptrollerProxy,
153
+ integrationManager,
154
+ fundOwner,
155
+ compoundAdapter,
156
+ compoundComptroller,
157
+ cTokens,
158
+ }: {
159
+ comptrollerProxy: ComptrollerLib;
160
+ integrationManager: IntegrationManager;
161
+ fundOwner: SignerWithAddress;
162
+ compoundAdapter: CompoundAdapter;
163
+ compoundComptroller: AddressLike;
164
+ cTokens: AddressLike[];
165
+ }) {
166
+ const claimArgs = compoundClaimRewardsArgs({
167
+ cTokens,
168
+ compoundComptroller,
169
+ });
170
+
171
+ const callArgs = callOnIntegrationArgs({
172
+ adapter: compoundAdapter,
173
+ encodedCallArgs: claimArgs,
174
+ selector: claimRewardsSelector,
175
+ });
176
+
177
+ const claimRewardsTx = comptrollerProxy
178
+ .connect(fundOwner)
179
+ .callOnExtension(integrationManager, IntegrationManagerActionId.CallOnIntegration, callArgs);
180
+
181
+ return claimRewardsTx;
182
+ }
183
+
23
184
  export async function compoundLend({
24
185
  comptrollerProxy,
25
186
  integrationManager,