Skip to content

Commit

Permalink
feat: gho (#445)
Browse files Browse the repository at this point in the history
* feat: add in GhoDiscountRateStrategyService (#443)

* feat: add in typechain and setup base GhoDiscountRateService

* chore: add in type definition files

* chore: add in basic calculateDiscountRate function and unit test

* fix: skip unit test for now

* fix: allow to commit to repo and bypass jest coverage limit

* chore: write utility for calculating discount rate

* fix: write unit tests for all use cases for discount rates

* fix: write unit test for barrel file

* chore: jest config and export gho service

* fix: use zero values and mock return calls

* fix: test coverage and mocks

* chore: remove unnecessary coverage skips

* feat: add in GhoTokenService for totalSupply & facilitator info (#444)

* feat: add in GhoTokenService and getFacilitatorBucket

* fix: typo

* feat: add in more utils for GhoTokenService

* feat: add in GhoVariableDebtTokenService & getters for debt strategy constants (#446)

* chore: move existing test files to __tests__ dir

* chore: add in typechain types

* feat: add in GhoVariableDebtTokenService with methods and tests

* feat: add in getters and tests for GhoDiscountRateStrategy constants

* chore: update discount rate strategy source (#447)

* feat: add getDiscountRateStrategy to ghoVariableDebtTokenService

* feat: use ghoVariableDebtToken as source of discount strategy address

* feat: add test for discountRateStrategy update

* feat: add function for getting reserve data from lending pool (#451)

* feat: add function for getting reserve data from lending pool

* test: getReserveData

* feat: add in GhoDiscountRateStrategyService (#443)

* feat: add in typechain and setup base GhoDiscountRateService

* chore: add in type definition files

* chore: add in basic calculateDiscountRate function and unit test

* fix: skip unit test for now

* fix: allow to commit to repo and bypass jest coverage limit

* chore: write utility for calculating discount rate

* fix: write unit tests for all use cases for discount rates

* fix: write unit test for barrel file

* chore: jest config and export gho service

* fix: use zero values and mock return calls

* fix: test coverage and mocks

* chore: remove unnecessary coverage skips

* feat: add in GhoTokenService for totalSupply & facilitator info (#444)

* feat: add in GhoTokenService and getFacilitatorBucket

* fix: typo

* feat: add in more utils for GhoTokenService

* feat: add in GhoVariableDebtTokenService & getters for debt strategy constants (#446)

* chore: move existing test files to __tests__ dir

* chore: add in typechain types

* feat: add in GhoVariableDebtTokenService with methods and tests

* feat: add in getters and tests for GhoDiscountRateStrategy constants

* chore: update discount rate strategy source (#447)

* feat: add getDiscountRateStrategy to ghoVariableDebtTokenService

* feat: use ghoVariableDebtToken as source of discount strategy address

* feat: add test for discountRateStrategy update

* feat: add function for getting reserve data from lending pool (#451)

* feat: add function for getting reserve data from lending pool

* test: getReserveData

* chore: sync gho base with upstream (#472)

* feat: add default gas estimation for permit actions (#461)

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.10.0
 - @aave/math-utils@1.10.0

Co-authored-by: DeFi Spartan <andrew@aave.com>
Co-authored-by: GitHub Actions Build <developers@aave.com>

* chore/export compounding rate helper (#462)

* chore: export compounded rate helper

* chore: use compounded rate helper in formatReserves

* fix: add in plumbing for exporting calc compound rate

* chore: remove duplicated function and update refs

Co-authored-by: Drew Cook <drew@dco.dev>

* fix: build error

* feat: gho sdk (#466)

* feat: add in GhoDiscountRateStrategyService (#443)

* feat: add in typechain and setup base GhoDiscountRateService

* chore: add in type definition files

* chore: add in basic calculateDiscountRate function and unit test

* fix: skip unit test for now

* fix: allow to commit to repo and bypass jest coverage limit

* chore: write utility for calculating discount rate

* fix: write unit tests for all use cases for discount rates

* fix: write unit test for barrel file

* chore: jest config and export gho service

* fix: use zero values and mock return calls

* fix: test coverage and mocks

* chore: remove unnecessary coverage skips

* feat: add in GhoTokenService for totalSupply & facilitator info (#444)

* feat: add in GhoTokenService and getFacilitatorBucket

* fix: typo

* feat: add in more utils for GhoTokenService

* feat: add in GhoVariableDebtTokenService & getters for debt strategy constants (#446)

* chore: move existing test files to __tests__ dir

* chore: add in typechain types

* feat: add in GhoVariableDebtTokenService with methods and tests

* feat: add in getters and tests for GhoDiscountRateStrategy constants

* chore: update discount rate strategy source (#447)

* feat: add getDiscountRateStrategy to ghoVariableDebtTokenService

* feat: use ghoVariableDebtToken as source of discount strategy address

* feat: add test for discountRateStrategy update

* feat: add function for getting reserve data from lending pool (#451)

* feat: add function for getting reserve data from lending pool

* test: getReserveData

* chore: export compounded rate helper

* chore: use compounded rate helper in formatReserves

* fix: add in plumbing for exporting calc compound rate

* chore: remove duplicated function and update refs

* feat: add fetchGhoData wrapper service

* feat: add formatGhoData utility function

* chore: re-add exports

* fix: discountLockPeriod decimal formatting

* feat: export gho formatter

* feat: facilitator percentage minted

* chore: swap string to number in gho formatter

* chore: use object destructuring for facilitatorInfo

* chore: rename fields and add userGhoBorrowBalance

* fix: facilitatorAddress parameter

* fix: facilitator info typo

* chore: remove userGhoBorrowBalance from service and formatter

* chore: split user and reserve services and add fields for user borrow balance

* chore: split user and reserve formatters

* fix: use correct service for scaledBalance and previousIndex

* chore: export discounted gho interest to factor into total borrows

* feat: add Ui helper contract typechain

* feat: use helper contract in GhoService

* chore: purge unused gho services

* feat: helper function to account for gho discount in user summary

* feat: update discount summary helper and add tests

* chore: remove old comment

Co-authored-by: Drew Cook <drew@dco.dev>
Co-authored-by: Mark Grothe <grothem@gmail.com>

* chore: cleanup

* chore: update staking permit (#485)

* feat: fetch nonce inside staking signature generation

* fix: nonce test

* feat: add deadline parameter

* fix: blank nonce test coverage

* feat: add staking default gas estimation

* chore: revert dynamic deadline which contract does not support

* feat: gho testnet (#506)

* feat: add default gas estimation for borrow and vote (#492)

* feat: add default gas estimation for borrow

* chore: add default estimation for vote

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.13.0
 - @aave/math-utils@1.13.0

* fix: apply default gas limit estimations (#499)

* fix: apply default gas limit estimations

* chore: update vote estimate

* fix: update remaining actions

* chore: update gas limit tests for v3 pool

* chore: update gas limits tests for v2 pool

* chore: update gas limits tests for voting

* chore: revert v3 pool rollup changes

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.13.1
 - @aave/math-utils@1.13.1

* chore: change migration on v3 from flash loan to use credit delegation (#493)

* feat: v3 migration services added

* feat: erc20-2612 export and test for v3 migration added

* feat: migration service types

* feat: migrate no borrow without permits

* feat: migrate v3 with borrow continue

* fix: pass permits to flashloan v3

* fix: added test for migrateV3 and fixed some types

* fix: remove approval tx if permits passed

* fix: approve txs in migrate with permits

* fix: added 100% coverage

* fix: fixed ingores

* feat: add migrate method

* fix: add tests

* fix: added credit delegation approval

* fix: separate v3 variable debt approval for migraiton v3

* fix: updated tests

* feat: add get migration supply method added

* fix: get migration supply test added

* fix: get migration supply test

Co-authored-by: sendra <polsendra@gmail.com>

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.13.2
 - @aave/math-utils@1.13.2

* fix: typechain structure (#501)

* fix: typechain structure

* chore: disable typescript linting for migration service

* chore: add type to permit mapping

* fix: migration typechain import and unused config

* fix: factory typechain import

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.13.3
 - @aave/math-utils@1.13.3

* fix: check for liq threshold in place of ltv for user collateral check (#505)

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.13.4
 - @aave/math-utils@1.13.4

* fix: Fix typos (#486)

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.13.5
 - @aave/math-utils@1.13.5

* feat: decentralize the readme header image

* chore: remove legacy files

* feat: update uighodataprovider typechain and references (#507)

* feat: custom version for gho beta [skip ci]

* chore(release): [skip ci]

 - @aave/contract-helpers@1.0.0-gho-beta.0
 - @aave/math-utils@1.0.0-gho-beta.0

* chore: remove readme line

* chore: revert attempt for custom custom version

---------

Co-authored-by: GitHub Actions Build <developers@aave.com>
Co-authored-by: Dmitry Petrov <satanworker@gmail.com>
Co-authored-by: sendra <polsendra@gmail.com>
Co-authored-by: Dimitris Apostolou <dimitris.apostolou@icloud.com>

* feat: gho uighodataprovider update (#526)

* feat: update uighodataprovider typechain

* feat: update usage of discountLockPeriod in gho service

* feat: gho base update (#536)

* feat: add Scroll Alpha chainId (#528)

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.15.0
 - @aave/math-utils@1.15.0

* feat: update borrow methods SDK (#527)

* feat: updated borrow methods + test for L2Pool

* feat: updated borrow methods + test for WETHGateway

* feat: update  borrow methods on V3 pool bundle + tests

* feat: update borrow methods on V2 bundle + tests

* chore: add wethgateway test coverage

* feat: add generateApproveDelegationTxData helper function + tests

* feat: numeric credit delegation approved amount instead of boolean

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.16.0
 - @aave/math-utils@1.16.0

* fix: apply default gas limits (#533)

* chore: add approval and approveDelegation gasLimitRecommendations

* fix: apply default gas limit estimations to all tx data generation methods

* feat: fixed available debt in isolated reserve in case that debt > ma… (#532)

* feat: fixed available debt in isolated reserve in case that debt > max debt

* feat: add isolation mode ceiling exceeded test

* chore: remove comment

---------

Co-authored-by: aschmidt20 <andrew@aave.com>

* chore(release): publish [ci skip]

 - @aave/contract-helpers@1.17.0
 - @aave/math-utils@1.17.0

---------

Co-authored-by: Daniel Helm <dan.helm@gmail.com>
Co-authored-by: GitHub Actions Build <developers@aave.com>
Co-authored-by: JoaquinBattilana <battilanajn@gmail.com>

* fix: check that user has required amount of token for discount (#539)

* fix: check that user has required amount of token for discount

* test: unit itest for not having enough discount token for discount

* fix: bad merge

* fix: typings

* chore: cleanup unnecessary changes

* chore: more file cleanup

* chore: update stakeWithPermit to directly call function on  StkAave token

* chore: update signStaking and stakeWithPermit tests

* chore: add ProtocolAction to stakeWithPermit

* fix: signStakingApproval spender

---------

Co-authored-by: Drew Cook <drew@dco.dev>
Co-authored-by: Andrew Schmidt <andrew@aave.com>
Co-authored-by: GitHub Actions Build <developers@aave.com>
Co-authored-by: Dmitry Petrov <satanworker@gmail.com>
Co-authored-by: sendra <polsendra@gmail.com>
Co-authored-by: Dimitris Apostolou <dimitris.apostolou@icloud.com>
Co-authored-by: Daniel Helm <dan.helm@gmail.com>
Co-authored-by: JoaquinBattilana <battilanajn@gmail.com>
  • Loading branch information
9 people authored Jul 14, 2023
1 parent 23a7ead commit 102091c
Show file tree
Hide file tree
Showing 29 changed files with 1,247 additions and 313 deletions.
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
preset: 'ts-jest',
collectCoverageFrom: ['packages/*/src/**/*.ts'],
collectCoverageFrom: ['packages/*/src/**(!typechain)/*.ts'],
coverageDirectory: 'coverage',
coverageReporters: ['lcov', 'text'],
coverageThreshold: {
Expand Down
2 changes: 1 addition & 1 deletion packages/contract-helpers/src/commons/BaseService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ describe('BaseService', () => {
expect(gas?.gasLimit).toEqual('1');
expect(gas?.gasPrice).toEqual('2');
});
xit('Expects null when no gas limit', async () => {
it.skip('Expects null when no gas limit', async () => {
const txCallback = async () => ({});
const txs = [
{
Expand Down
1 change: 1 addition & 0 deletions packages/contract-helpers/src/commons/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export enum ProtocolAction {
migrateV3 = 'migrateV3',
supplyWithPermit = 'supplyWithPermit',
repayWithPermit = 'repayWithPermit',
stakeWithPermit = 'stakeWithPermit',
vote = 'vote',
approval = 'approval',
creditDelegationApproval = 'creditDelegationApproval',
Expand Down
8 changes: 8 additions & 0 deletions packages/contract-helpers/src/commons/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ export const gasLimitRecommendations: GasRecommendationType = {
limit: '350000',
recommended: '350000',
},
[ProtocolAction.stake]: {
limit: '350000',
recommended: '350000',
},
[ProtocolAction.stakeWithPermit]: {
limit: '400000',
recommended: '400000',
},
[ProtocolAction.vote]: {
limit: '125000',
recommended: '125000',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,7 @@ export function SignStakingValidator(
descriptor.value = function () {
if (
// @ts-expect-error todo: check why this ignore is needed
!utils.isAddress(this.stakingContractAddress) ||
// @ts-expect-error todo: check why this ignore is needed
!utils.isAddress(this.stakingHelperContractAddress)
!utils.isAddress(this.stakingContractAddress)
) {
console.error(`[StakingValidator] You need to pass valid addresses`);
return [];
Expand Down
88 changes: 88 additions & 0 deletions packages/contract-helpers/src/gho/GhoService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { providers } from 'ethers';
import { isAddress } from 'ethers/lib/utils';
import { tEthereumAddress } from '../commons/types';
import { IUiGhoDataProvider } from './typechain/IUiGhoDataProvider';
import { IUiGhoDataProvider__factory } from './typechain/IUiGhoDataProvider__factory';
import { GhoReserveData, GhoUserData } from './types';

export interface IGhoService {
getGhoReserveData: () => Promise<GhoReserveData>;
getGhoUserData: (
userAddress: tEthereumAddress,
ghoDiscountTokenAddress?: tEthereumAddress,
) => Promise<GhoUserData>;
}

// Wrapper service for fetching gho reserve, discount, facilitator, and user data for UI purposes
export class GhoService implements IGhoService {
readonly ghoDataProviderService: IUiGhoDataProvider;
constructor({
provider,
uiGhoDataProviderAddress,
}: {
provider: providers.Provider;
uiGhoDataProviderAddress: tEthereumAddress;
}) {
if (!isAddress(uiGhoDataProviderAddress)) {
throw new Error('UiGhoDataProvider contract address is not valid');
}

this.ghoDataProviderService = IUiGhoDataProvider__factory.connect(
uiGhoDataProviderAddress,
provider,
);
}

/**
* Fetches Gho reserve, discount, facilitator data
* @returns - instance of GhoReserveData with reserve, discount, facilitator data
*/
public async getGhoReserveData(): Promise<GhoReserveData> {
const ghoReserveData =
await this.ghoDataProviderService.getGhoReserveData();

return {
ghoBaseVariableBorrowRate:
ghoReserveData.ghoBaseVariableBorrowRate.toString(),
ghoDiscountedPerToken: ghoReserveData.ghoDiscountedPerToken.toString(),
ghoDiscountRate: ghoReserveData.ghoDiscountRate.toString(),
aaveFacilitatorBucketMaxCapacity:
ghoReserveData.aaveFacilitatorBucketMaxCapacity.toString(),
aaveFacilitatorBucketLevel:
ghoReserveData.aaveFacilitatorBucketLevel.toString(),
ghoMinDebtTokenBalanceForDiscount:
ghoReserveData.ghoMinDebtTokenBalanceForDiscount.toString(),
ghoMinDiscountTokenBalanceForDiscount:
ghoReserveData.ghoMinDiscountTokenBalanceForDiscount.toString(),
ghoCurrentBorrowIndex: ghoReserveData.ghoCurrentBorrowIndex.toString(),
ghoReserveLastUpdateTimestamp:
ghoReserveData.ghoReserveLastUpdateTimestamp.toString(),
};
}

/**
* Fetches Gho user data for UI display
* @param userAddress - Address of user to fetch ghoDiscountRate, ghoDiscountTokenBalance, and gho balance indeces
* @returns - instance of GhoUserData
*/
public async getGhoUserData(
userAddress: tEthereumAddress,
): Promise<GhoUserData> {
if (!isAddress(userAddress)) {
throw new Error('user address is not valid');
}

const ghoUserData = await this.ghoDataProviderService.getGhoUserData(
userAddress,
);

return {
userGhoDiscountPercent: ghoUserData.userGhoDiscountPercent.toString(),
userDiscountTokenBalance: ghoUserData.userDiscountTokenBalance.toString(),
userGhoScaledBorrowBalance:
ghoUserData.userGhoScaledBorrowBalance.toString(),
userPreviousGhoBorrowIndex:
ghoUserData.userPreviousGhoBorrowIndex.toString(),
};
}
}
107 changes: 107 additions & 0 deletions packages/contract-helpers/src/gho/__tests__/GhoService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { providers, constants } from 'ethers';
import { GhoService, IGhoService } from '../GhoService';
import { IUiGhoDataProvider } from '../typechain/IUiGhoDataProvider';
import { IUiGhoDataProvider__factory } from '../typechain/IUiGhoDataProvider__factory';
import { GhoReserveData, GhoUserData } from '../types';

const ghoReserveDataMock: GhoReserveData = {
ghoBaseVariableBorrowRate: '0',
ghoDiscountedPerToken: '0',
ghoDiscountRate: '0',
aaveFacilitatorBucketLevel: '0',
aaveFacilitatorBucketMaxCapacity: '0',
ghoMinDebtTokenBalanceForDiscount: '0',
ghoMinDiscountTokenBalanceForDiscount: '0',
ghoCurrentBorrowIndex: '0',
ghoReserveLastUpdateTimestamp: '0',
};

const ghoUserDataMock: GhoUserData = {
userGhoDiscountPercent: '0',
userDiscountTokenBalance: '0',
userGhoScaledBorrowBalance: '0',
userPreviousGhoBorrowIndex: '0',
};

describe('GhoService', () => {
const uiGhoDataProviderAddress = constants.AddressZero;
const provider: providers.Provider = new providers.JsonRpcProvider();

describe('Init', () => {
it('Expects to create the instance', () => {
const instance: IGhoService = new GhoService({
provider,
uiGhoDataProviderAddress,
});
expect(instance instanceof GhoService);
});

it('Expects to throw an error with an invalid parameter address', () => {
expect(
() =>
new GhoService({
provider,
uiGhoDataProviderAddress: 'hi',
}),
).toThrowError('UiGhoDataProvider contract address is not valid');
});

describe('getGhoReserveData full mock', () => {
it('Expects to get GhoReserveData response type', async () => {
// Mock it
const spy = jest
.spyOn(IUiGhoDataProvider__factory, 'connect')
.mockReturnValue({
getGhoReserveData: async () => Promise.resolve(ghoReserveDataMock),
} as unknown as IUiGhoDataProvider);

// Call it
const instance: IGhoService = new GhoService({
provider,
uiGhoDataProviderAddress,
});
const rawReserveData = await instance.getGhoReserveData();

// Assert it
expect(spy).toHaveBeenCalled();
expect(spy).toBeCalledTimes(1);
expect(rawReserveData).toEqual(ghoReserveDataMock);
});
});

describe('getGhoUserData full mock', () => {
it('Expects to get GhoUserData response type', async () => {
// Mock it
const spy = jest
.spyOn(IUiGhoDataProvider__factory, 'connect')
.mockReturnValue({
getGhoUserData: async (_userAddress: string) =>
Promise.resolve(ghoUserDataMock),
} as unknown as IUiGhoDataProvider);

// Call it
const instance: IGhoService = new GhoService({
provider,
uiGhoDataProviderAddress,
});
const mockAddress = constants.AddressZero;
const rawUserData = await instance.getGhoUserData(mockAddress);

// Assert it
expect(spy).toHaveBeenCalled();
expect(spy).toBeCalledTimes(2); // reserve + user
expect(rawUserData).toEqual(ghoUserDataMock);
});

it('Expects to throw an error with an invalid user address', async () => {
const instance: IGhoService = new GhoService({
provider,
uiGhoDataProviderAddress,
});
await expect(instance.getGhoUserData('hello')).rejects.toThrow(
'user address is not valid',
);
});
});
});
});
7 changes: 7 additions & 0 deletions packages/contract-helpers/src/gho/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { GhoService } from '../index';

describe('gho contract helpers', () => {
it('exports out the GhoService', () => {
expect(GhoService).toBeTruthy();
});
});
3 changes: 3 additions & 0 deletions packages/contract-helpers/src/gho/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { GhoService } from './GhoService';

export { GhoService };
Loading

0 comments on commit 102091c

Please sign in to comment.