From 947d6be8bac97f4ac50f14bbaeb364c74613c547 Mon Sep 17 00:00:00 2001 From: Harsh Pandey Date: Tue, 10 Dec 2024 22:22:53 +0530 Subject: [PATCH] feat: add zksync (#24) * feat: add zksync * chore: fix comment --- Makefile | 3 ++- foundry.toml | 4 +-- generator/generator.ts | 21 +++++++++++---- generator/templates/proposal.template.ts | 2 +- generator/types.ts | 3 ++- generator/utils/importsResolver.ts | 2 +- scripts/RiskStewardsBase.s.sol | 5 ++-- scripts/networks/RiskStewardsZkSync.s.sol | 11 ++++++++ .../src/contracts/examples/ZkSyncExample.sol | 27 +++++++++++++++++++ 9 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 scripts/networks/RiskStewardsZkSync.s.sol create mode 100644 zksync/src/contracts/examples/ZkSyncExample.sol diff --git a/Makefile b/Makefile index 5a154ef..e1c0f39 100644 --- a/Makefile +++ b/Makefile @@ -31,4 +31,5 @@ git-diff : deploy-ledger :; FOUNDRY_PROFILE=${chain} forge script $(if $(filter zksync,${chain}),--zksync) ${contract} --rpc-url ${chain} $(if ${dry},--sender 0x25F2226B597E8F9514B3F68F00f494cF4f286491 -vvvv, --ledger --mnemonic-indexes ${MNEMONIC_INDEX} --sender ${LEDGER_SENDER} --verify -vvvv --slow --broadcast) deploy-pk :; FOUNDRY_PROFILE=${chain} forge script $(if $(filter zksync,${chain}),--zksync) ${contract} --rpc-url ${chain} $(if ${dry},--sender 0x25F2226B597E8F9514B3F68F00f494cF4f286491 -vvvv, --private-key ${PRIVATE_KEY} --verify -vvvv --slow --broadcast) -run-script:; FOUNDRY_PROFILE=${network} forge script ${contract} --rpc-url ${network} --sig "run(bool, bool, bool)" ${broadcast} ${generate_diff} ${skip_timelock} -vv + +run-script:; FOUNDRY_PROFILE=${network} forge script $(if $(filter zksync,${network}),--zksync) ${contract} --rpc-url ${network} --sig "run(bool, bool, bool)" ${broadcast} ${generate_diff} ${skip_timelock} -vv \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index 862658f..d2d7a33 100644 --- a/foundry.toml +++ b/foundry.toml @@ -24,8 +24,8 @@ evm_version = 'shanghai' [profile.zksync.zksync] compile = true fallback_oz = true -mode = '3' -zksolc = '1.5.3' +optimizer_mode = 'z' +zksolc = '1.5.7' [rpc_endpoints] mainnet = "${RPC_MAINNET}" diff --git a/generator/generator.ts b/generator/generator.ts index b76dc20..0c8bd5e 100644 --- a/generator/generator.ts +++ b/generator/generator.ts @@ -69,8 +69,10 @@ async function askBeforeWrite(options: Options, path: string, content: string) { export async function writeFiles(options: Options, {jsonConfig, payloads}: Files) { const baseName = generateFolderName(options); const baseFolder = path.join(process.cwd(), 'src/contracts/updates/', baseName); + const zkSyncBaseFolder = path.join(process.cwd(), 'zksync/src/contracts/updates', baseName); + const isZkSync = options.pools.includes('AaveV3ZkSync'); - if (fs.existsSync(baseFolder)) { + if (fs.existsSync(baseFolder) || (isZkSync && fs.existsSync(zkSyncBaseFolder))) { if (!options.force && fs.existsSync(baseFolder)) { const force = await confirm({ message: 'A proposal already exists at that location, do you want to continue?', @@ -79,16 +81,25 @@ export async function writeFiles(options: Options, {jsonConfig, payloads}: Files if (!force) return; } } else { - fs.mkdirSync(baseFolder, {recursive: true}); + if (isZkSync) { + fs.mkdirSync(zkSyncBaseFolder, {recursive: true}); + } + if (!isZkSync || options.pools.length > 1) { + fs.mkdirSync(baseFolder, {recursive: true}); + } } // write config - await askBeforeWrite(options, path.join(baseFolder, 'config.ts'), jsonConfig); + await askBeforeWrite( + options, + path.join(isZkSync ? zkSyncBaseFolder : baseFolder, 'config.ts'), + jsonConfig + ); - for (const {payload, contractName} of payloads) { + for (const {pool, payload, contractName} of payloads) { await askBeforeWrite( options, - path.join(baseFolder, `${contractName}.sol`), + path.join(pool === 'AaveV3ZkSync' ? zkSyncBaseFolder : baseFolder, `${contractName}.sol`), payload, ); } diff --git a/generator/templates/proposal.template.ts b/generator/templates/proposal.template.ts index 9cfe3fe..2c88db0 100644 --- a/generator/templates/proposal.template.ts +++ b/generator/templates/proposal.template.ts @@ -24,7 +24,7 @@ export const proposalTemplate = ( * @title ${title || 'TODO'} * @author ${author || 'TODO'} * - discussion: ${discussion || 'TODO'} - * - deploy-command: make run-script contract=src/contracts/updates/${folderName}/${contractName}.sol:${contractName} network=${getChainAlias( + * - deploy-command: make run-script contract=${chain == 'ZkSync' ? 'zksync/' : ''}src/contracts/updates/${folderName}/${contractName}.sol:${contractName} network=${getChainAlias( chain )} broadcast=false generate_diff=true skip_timelock=false */ diff --git a/generator/types.ts b/generator/types.ts index 052d532..909e9a1 100644 --- a/generator/types.ts +++ b/generator/types.ts @@ -19,7 +19,8 @@ export const V3_POOLS = [ 'AaveV3Base', 'AaveV3Gnosis', 'AaveV3Scroll', - 'AaveV3BNB' + 'AaveV3BNB', + 'AaveV3ZkSync' ] as const satisfies readonly (keyof typeof addressBook)[]; export const POOLS = [ diff --git a/generator/utils/importsResolver.ts b/generator/utils/importsResolver.ts index 469c4fa..382048d 100644 --- a/generator/utils/importsResolver.ts +++ b/generator/utils/importsResolver.ts @@ -41,7 +41,7 @@ function generateRiskStewardImport(code: string) { const match = code.match(/RiskStewards(\w+)/); if (match) { - imports = `import {RiskStewards${match[1]}} from '../../../../scripts/networks/RiskStewards${match[1]}.s.sol';\n`; + imports = `import {RiskStewards${match[1]}} from '${match[1] == 'ZkSync' ? '../' : ''}../../../../scripts/networks/RiskStewards${match[1]}.s.sol';\n`; if (findMatch(code, 'IRiskSteward')) { imports += `import {IRiskSteward${findMatch(code, 'IPriceCapAdapter') ? ', IPriceCapAdapter': ''}} from '../../../interfaces/IRiskSteward.sol';\n`; } diff --git a/scripts/RiskStewardsBase.s.sol b/scripts/RiskStewardsBase.s.sol index 5ab41b1..fabf42f 100644 --- a/scripts/RiskStewardsBase.s.sol +++ b/scripts/RiskStewardsBase.s.sol @@ -125,9 +125,8 @@ abstract contract RiskStewardsBase is ProtocolV3TestBase { vm.warp(block.timestamp + uint256(maxTimelock) + 1); } - bool rateUpdatesPresent = rateUpdates.length != 0; if (generateDiffReport) - createConfigurationSnapshot(pre, POOL, true, rateUpdatesPresent, false, false); + createConfigurationSnapshot(pre, POOL, true, true, false, false); if (capUpdates.length != 0) { callDatas[txCount] = abi.encodeWithSelector(IRiskSteward.updateCaps.selector, capUpdates); @@ -175,7 +174,7 @@ abstract contract RiskStewardsBase is ProtocolV3TestBase { } if (generateDiffReport) { - createConfigurationSnapshot(post, POOL, true, rateUpdatesPresent, false, false); + createConfigurationSnapshot(post, POOL, true, true, false, false); diffReports(pre, post); } diff --git a/scripts/networks/RiskStewardsZkSync.s.sol b/scripts/networks/RiskStewardsZkSync.s.sol new file mode 100644 index 0000000..cbc996f --- /dev/null +++ b/scripts/networks/RiskStewardsZkSync.s.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3ZkSync} from 'aave-address-book/AaveV3ZkSync.sol'; +import {RiskStewardsBase} from '../RiskStewardsBase.s.sol'; + +abstract contract RiskStewardsZkSync is RiskStewardsBase { + constructor() + RiskStewardsBase(address(AaveV3ZkSync.POOL), AaveV3ZkSync.RISK_STEWARD) + {} +} diff --git a/zksync/src/contracts/examples/ZkSyncExample.sol b/zksync/src/contracts/examples/ZkSyncExample.sol new file mode 100644 index 0000000..9469ed7 --- /dev/null +++ b/zksync/src/contracts/examples/ZkSyncExample.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AaveV3ZkSyncAssets} from 'aave-address-book/AaveV3ZkSync.sol'; +import {IAaveV3ConfigEngine as IEngine} from 'aave-v3-origin/src/contracts/extensions/v3-config-engine/IAaveV3ConfigEngine.sol'; +import {EngineFlags} from 'aave-v3-origin/src/contracts/extensions/v3-config-engine/EngineFlags.sol'; +import {RiskStewardsZkSync} from '../../../../scripts/networks/RiskStewardsZkSync.s.sol'; + +// make run-script network=zksync contract=zksync/src/contracts/examples/ZkSyncExample.sol broadcast=false generate_diff=true skip_timelock=false +contract ZkSyncExample is RiskStewardsZkSync { + /** + * @return string name identifier used for the diff + */ + function name() public pure override returns (string memory) { + return 'zksync_example'; + } + + function capsUpdates() public pure override returns (IEngine.CapsUpdate[] memory) { + IEngine.CapsUpdate[] memory capUpdates = new IEngine.CapsUpdate[](1); + capUpdates[0] = IEngine.CapsUpdate({ + asset: AaveV3ZkSyncAssets.USDC_UNDERLYING, + supplyCap: 2_500_000, + borrowCap: EngineFlags.KEEP_CURRENT + }); + return capUpdates; + } +}