Skip to content

Commit

Permalink
feat: Emission admin AIP generator (bgd-labs#473)
Browse files Browse the repository at this point in the history
* feat: Emission admin AIP generator

* fix: outsource explorer list curration to viem

* fix: typo

Co-authored-by: Harsh Pandey <[email protected]>

* Update generator/features/emission.ts

Co-authored-by: Harsh Pandey <[email protected]>

* Update generator/features/emission.ts

Co-authored-by: Harsh Pandey <[email protected]>

---------

Co-authored-by: Harsh Pandey <[email protected]>
  • Loading branch information
Rozengarden and brotherlymite authored Oct 7, 2024
1 parent 5dd0d74 commit 226a629
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 1 deletion.
2 changes: 2 additions & 0 deletions generator/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {eModeUpdates} from './features/eModesUpdates';
import {eModeAssets} from './features/eModesAssets';
import {priceFeedsUpdates} from './features/priceFeedsUpdates';
import {freezeUpdates} from './features/freeze';
import {emissionUpdates} from './features/emission';
import {assetListing, assetListingCustom} from './features/assetListing';
import {generateFiles, writeFiles} from './generator';
import {CHAIN_ID_CLIENT_MAP} from '@bgd-labs/js-utils';
Expand Down Expand Up @@ -79,6 +80,7 @@ const FEATURE_MODULES_V3 = [
assetListing,
assetListingCustom,
freezeUpdates,
emissionUpdates,
PLACEHOLDER_MODULE,
];

Expand Down
11 changes: 11 additions & 0 deletions generator/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
scroll,
zkSync,
} from 'viem/chains';
import {Client, Hex, getAddress} from 'viem';
import {CHAIN_ID_CLIENT_MAP} from '@bgd-labs/js-utils';

export const AVAILABLE_CHAINS = [
'Ethereum',
Expand Down Expand Up @@ -54,6 +56,15 @@ export function getPoolChain(pool: PoolIdentifier) {
return chain;
}

export function getExplorerLink(chainId: number, address: Hex) {
const client = CHAIN_ID_CLIENT_MAP[chainId];
let url = client.chain?.blockExplorers?.default.url;
if (url && url.endsWith('/')) {
url = url.slice(0, -1); // sanitize explorer url
}
return `${url}/address/${getAddress(address)}`;
}

export function getDate() {
const date = new Date();
const years = date.getFullYear();
Expand Down
97 changes: 97 additions & 0 deletions generator/features/emission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import {confirm} from '@inquirer/prompts';
import {CodeArtifact, FEATURE, FeatureModule, PoolIdentifier} from '../types';
import {getContract} from 'viem';
import {CHAIN_TO_CHAIN_ID, getPoolChain, getExplorerLink} from '../common';
import {TEST_EXECUTE_PROPOSAL} from '../utils/constants';
import {EmissionUpdate} from './types';
import {addressPrompt, translateJsAddressToSol} from '../prompts/addressPrompt';
import {CHAIN_ID_CLIENT_MAP} from '@bgd-labs/js-utils';

async function fetchEmission(pool: PoolIdentifier): Promise<EmissionUpdate> {
const asset = await addressPrompt({
message: 'Address of the reward asset for which emission admin will be set',
required: true,
});

const chain = getPoolChain(pool);
const erc20 = getContract({
abi: [
{
constant: true,
inputs: [],
name: 'symbol',
outputs: [{internalType: 'string', name: '', type: 'string'}],
payable: false,
stateMutability: 'view',
type: 'function',
},
],
client: CHAIN_ID_CLIENT_MAP[CHAIN_TO_CHAIN_ID[chain]],
address: asset,
});
let symbol = '';
try {
symbol = await erc20.read.symbol();
} catch (e) {
console.log('could not fetch the symbol - this is likely an error');
console.log(e);
}

const admin = await addressPrompt({
message: `Address of the emission admin for the selected reward asset (${symbol})`,
required: true,
});
return {
asset: asset,
symbol: symbol,
admin: admin,
};
}

export const emissionUpdates: FeatureModule<EmissionUpdate[]> = {
value: FEATURE.EMISSION,
description: 'Set the emission admin for an asset',
async cli({pool}) {
const response: EmissionUpdate[] = [];
let more: boolean = true;
while (more) {
response.push(await fetchEmission(pool));
more = await confirm({
message: 'Do you want to assign an emission admin to another asset?',
default: false,
});
}
return response;
},
build({pool, cfg}) {
const response: CodeArtifact = {
code: {
constants: cfg
.map((cfg) => [
`address public constant ${cfg.symbol} = ${translateJsAddressToSol(cfg.asset)};`,
`address public constant ${cfg.symbol}_ADMIN = ${translateJsAddressToSol(cfg.admin)};`,
])
.flat(),
execute: cfg.map(
(cfg) =>
`IEmissionManager(${pool}.EMISSION_MANAGER).setEmissionAdmin(${cfg.symbol}, ${cfg.symbol}_ADMIN);`,
),
},
test: {
fn: cfg.map(
(cfg) => `function test_${cfg.symbol}Admin() public {
${TEST_EXECUTE_PROPOSAL}
assertEq(IEmissionManager(${pool}.EMISSION_MANAGER).getEmissionAdmin(${translateJsAddressToSol(cfg.asset)}), ${translateJsAddressToSol(cfg.admin)});
}`,
),
},
aip: {
specification: cfg.map(
(cfg) =>
`The emission admin role for [${cfg.symbol}](${getExplorerLink(CHAIN_TO_CHAIN_ID[getPoolChain(pool)], cfg.asset)}) is granted to [${cfg.admin}](${getExplorerLink(CHAIN_TO_CHAIN_ID[getPoolChain(pool)], cfg.admin)}).\n`,
),
},
};
return response;
},
};
6 changes: 6 additions & 0 deletions generator/features/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,9 @@ export interface TokenStream {
export interface FreezeUpdate extends AssetSelector {
shouldBeFrozen: boolean;
}

export interface EmissionUpdate {
asset: Hex;
symbol: string;
admin: Hex;
}
3 changes: 3 additions & 0 deletions generator/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
PriceFeedUpdate,
RateStrategyUpdate,
FreezeUpdate,
EmissionUpdate,
} from './features/types';
import {FlashBorrower} from './features/flashBorrower';

Expand Down Expand Up @@ -88,6 +89,7 @@ export enum FEATURE {
RATE_UPDATE_V3 = 'RATE_UPDATE_V3',
RATE_UPDATE_V2 = 'RATE_UPDATE_V2',
FREEZE = 'FREEZE',
EMISSION = 'EMISSION',
OTHERS = 'OTHERS',
}

Expand Down Expand Up @@ -136,6 +138,7 @@ export interface PoolConfig {
[FEATURE.RATE_UPDATE_V3]?: RateStrategyUpdate[]; // TODO: type could be improved
[FEATURE.RATE_UPDATE_V2]?: RateStrategyUpdate[];
[FEATURE.FREEZE]?: FreezeUpdate[];
[FEATURE.EMISSION]?: EmissionUpdate[];
[FEATURE.OTHERS]?: {};
};
cache: PoolCache;
Expand Down
4 changes: 3 additions & 1 deletion generator/utils/importsResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ export function prefixWithImports(code: string) {
if (findMatch(code, 'GovernanceV3Ethereum')) {
imports += `import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol';\n`;
}

if (findMatch(code, 'IEmissionManager')) {
imports += `import {IEmissionManager} from 'aave-v3-periphery/contracts/rewards/interfaces/IEmissionManager.sol';\n`;
}
return imports + code;
}

0 comments on commit 226a629

Please sign in to comment.