diff --git a/packages/contract-helpers/src/commons/types.ts b/packages/contract-helpers/src/commons/types.ts index 0c12eff7..2801c443 100644 --- a/packages/contract-helpers/src/commons/types.ts +++ b/packages/contract-helpers/src/commons/types.ts @@ -143,6 +143,7 @@ export enum ProtocolAction { claimRewardsAndStake = 'claimRewardsAndStake', setUsageAsCollateral = 'setUsageAsCollateral', withdrawAndSwitch = 'withdrawAndSwitch', + batchMetaDelegate = 'batchMetaDelegate', } export enum GovernanceVote { diff --git a/packages/contract-helpers/src/commons/utils.ts b/packages/contract-helpers/src/commons/utils.ts index e711ac9b..6982abb4 100644 --- a/packages/contract-helpers/src/commons/utils.ts +++ b/packages/contract-helpers/src/commons/utils.ts @@ -138,6 +138,10 @@ export const gasLimitRecommendations: GasRecommendationType = { limit: '1000000', recommended: '1000000', }, + [ProtocolAction.batchMetaDelegate]: { + limit: '200000', + recommended: '200000', + }, }; export const mintAmountsPerToken: Record = { diff --git a/packages/contract-helpers/src/governance-v3/delegate-helper/index.ts b/packages/contract-helpers/src/governance-v3/delegate-helper/index.ts index 3a02c3aa..5b230f1e 100644 --- a/packages/contract-helpers/src/governance-v3/delegate-helper/index.ts +++ b/packages/contract-helpers/src/governance-v3/delegate-helper/index.ts @@ -1,8 +1,8 @@ -import { SignatureLike } from '@ethersproject/bytes'; -import { BigNumber, PopulatedTransaction, Signature, utils } from 'ethers'; -import { MetaDelegateHelperInterface } from '../typechain/MetaDelegateHelper'; +import { gasLimitRecommendations } from 'contract-helpers/src/commons/utils'; +import { BigNumber, PopulatedTransaction, providers } from 'ethers'; +import { tEthereumAddress, ENS, ProtocolAction } from '../../commons/types'; +import { MetaDelegateHelper } from '../typechain/MetaDelegateHelper'; import { MetaDelegateHelper__factory } from '../typechain/factories/MetaDelegateHelper__factory'; - export enum DelegationType { VOTING, PROPOSITION, @@ -10,43 +10,141 @@ export enum DelegationType { } export type MetaDelegateParams = { - underlyingAsset: string; - delegationType: DelegationType; 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; - signature: SignatureLike; }; export class MetaDelegateHelperService { - private readonly _contractInterface: MetaDelegateHelperInterface; + readonly _contract: MetaDelegateHelper; + + readonly _contractInterface = MetaDelegateHelper__factory.createInterface(); + private readonly metaDelegateHelperContractAddress: string; - constructor(private readonly metaDelegateHelperContracAddress: string) { - this._contractInterface = MetaDelegateHelper__factory.createInterface(); + 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 params = delegateParams.map(p => { - const sig: Signature = utils.splitSignature(p.signature); - return { - ...p, - v: sig.v, - r: sig.r, - s: sig.s, - }; - }); - const tx: PopulatedTransaction = { data: this._contractInterface.encodeFunctionData('batchMetaDelegate', [ - params, + delegateParams, ]), - to: this.metaDelegateHelperContracAddress, + to: this.metaDelegateHelperContractAddress, from: user, - gasLimit: BigNumber.from('1000000'), + gasLimit: BigNumber.from( + gasLimitRecommendations[ProtocolAction.batchMetaDelegate], + ), }; return tx; } + + public async prepareV3DelegateByTypeSignature({ + underlyingAsset, + delegatee, + delegationType, + delegator, + increaseNonce, + governanceTokenName, + nonce, + connectedChainId, + deadline, + }: DelegateMetaSigParams): Promise { + 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); + } }