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

Timelock for Access Registry #318

Merged
merged 8 commits into from
Nov 28, 2024
32 changes: 32 additions & 0 deletions broadcast/147-deploy-access-managers.s.sol/1/run-1732573760.json

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions broadcast/147-deploy-access-managers.s.sol/1/run-1732641810.json

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions broadcast/147-deploy-access-managers.s.sol/1/run-latest.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

67 changes: 67 additions & 0 deletions broadcast/147-deploy-access-managers.s.sol/42161/run-latest.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions broadcast/147-deploy-access-managers.s.sol/8453/run-latest.json

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions script/migrations/121-upgrade_access_protocol.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import {Script} from "forge-std/Script.sol";
import {console2} from "forge-std/console2.sol";

contract DeployScript is Script, MigrationHelper {
// Entry Point address is the same on all chains.
address payable internal constant ENTRY_POINT = payable(0x0000000071727De22E5E9d8BAf0edAc6f37da032);
// Exchange Proxy address is the same on all chains.
address internal constant EXCHANGE_PROXY = 0x0000000000001fF3684f28c67538d4D072C22734;

Expand Down
35 changes: 35 additions & 0 deletions script/migrations/147-deploy-access-managers.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {AccessManager} from "@openzeppelin-5.0.1/contracts/access/manager/AccessManager.sol";

import {SafeBeaconProxy} from "@kinto-core/proxy/SafeBeaconProxy.sol";

import {UUPSProxy} from "@kinto-core-test/helpers/UUPSProxy.sol";
import {MigrationHelper} from "@kinto-core-script/utils/MigrationHelper.sol";

import {Script} from "forge-std/Script.sol";
import {console2} from "forge-std/console2.sol";

contract DeployScript is Script, MigrationHelper {
function run() public override {
super.run();

if (_getChainDeployment("AccessManager") != address(0)) {
console2.log("AccessManager is deployed");
return;
}

(bytes32 salt, address expectedAddress) =
mineSalt(keccak256(abi.encodePacked(type(AccessManager).creationCode, abi.encode(deployer))), "ACC000");

vm.broadcast(deployerPrivateKey);
AccessManager accessManager = new AccessManager{salt: salt}(deployer);

assertEq(address(accessManager), address(expectedAddress));
(bool isMember,) = accessManager.hasRole(0, deployer);
assertTrue(isMember);

saveContractAddress("AccessManager", address(accessManager));
}
}
90 changes: 90 additions & 0 deletions script/migrations/148-transfer-access-registry-ownership.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {AccessRegistry} from "@kinto-core/access/AccessRegistry.sol";
import {AccessPoint} from "@kinto-core/access/AccessPoint.sol";
import {UUPSProxy} from "@kinto-core-test/helpers/UUPSProxy.sol";
import {AccessManager} from "@openzeppelin-5.0.1/contracts/access/manager/AccessManager.sol";
import {Ownable} from "@openzeppelin-5.0.1/contracts/access/Ownable.sol";
import {UUPSUpgradeable} from "@openzeppelin-5.0.1/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {IAccessPoint} from "@kinto-core/interfaces/IAccessPoint.sol";
import {IEntryPoint} from "@aa-v7/interfaces/IEntryPoint.sol";

import {MigrationHelper} from "@kinto-core-script/utils/MigrationHelper.sol";

import "forge-std/console2.sol";

contract DeployScript is MigrationHelper {
function run() public override {
super.run();

AccessManager accessManager = AccessManager(_getChainDeployment("AccessManager"));
AccessRegistry accessRegistry = AccessRegistry(_getChainDeployment("AccessRegistry"));
address safe = getMamoriSafeByChainId(block.chainid);
console2.log("safe:", safe);

bytes4[] memory selectors = new bytes4[](4);
selectors[0] = AccessRegistry.upgradeAll.selector;
selectors[1] = UUPSUpgradeable.upgradeToAndCall.selector;
selectors[2] = AccessRegistry.disallowWorkflow.selector;
selectors[3] = AccessRegistry.allowWorkflow.selector;

vm.startBroadcast(deployerPrivateKey);

// make Safe an admin
accessManager.grantRole(accessManager.ADMIN_ROLE(), safe, 0);

// set UPGRADER role for target functions
accessManager.setTargetFunctionRole(address(accessRegistry), selectors, UPGRADER_ROLE);

// label the role
accessManager.labelRole(UPGRADER_ROLE, "UPGRADER_ROLE");

// grant role to a Safe with a delay
accessManager.grantRole(UPGRADER_ROLE, safe, ACCESS_REGISTRY_DELAY);

// set grantDelay, so admin can't grant the same role to another account with no delay
accessManager.setGrantDelay(UPGRADER_ROLE, ACCESS_REGISTRY_DELAY);

// set delay on admin actions so admin can't move selectors to another role with no delay
accessManager.setTargetAdminDelay(address(accessRegistry), ACCESS_REGISTRY_DELAY);

// transfer ownership to access manager
accessRegistry.transferOwnership(address(accessManager));

vm.stopBroadcast();

assertEq(accessRegistry.owner(), address(accessManager));

// check that Safe is an admin
(bool isMember, uint32 currentDelay) = accessManager.hasRole(accessManager.ADMIN_ROLE(), safe);
assertTrue(isMember);
assertEq(currentDelay, 0);

(bool immediate, uint32 delay) =
accessManager.canCall(safe, address(accessRegistry), AccessRegistry.upgradeAll.selector);
assertFalse(immediate);
assertEq(delay, ACCESS_REGISTRY_DELAY);

(isMember, currentDelay) = accessManager.hasRole(UPGRADER_ROLE, safe);
assertTrue(isMember);
assertEq(currentDelay, ACCESS_REGISTRY_DELAY);

// test that we can upgrade to a new access point version
AccessPoint newImpl = new AccessPoint(IEntryPoint(ENTRY_POINT), accessRegistry);

bytes memory upgradeAllCalldata = abi.encodeWithSelector(AccessRegistry.upgradeAll.selector, newImpl);

vm.prank(safe);
accessManager.schedule(
address(accessRegistry), upgradeAllCalldata, uint48(block.timestamp + ACCESS_REGISTRY_DELAY)
);

vm.warp(block.timestamp + ACCESS_REGISTRY_DELAY);

vm.prank(safe);
accessManager.execute(address(accessRegistry), upgradeAllCalldata);

assertEq(address(newImpl), accessRegistry.beacon().implementation());
}
}
2 changes: 0 additions & 2 deletions script/migrations/48-deploy_access_protocol.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import {Script} from "forge-std/Script.sol";
import {console2} from "forge-std/console2.sol";

contract DeployAccessProtocolScript is Script, MigrationHelper {
// Entry Point address is the same on all chains.
address payable internal constant ENTRY_POINT = payable(0x0000000071727De22E5E9d8BAf0edAc6f37da032);
// Exchange Proxy address is the same on all chains.
address internal constant EXCHANGE_PROXY = 0xDef1C0ded9bec7F1a1670819833240f027b25EfF;

Expand Down
2 changes: 0 additions & 2 deletions script/migrations/53-upgrade_access_point.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import {console2} from "forge-std/console2.sol";
import {Script} from "forge-std/Script.sol";

contract UpgradeAccessPointScript is Script, MigrationHelper {
address payable internal constant ENTRY_POINT = payable(0x0000000071727De22E5E9d8BAf0edAc6f37da032);

AccessRegistry registry;
AccessPoint newImpl;

Expand Down
49 changes: 47 additions & 2 deletions script/migrations/const.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract Constants {
import {CommonBase} from "forge-std/Base.sol";

contract Constants is CommonBase {
uint256 internal constant LEDGER = 0;
uint256 internal constant TREZOR = 1;

Expand All @@ -12,7 +14,9 @@ contract Constants {
address internal constant WUSDM = 0x57F5E098CaD7A3D1Eed53991D4d66C45C9AF7812; // wUSDM

uint64 internal constant NIO_GOVERNOR_ROLE = uint64(uint256(keccak256("NIO_GOVERNOR_ROLE")));
uint256 internal constant NIO_EXECUTION_DELAY = 3 days;
uint64 internal constant UPGRADER_ROLE = uint64(uint256(keccak256("UPGRADER_ROLE")));
uint32 internal constant NIO_EXECUTION_DELAY = 3 days;
uint32 internal constant ACCESS_REGISTRY_DELAY = 16 hours;
uint256 internal constant RATE_LIMIT_PERIOD = 1 minutes;
uint256 internal constant RATE_LIMIT_THRESHOLD = 10;
uint256 internal constant GAS_LIMIT_PERIOD = 30 days;
Expand All @@ -21,11 +25,52 @@ contract Constants {
address internal constant ARB_AAVE_POOL_PROVIDER = 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb;
address internal constant BASE_AAVE_POOL_PROVIDER = 0xe20fCBdBfFC4Dd138cE8b2E6FBb6CB49777ad64D;
address internal constant ETHEREUM_AAVE_POOL_PROVIDER = 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e;
address payable internal constant ENTRY_POINT = payable(0x0000000071727De22E5E9d8BAf0edAc6f37da032);

function getAavePoolProvider() internal view returns (address) {
if (block.chainid == ARBITRUM_CHAINID) return ARB_AAVE_POOL_PROVIDER;
if (block.chainid == BASE_CHAINID) return BASE_AAVE_POOL_PROVIDER;
if (block.chainid == ETHEREUM_CHAINID) return ETHEREUM_AAVE_POOL_PROVIDER;
revert("No Aave pool provider for current chain");
}

function getMamoriSafeByChainId(uint256 chainid) public view returns (address) {
// mainnet
if (chainid == 1) {
return 0xf152Abda9E4ce8b134eF22Dc3C6aCe19C4895D82;
}
// base
if (chainid == 8453) {
return 0x45e9deAbb4FdD048Ae38Fce9D9E8d68EC6f592a2;
}
// arbitrum one
if (chainid == 42161) {
return 0x8bFe32Ac9C21609F45eE6AE44d4E326973700614;
}
revert(string.concat("No Safe address for chainid:", vm.toString(block.chainid)));
}

function getWethByChainId(uint256 chainid) public view returns (address) {
// local
if (chainid == 31337) {
return 0x4200000000000000000000000000000000000006;
}
// mainnet
if (chainid == 1) {
return 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
}
// base
if (chainid == 8453) {
return 0x4200000000000000000000000000000000000006;
}
// arbitrum one
if (chainid == 42161) {
return 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
}
// optimism
if (chainid == 10) {
return 0x4200000000000000000000000000000000000006;
}
revert(string.concat("No WETH address for chainid:", vm.toString(block.chainid)));
}
}
24 changes: 0 additions & 24 deletions script/utils/DeployerHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,6 @@ import {ArtifactsReader} from "../../test/helpers/ArtifactsReader.sol";
abstract contract DeployerHelper is Create2Helper, ArtifactsReader {
using stdJson for string;

function getWethByChainId(uint256 chainid) public view returns (address) {
// local
if (chainid == 31337) {
return 0x4200000000000000000000000000000000000006;
}
// mainnet
if (chainid == 1) {
return 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
}
// base
if (chainid == 8453) {
return 0x4200000000000000000000000000000000000006;
}
// arbitrum one
if (chainid == 42161) {
return 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
}
// optimism
if (chainid == 10) {
return 0x4200000000000000000000000000000000000006;
}
revert(string.concat("No WETH address for chainid:", vm.toString(block.chainid)));
}

function create2(bytes memory creationCodeWithArgs) internal returns (address addr) {
return create2(creationCodeWithArgs, 0);
}
Expand Down
3 changes: 2 additions & 1 deletion test/artifacts/1/addresses.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@
"AaveLendWorkflow": "0x30592A2E419Db1338A6759279c547A9fdf2cd1DF",
"AaveRepayWorkflow": "0x694Cb08134aEA59D780f0d16004f38081fB184c9",
"AaveWithdrawWorkflow": "0xb4D3004b5E56d236977e9153F4689cF10E4Ff723",
"AaveBorrowWorkflow": "0x8c13D7aDD034A9E1bD8280225Efab7584c5E85A6"
"AaveBorrowWorkflow": "0x8c13D7aDD034A9E1bD8280225Efab7584c5E85A6",
"AccessManager": "0xaCC00065030f6FaaF7B3Cd6630158672380485dC"
}
3 changes: 2 additions & 1 deletion test/artifacts/42161/addresses.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@
"AaveLendWorkflow": "0xB47Ed636c8296729E81463109FEbf833CeEa71fb",
"AaveRepayWorkflow": "0x24f71379C39b515Ff5182F4b0cc298793EC5998c",
"AaveWithdrawWorkflow": "0xef4D6687372172c4af1802C208Ab40673b014309",
"AaveBorrowWorkflow": "0xD0187Ca378f7B26D53e0A91fBe8D7ba80498EF10"
"AaveBorrowWorkflow": "0xD0187Ca378f7B26D53e0A91fBe8D7ba80498EF10",
"AccessManager": "0xacc0003a4aAE5dA4ba12F771C7350D40147Cd7D4"
}
3 changes: 2 additions & 1 deletion test/artifacts/8453/addresses.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@
"AaveLendWorkflow": "0x720E7BC50C5Db2B387463F3f58E51D4eEa4513E5",
"AaveRepayWorkflow": "0x2B0AC9D2BfDB3cA3507F3678F82F9cF6Fd927cf8",
"AaveWithdrawWorkflow": "0xe307f7bf3fBfBB187f6870b6ad6b393f824e49e6",
"AaveBorrowWorkflow": "0x8447861eF3F3b390E7e090B5eFaac0133cD0bCEe"
"AaveBorrowWorkflow": "0x8447861eF3F3b390E7e090B5eFaac0133cD0bCEe",
"AccessManager": "0xAcc0004fD1693a13E1E1BFFCd152286906216f0B"
}