Skip to content

Commit

Permalink
Merge branch 'feat/gov-v3' into feat/temp-sdai
Browse files Browse the repository at this point in the history
  • Loading branch information
grothem committed Jan 5, 2024
2 parents c8b03e9 + d4472ca commit f51b244
Show file tree
Hide file tree
Showing 30 changed files with 14,130 additions and 2,512 deletions.
2 changes: 2 additions & 0 deletions packages/contract-helpers/src/commons/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ export enum ProtocolAction {
claimRewardsAndStake = 'claimRewardsAndStake',
setUsageAsCollateral = 'setUsageAsCollateral',
withdrawAndSwitch = 'withdrawAndSwitch',
batchMetaDelegate = 'batchMetaDelegate',
updateRepresentatives = 'updateRepresentatives',
}

export enum GovernanceVote {
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 @@ -138,6 +138,14 @@ export const gasLimitRecommendations: GasRecommendationType = {
limit: '1000000',
recommended: '1000000',
},
[ProtocolAction.batchMetaDelegate]: {
limit: '200000',
recommended: '200000',
},
[ProtocolAction.updateRepresentatives]: {
limit: '60000',
recommended: '60000',
},
};

export const mintAmountsPerToken: Record<string, string> = {
Expand Down
84 changes: 84 additions & 0 deletions packages/contract-helpers/src/governance-v3/aave-token-v3/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { BigNumber, PopulatedTransaction, providers } from 'ethers';
import { AaveTokenV3 } from '../typechain/AaveTokenV3';
import { AaveTokenV3__factory } from '../typechain/factories/AaveTokenV3__factory';

export enum GovernancePowerType {
VOTING,
PROPOSITION,
ALL,
}

interface Eip712Domain {
name: string;
version: string;
chainId: BigNumber;
verifyingContract: string;
}

export class AaveTokenV3Service {
readonly _contract: AaveTokenV3;
readonly _contractInterface = AaveTokenV3__factory.createInterface();

constructor(tokenAddress: string, provider: providers.Provider) {
this._contract = AaveTokenV3__factory.connect(tokenAddress, provider);
}

public async balanceOf(user: string) {
return this._contract.balanceOf(user);
}

public async getPowerAt(
blockNumber: number,
user: string,
delegationType: GovernancePowerType,
) {
return this._contract.functions.getPowerCurrent(user, delegationType, {
blockTag: blockNumber,
});
}

public async getPowers(user: string) {
const powers = await this._contract.getPowersCurrent(user);
return {
votingPower: powers[0],
propositionPower: powers[1],
};
}

public async getDelegateeData(user: string) {
const data = await this._contract.getDelegates(user);
return {
votingDelegatee: data[0],
propositionDelegatee: data[1],
};
}

public getDelegateTxData(
user: string,
delegateTo: string,
type: GovernancePowerType,
): PopulatedTransaction {
const tx: PopulatedTransaction = {};
if (type === GovernancePowerType.ALL) {
tx.data = this._contractInterface.encodeFunctionData('delegate', [
delegateTo,
]);
} else {
tx.data = this._contractInterface.encodeFunctionData('delegateByType', [
delegateTo,
type,
]);
}

return {
...tx,
to: this._contract.address,
from: user,
gasLimit: BigNumber.from('100000'),
};
}

public async getEip712Domain(): Promise<Eip712Domain> {
return this._contract.functions.eip712Domain();
}
}
150 changes: 150 additions & 0 deletions packages/contract-helpers/src/governance-v3/delegate-helper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { BigNumber, PopulatedTransaction, providers } from 'ethers';
import { tEthereumAddress, ENS, ProtocolAction } from '../../commons/types';
import { gasLimitRecommendations } from '../../commons/utils';
import { MetaDelegateHelper } from '../typechain/MetaDelegateHelper';
import { MetaDelegateHelper__factory } from '../typechain/factories/MetaDelegateHelper__factory';
export enum DelegationType {
VOTING,
PROPOSITION,
ALL,
}

export type MetaDelegateParams = {
delegator: string;
delegatee: string;
underlyingAsset: string;
deadline: string;
v: number;
r: string;
s: string;
delegationType: number;
};

export type DelegateMetaSigParams = {
underlyingAsset: tEthereumAddress;
delegatee: tEthereumAddress | ENS;
delegationType: DelegationType;
delegator: tEthereumAddress;
increaseNonce: boolean;
governanceTokenName: string;
nonce: string;
connectedChainId: number;
deadline: string;
};

export class MetaDelegateHelperService {
readonly _contract: MetaDelegateHelper;

readonly _contractInterface = MetaDelegateHelper__factory.createInterface();
private readonly metaDelegateHelperContractAddress: string;

constructor(
metaDelegateHelperContractAddress: string,
provider: providers.Provider,
) {
this.metaDelegateHelperContractAddress = metaDelegateHelperContractAddress; // Assign the contract address

this._contract = MetaDelegateHelper__factory.connect(
metaDelegateHelperContractAddress,
provider,
);
}

public batchMetaDelegate(
user: string,
delegateParams: MetaDelegateParams[],
): PopulatedTransaction {
const tx: PopulatedTransaction = {
data: this._contractInterface.encodeFunctionData('batchMetaDelegate', [
delegateParams,
]),
to: this.metaDelegateHelperContractAddress,
from: user,
gasLimit: BigNumber.from(
gasLimitRecommendations[ProtocolAction.batchMetaDelegate].limit,
),
};
return tx;
}

public async prepareV3DelegateByTypeSignature({
underlyingAsset,
delegatee,
delegationType,
delegator,
increaseNonce,
governanceTokenName,
nonce,
connectedChainId,
deadline,
}: DelegateMetaSigParams): Promise<string> {
const isAllDelegate = delegationType === DelegationType.ALL;

const sigBaseType = [
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' },
];
const sigParametersType = [
{ name: 'delegator', type: 'address' },
{ name: 'delegatee', type: 'address' },
];
const sigDelegationTypeType = [{ name: 'delegationType', type: 'uint8' }];

const typesData = {
delegator,
delegatee,
nonce: BigInt(increaseNonce ? Number(nonce) + 1 : nonce).toString(),
deadline,
};

const eIP712DomainType = {
EIP712Domain: [
{
name: 'name',
type: 'string',
},
{
name: 'version',
type: 'string',
},
{
name: 'chainId',
type: 'uint256',
},
{
name: 'verifyingContract',
type: 'address',
},
],
};

const typeData = {
domain: {
name: governanceTokenName,
version: '2',
chainId: connectedChainId,
verifyingContract: underlyingAsset,
},
types: isAllDelegate
? {
...eIP712DomainType,
Delegate: [...sigParametersType, ...sigBaseType],
}
: {
...eIP712DomainType,

DelegateByType: [
...sigParametersType,
...sigDelegationTypeType,
...sigBaseType,
],
},
primaryType: isAllDelegate ? 'Delegate' : 'DelegateByType',
message: isAllDelegate
? { ...typesData }
: { ...typesData, delegationType },
};

return JSON.stringify(typeData);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { BigNumber, PopulatedTransaction, providers } from 'ethers';
import { ChainId, ProtocolAction } from '../../commons/types';
import { gasLimitRecommendations } from '../../commons/utils';
import {
GovernanceCore,
GovernanceCoreInterface,
} from '../typechain/GovernanceCore';
import { GovernanceCore__factory } from '../typechain/factories/GovernanceCore__factory';

export interface GovernanceCoreServiceInterface {
getProposalCount: () => Promise<number>;
updateRepresentativesForChain: (
user: string,
representatives: Array<{ representative: string; chainId: ChainId }>,
) => PopulatedTransaction;
}
export class GovernanceCoreService implements GovernanceCoreServiceInterface {
private readonly _contractInterface: GovernanceCoreInterface;
private readonly _contractInstance: GovernanceCore;

constructor(
governanceCoreContractAddress: string,
provider: providers.Provider,
) {
this._contractInterface = GovernanceCore__factory.createInterface();
this._contractInstance = GovernanceCore__factory.connect(
governanceCoreContractAddress,
provider,
);
}

public async getProposalCount(): Promise<number> {
const count = await this._contractInstance.getProposalsCount();
return count.toNumber();
}

public updateRepresentativesForChain(
user: string,
representatives: Array<{ representative: string; chainId: ChainId }>,
): PopulatedTransaction {
const actionTx: PopulatedTransaction = {
data: this._contractInterface.encodeFunctionData(
'updateRepresentativesForChain',
[representatives],
),
to: this._contractInstance.address,
from: user,
gasLimit: BigNumber.from(
gasLimitRecommendations[ProtocolAction.updateRepresentatives].limit,
),
};

return actionTx;
}
}
Loading

0 comments on commit f51b244

Please sign in to comment.