Skip to content
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
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,4 @@ 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 --verifier etherscan -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 --verifier etherscan -vvvv --slow --broadcast --verifier etherscan)


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
run-script:; FOUNDRY_PROFILE=$(if $(filter zksync,${network}),zksync,test) forge script $(if $(filter zksync,${network}),--zksync) ${contract} --rpc-url ${network} --sig "run(bool, bool, bool)" ${broadcast} ${generate_diff} ${skip_timelock} -vv
5 changes: 4 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ src = 'zksync'
test = 'zksync'
script = 'scripts'
libs = ['lib']
solc = '0.8.22'
solc = '0.8.27'
fs_permissions = [{ access = "write", path = "./reports" }]
ffi = true
evm_version = 'shanghai'
Expand All @@ -38,6 +38,9 @@ evm_version = 'cancun'
[profile.celo]
evm_version = 'paris'

[profile.test]
evm_version = 'cancun'

[rpc_endpoints]
mainnet = "${RPC_MAINNET}"
optimism = "${RPC_OPTIMISM}"
Expand Down
5 changes: 2 additions & 3 deletions generator/utils/importsResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ function generateRiskStewardImport(code: string) {
const match = code.match(/RiskStewards(\w+)/);

if (match) {
imports = `import {RiskStewards${match[1]}} from '${
match[1] == 'ZkSync' ? '../' : ''
}../../../../scripts/networks/RiskStewards${match[1]}.s.sol';\n`;
imports = `import {RiskStewards${match[1]}} from
'../../../../scripts/networks/RiskStewards${match[1]}.s.sol';\n`;
if (findMatch(code, 'IRiskSteward')) {
imports += `import {IRiskSteward${
findMatch(code, 'IPriceCapAdapter') ? ', IPriceCapAdapter' : ''
Expand Down
206 changes: 206 additions & 0 deletions zksync/scripts/RiskStewardsBase.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IAaveV3ConfigEngine as IEngine, IPool} from 'aave-v3-origin/src/contracts/extensions/v3-config-engine/IAaveV3ConfigEngine.sol';
import {IRiskSteward} from '../../src/interfaces/IRiskSteward.sol';
import {IOwnable} from 'aave-address-book/common/IOwnable.sol';
import {IACLManager} from 'aave-address-book/AaveV3.sol';

import {ProtocolV3TestBase} from 'aave-helpers/zksync/src/ProtocolV3TestBase.sol';

abstract contract RiskStewardsBase is ProtocolV3TestBase {
error FailedUpdate();
IPool immutable POOL;
IRiskSteward immutable STEWARD;

uint8 public constant MAX_TX = 6;

constructor(address pool, address steward) {
POOL = IPool(pool);
STEWARD = IRiskSteward(steward);
}

function capsUpdates() public pure virtual returns (IEngine.CapsUpdate[] memory) {}

function collateralsUpdates() public pure virtual returns (IEngine.CollateralUpdate[] memory) {}

function rateStrategiesUpdates()
public
pure
virtual
returns (IEngine.RateStrategyUpdate[] memory)
{}

function eModeCategoriesUpdates()
public
pure
virtual
returns (IEngine.EModeCategoryUpdate[] memory)
{}

function lstPriceCapsUpdates()
public
pure
virtual
returns (IRiskSteward.PriceCapLstUpdate[] memory)
{}

function stablePriceCapsUpdates()
public
pure
virtual
returns (IRiskSteward.PriceCapStableUpdate[] memory)
{}

function name() public pure virtual returns (string memory);

/**
* @notice This script doesn't broadcast as it's intended to be used via safe
*/
function run(bool broadcastToSafe, bool generateDiffReport, bool skipTimelock) external {
vm.startPrank(STEWARD.RISK_COUNCIL());
bytes[] memory callDatas = _simulateAndGenerateDiff(generateDiffReport, skipTimelock);
vm.stopPrank();

if (callDatas.length > 1)
emit log_string('** multiple calldatas emitted, please execute them all **');
emit log_string('safe address');
emit log_address(STEWARD.RISK_COUNCIL());
emit log_string('steward address:');
emit log_address(address(STEWARD));

for (uint8 i = 0; i < callDatas.length; i++) {
emit log_string('calldata:');
emit log_bytes(callDatas[i]);

if (broadcastToSafe) {
_sendToSafe(callDatas[i]);
}
}
}

function _simulateAndGenerateDiff(
bool generateDiffReport,
bool skipTimelock
) internal returns (bytes[] memory) {
bytes[] memory callDatas = new bytes[](MAX_TX);
uint8 txCount;

string memory pre = string(abi.encodePacked('pre_', name()));
string memory post = string(abi.encodePacked('post_', name()));

IEngine.CapsUpdate[] memory capUpdates = capsUpdates();
IEngine.CollateralUpdate[] memory collateralUpdates = collateralsUpdates();
IEngine.EModeCategoryUpdate[] memory eModeUpdates = eModeCategoriesUpdates();
IEngine.RateStrategyUpdate[] memory rateUpdates = rateStrategiesUpdates();
IRiskSteward.PriceCapLstUpdate[] memory lstPriceCapUpdates = lstPriceCapsUpdates();
IRiskSteward.PriceCapStableUpdate[] memory stablePriceCapUpdates = stablePriceCapsUpdates();

if (skipTimelock) {
vm.warp(block.timestamp + 15 days);
}

if (generateDiffReport) createConfigurationSnapshot(pre, POOL, true, true, false, false);

if (capUpdates.length != 0) {
callDatas[txCount] = abi.encodeWithSelector(IRiskSteward.updateCaps.selector, capUpdates);
(bool success, bytes memory resultData) = address(STEWARD).call(callDatas[txCount]);
_verifyCallResult(success, resultData);

txCount++;
}

if (collateralUpdates.length != 0) {
callDatas[txCount] = abi.encodeWithSelector(
IRiskSteward.updateCollateralSide.selector,
collateralUpdates
);
(bool success, bytes memory resultData) = address(STEWARD).call(callDatas[txCount]);
_verifyCallResult(success, resultData);
txCount++;
}

if (eModeUpdates.length != 0) {
callDatas[txCount] = abi.encodeWithSelector(
IRiskSteward.updateEModeCategories.selector,
eModeUpdates
);
(bool success, bytes memory resultData) = address(STEWARD).call(callDatas[txCount]);
_verifyCallResult(success, resultData);
txCount++;
}

if (rateUpdates.length != 0) {
callDatas[txCount] = abi.encodeWithSelector(IRiskSteward.updateRates.selector, rateUpdates);
(bool success, bytes memory resultData) = address(STEWARD).call(callDatas[txCount]);
_verifyCallResult(success, resultData);
txCount++;
}

if (lstPriceCapUpdates.length != 0) {
callDatas[txCount] = abi.encodeWithSelector(
IRiskSteward.updateLstPriceCaps.selector,
lstPriceCapUpdates
);
(bool success, bytes memory resultData) = address(STEWARD).call(callDatas[txCount]);
_verifyCallResult(success, resultData);
txCount++;
}

if (stablePriceCapUpdates.length != 0) {
callDatas[txCount] = abi.encodeWithSelector(
IRiskSteward.updateStablePriceCaps.selector,
stablePriceCapUpdates
);
(bool success, bytes memory resultData) = address(STEWARD).call(callDatas[txCount]);
_verifyCallResult(success, resultData);
txCount++;
}

if (generateDiffReport) {
createConfigurationSnapshot(post, POOL, true, true, false, false);
diffReports(pre, post);
}

// we defined the callDatas with MAX_TX size, we now squash it to the number of txs
assembly {
mstore(callDatas, txCount)
}
return callDatas;
}

function _sendToSafe(bytes memory callDatas) internal {
string[] memory inputs = new string[](8);
inputs[0] = 'npx';
inputs[1] = 'ts-node';
inputs[2] = 'scripts/safe-helper.ts';
inputs[3] = vm.toString(STEWARD.RISK_COUNCIL());
inputs[4] = vm.toString(address(STEWARD));
inputs[5] = vm.toString(callDatas);
inputs[6] = vm.toString(block.chainid);
inputs[7] = 'Call';
vm.ffi(inputs);
}

function _verifyCallResult(
bool success,
bytes memory returnData
) private pure returns (bytes memory) {
if (success) {
return returnData;
} else {
// Look for revert reason and bubble it up if present
if (returnData.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly

// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returnData)
revert(add(32, returnData), returndata_size)
}
} else {
revert FailedUpdate();
}
}
}
}
2 changes: 1 addition & 1 deletion zksync/src/contracts/examples/ZkSyncExample.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ 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';
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 {
Expand Down
Loading