Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: extend listing generator with emission admin #476

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions generator/features/__snapshots__/assetListing.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -571,12 +571,14 @@ exports[`feature: assetListing > should return reasonable code 1`] = `
},
"code": {
"constants": [
"address public constant PSP = 0xcAfE001067cDEF266AfB7Eb5A286dCFD277f3dE5;",
"uint256 public constant PSP_SEED_AMOUNT = 1e18;",
"address public constant PSP = 0xcAfE001067cDEF266AfB7Eb5A286dCFD277f3dE5;
uint256 public constant PSP_SEED_AMOUNT = 1e18;
",
],
"execute": [
"IERC20(PSP).forceApprove(address(AaveV3Ethereum.POOL), PSP_SEED_AMOUNT);
AaveV3Ethereum.POOL.supply(PSP, PSP_SEED_AMOUNT, address(AaveV3Ethereum.COLLECTOR), 0);",
AaveV3Ethereum.POOL.supply(PSP, PSP_SEED_AMOUNT, address(AaveV3Ethereum.COLLECTOR), 0);
",
],
"fn": [
"function newListings() public pure override returns (IAaveV3ConfigEngine.Listing[] memory) {
Expand Down Expand Up @@ -618,7 +620,8 @@ exports[`feature: assetListing > should return reasonable code 1`] = `
GovV3Helpers.executePayload(vm,address(proposal));
(address aTokenAddress, , ) = AaveV3Ethereum.AAVE_PROTOCOL_DATA_PROVIDER.getReserveTokensAddresses(proposal.PSP());
assertGe(IERC20(aTokenAddress).balanceOf(address(AaveV3Ethereum.COLLECTOR)), 10 ** 18);
}",
}
",
],
},
}
Expand Down
54 changes: 37 additions & 17 deletions generator/features/assetListing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {fetchRateStrategyParamsV3} from './rateUpdates';
import {fetchCollateralUpdate} from './collateralsUpdates';
import {fetchCapsUpdate} from './capsUpdates';
import {Listing, ListingWithCustomImpl, TokenImplementations} from './types';
import {CHAIN_TO_CHAIN_ID, getPoolChain} from '../common';
import {getContract} from 'viem';
import {CHAIN_TO_CHAIN_ID, getPoolChain, getExplorerLink} from '../common';
import {getContract, isAddress} from 'viem';
import {confirm} from '@inquirer/prompts';
import {TEST_EXECUTE_PROPOSAL} from '../utils/constants';
import {addressPrompt, translateJsAddressToSol} from '../prompts/addressPrompt';
Expand Down Expand Up @@ -79,6 +79,7 @@ async function fetchListing(pool: PoolIdentifier): Promise<Listing> {
pool,
}),
asset,
admin: await addressPrompt({message: 'Emission admin address (optional)', required: false}),
};
}

Expand Down Expand Up @@ -134,17 +135,24 @@ export const assetListing: FeatureModule<Listing[]> = {
build({pool, cfg}) {
const response: CodeArtifact = {
code: {
constants: cfg
.map((cfg) => [
`address public constant ${cfg.assetSymbol} = ${translateJsAddressToSol(cfg.asset)};`,
`uint256 public constant ${cfg.assetSymbol}_SEED_AMOUNT = 1e${cfg.decimals};`,
])
.flat(),
execute: cfg.map(
(cfg) =>
`IERC20(${cfg.assetSymbol}).forceApprove(address(${pool}.POOL), ${cfg.assetSymbol}_SEED_AMOUNT);
${pool}.POOL.supply(${cfg.assetSymbol}, ${cfg.assetSymbol}_SEED_AMOUNT, address(${pool}.COLLECTOR), 0);`,
),
constants: cfg.map((cfg) => {
let listingConstant = `address public constant ${cfg.assetSymbol} = ${translateJsAddressToSol(cfg.asset)};\n`;
listingConstant += `uint256 public constant ${cfg.assetSymbol}_SEED_AMOUNT = 1e${cfg.decimals};\n`;
if (isAddress(cfg.admin)) {
listingConstant += `address public constant ${cfg.assetSymbol}_LM_ADMIN = ${translateJsAddressToSol(cfg.admin)};\n`;
}
return listingConstant;
}),
execute: cfg.map((cfg) => {
let listingExe = `IERC20(${cfg.assetSymbol}).forceApprove(address(${pool}.POOL), ${cfg.assetSymbol}_SEED_AMOUNT);\n`;
listingExe += `${pool}.POOL.supply(${cfg.assetSymbol}, ${cfg.assetSymbol}_SEED_AMOUNT, address(${pool}.COLLECTOR), 0);\n`;
if (isAddress(cfg.admin)) {
listingExe += `\n(address a${cfg.assetSymbol}, , ) = ${pool}.AAVE_PROTOCOL_DATA_PROVIDER.getReserveTokensAddresses(${cfg.assetSymbol});\n`;
listingExe += `IEmissionManager(${pool}.EMISSION_MANAGER).setEmissionAdmin(${cfg.assetSymbol}, ${cfg.assetSymbol}_ADMIN);\n`;
listingExe += `IEmissionManager(${pool}.EMISSION_MANAGER).setEmissionAdmin(a${cfg.assetSymbol}, ${cfg.assetSymbol}_ADMIN);\n`;
}
return listingExe;
}),
fn: [
`function newListings() public pure override returns (IAaveV3ConfigEngine.Listing[] memory) {
IAaveV3ConfigEngine.Listing[] memory listings = new IAaveV3ConfigEngine.Listing[](${
Expand All @@ -164,13 +172,22 @@ export const assetListing: FeatureModule<Listing[]> = {
],
},
test: {
fn: cfg.map(
(cfg) => `function test_collectorHas${cfg.assetSymbol}Funds() public {
fn: cfg.map((cfg) => {
let listingTest = `function test_collectorHas${cfg.assetSymbol}Funds() public {
${TEST_EXECUTE_PROPOSAL}
(address aTokenAddress, , ) = ${pool}.AAVE_PROTOCOL_DATA_PROVIDER.getReserveTokensAddresses(proposal.${cfg.assetSymbol}());
assertGe(IERC20(aTokenAddress).balanceOf(address(${pool}.COLLECTOR)), 10 ** ${cfg.decimals});
}`,
),
}\n`;
if (isAddress(cfg.admin)) {
listingTest += `\nfunction test_${cfg.assetSymbol}Admin() public {
${TEST_EXECUTE_PROPOSAL}
(address a${cfg.assetSymbol}, , ) = ${pool}.AAVE_PROTOCOL_DATA_PROVIDER.getReserveTokensAddresses(proposal.${cfg.assetSymbol}());
assertEq(IEmissionManager(${pool}.EMISSION_MANAGER).getEmissionAdmin(proposal.${cfg.assetSymbol}()), proposal.${cfg.assetSymbol}_ADMIN());
assertEq(IEmissionManager(${pool}.EMISSION_MANAGER).getEmissionAdmin(a${cfg.assetSymbol}), proposal.${cfg.assetSymbol}_ADMIN());
}\n`;
}
return listingTest;
}),
},
aip: {
specification: cfg.map((cfg) => {
Expand Down Expand Up @@ -215,6 +232,9 @@ export const assetListing: FeatureModule<Listing[]> = {
listingTemplate += `| Siloed Borrowing | ${cfg.withSiloedBorrowing} |\n`;
listingTemplate += `| Borrowable in Isolation | ${cfg.borrowableInIsolation} |\n`;
listingTemplate += `| Oracle | ${cfg.priceFeed} |\n`;
if (isAddress(cfg.admin)) {
listingTemplate += `\nAdditionaly [${cfg.admin}](${getExplorerLink(CHAIN_TO_CHAIN_ID[getPoolChain(pool)], cfg.admin)}) has been set as the emission admin for ${cfg.assetSymbol} and the corresponding aToken.\n`;
}
return listingTemplate;
}),
},
Expand Down
1 change: 1 addition & 0 deletions generator/features/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export interface Listing
rateStrategyParams: RateStrategyParams;
eModeCategory: string;
decimals: number;
admin?: Hex | '';
}

export interface ListingWithCustomImpl {
Expand Down
1 change: 1 addition & 0 deletions generator/utils/importsResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,6 @@ export function prefixWithImports(code: string) {
if (findMatch(code, 'IEmissionManager')) {
imports += `import {IEmissionManager} from 'aave-v3-periphery/contracts/rewards/interfaces/IEmissionManager.sol';\n`;
}

return imports + code;
}
Loading