From 619e6bb9526497c957cea314de3c2d2e07c3c6b0 Mon Sep 17 00:00:00 2001 From: fredo Date: Mon, 1 Dec 2025 11:43:44 +0100 Subject: [PATCH 1/2] feat: add script to manage super admin --- script/ManageAdminVerifiers.s.sol | 72 +++++++++++++++++++ .../test/DeployAdminVerifierSuperAdmin.s.sol | 24 +++++++ test/ManagementScripts.t.sol | 49 +++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 script/ManageAdminVerifiers.s.sol create mode 100644 script/test/DeployAdminVerifierSuperAdmin.s.sol create mode 100644 test/ManagementScripts.t.sol diff --git a/script/ManageAdminVerifiers.s.sol b/script/ManageAdminVerifiers.s.sol new file mode 100644 index 0000000..ab78961 --- /dev/null +++ b/script/ManageAdminVerifiers.s.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.28; + +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; + +import {StateOracle} from "../src/StateOracle.sol"; +import {IAdminVerifier} from "../src/interfaces/IAdminVerifier.sol"; + +/// @title ManageAdminVerifiers +/// @notice Foundry script for adding or removing admin verifiers on an existing `StateOracle`. +/// @dev +/// Environment variables expected (all optional except `STATE_ORACLE_ADDRESS`): +/// - `STATE_ORACLE_ADDRESS`: address of the deployed `StateOracle` proxy/instance. +/// - `ADMIN_VERIFIER_TO_ADD`: address of the admin verifier to add (single address). +/// - `ADMIN_VERIFIER_TO_REMOVE`: address of the admin verifier to remove (single address). +/// +/// Example: +/// ```bash +/// STATE_ORACLE_ADDRESS=0xOracle \ +/// ADMIN_VERIFIER_TO_ADD=0xVerifier \ +/// forge script script/ManageAdminVerifiers.s.sol --broadcast --rpc-url $RPC_URL +/// ``` +contract ManageAdminVerifiers is Script { + error NoAdminVerifierAction(); + + modifier broadcast() { + vm.startBroadcast(); + _; + vm.stopBroadcast(); + } + + function run() external broadcast { + StateOracle oracle = StateOracle(vm.envAddress("STATE_ORACLE_ADDRESS")); + address verifierToAdd = vm.envOr("ADMIN_VERIFIER_TO_ADD", address(0)); + address verifierToRemove = vm.envOr("ADMIN_VERIFIER_TO_REMOVE", address(0)); + require(verifierToAdd != address(0) || verifierToRemove != address(0), NoAdminVerifierAction()); + + if (verifierToAdd != address(0)) _addAdminVerifier(oracle, verifierToAdd); + if (verifierToRemove != address(0)) _removeAdminVerifier(oracle, verifierToRemove); + } + + function addAdminVerifier(StateOracle oracle, address verifier) public broadcast { + _addAdminVerifier(oracle, verifier); + } + + function removeAdminVerifier(StateOracle oracle, address verifier) public broadcast { + _removeAdminVerifier(oracle, verifier); + } + + function _addAdminVerifier(StateOracle oracle, address verifier) internal { + IAdminVerifier adminVerifier = IAdminVerifier(verifier); + if (oracle.isAdminVerifierRegistered(adminVerifier)) { + console2.log("Admin verifier already registered:", verifier); + return; + } + + oracle.addAdminVerifier(adminVerifier); + console2.log("Added admin verifier:", verifier); + } + + function _removeAdminVerifier(StateOracle oracle, address verifier) internal { + IAdminVerifier adminVerifier = IAdminVerifier(verifier); + if (!oracle.isAdminVerifierRegistered(adminVerifier)) { + console2.log("Admin verifier not registered, skipping removal:", verifier); + return; + } + + oracle.removeAdminVerifier(adminVerifier); + console2.log("Removed admin verifier:", verifier); + } +} diff --git a/script/test/DeployAdminVerifierSuperAdmin.s.sol b/script/test/DeployAdminVerifierSuperAdmin.s.sol new file mode 100644 index 0000000..10b87c3 --- /dev/null +++ b/script/test/DeployAdminVerifierSuperAdmin.s.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.28; + +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; + +import {AdminVerifierSuperAdmin} from "../../src/verification/admin/AdminVerifierSuperAdmin.sol"; + +/// @title DeployAdminVerifierSuperAdmin +/// @notice Deploys the test-only verifier outside the production core deployment flow. +contract DeployAdminVerifierSuperAdmin is Script { + error InvalidSuperAdmin(); + + function run() external returns (AdminVerifierSuperAdmin verifier) { + address superAdmin = vm.envAddress("ADMIN_VERIFIER_SUPER_ADMIN_ADDRESS"); + require(superAdmin != address(0), InvalidSuperAdmin()); + + vm.startBroadcast(); + verifier = new AdminVerifierSuperAdmin(superAdmin); + vm.stopBroadcast(); + + console2.log("Admin Verifier (Super Admin) deployed at", address(verifier)); + } +} diff --git a/test/ManagementScripts.t.sol b/test/ManagementScripts.t.sol new file mode 100644 index 0000000..5aa256c --- /dev/null +++ b/test/ManagementScripts.t.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: CC0-1.0 +pragma solidity ^0.8.28; + +import {Test} from "forge-std/Test.sol"; + +import {DeployAdminVerifierSuperAdmin} from "../script/test/DeployAdminVerifierSuperAdmin.s.sol"; +import {ManageAdminVerifiers} from "../script/ManageAdminVerifiers.s.sol"; +import {IAdminVerifier} from "../src/interfaces/IAdminVerifier.sol"; +import {AdminVerifierSuperAdmin} from "../src/verification/admin/AdminVerifierSuperAdmin.sol"; + +contract AdminVerifierRegistryMock { + mapping(IAdminVerifier verifier => bool registered) public isAdminVerifierRegistered; + + function addAdminVerifier(IAdminVerifier verifier) external { + isAdminVerifierRegistered[verifier] = true; + } + + function removeAdminVerifier(IAdminVerifier verifier) external { + isAdminVerifierRegistered[verifier] = false; + } +} + +contract ManagementScriptsTest is Test { + function test_ManageAdminVerifiersRunAddsAndRemovesConfiguredVerifiers() public { + ManageAdminVerifiers script = new ManageAdminVerifiers(); + AdminVerifierRegistryMock oracle = new AdminVerifierRegistryMock(); + IAdminVerifier verifierToAdd = IAdminVerifier(makeAddr("verifierToAdd")); + IAdminVerifier verifierToRemove = IAdminVerifier(makeAddr("verifierToRemove")); + oracle.addAdminVerifier(verifierToRemove); + + vm.setEnv("STATE_ORACLE_ADDRESS", vm.toString(address(oracle))); + vm.setEnv("ADMIN_VERIFIER_TO_ADD", vm.toString(address(verifierToAdd))); + vm.setEnv("ADMIN_VERIFIER_TO_REMOVE", vm.toString(address(verifierToRemove))); + + script.run(); + + assertTrue(oracle.isAdminVerifierRegistered(verifierToAdd)); + assertFalse(oracle.isAdminVerifierRegistered(verifierToRemove)); + } + + function test_DeployAdminVerifierSuperAdminUsesConfiguredOwner() public { + address superAdmin = makeAddr("superAdmin"); + vm.setEnv("ADMIN_VERIFIER_SUPER_ADMIN_ADDRESS", vm.toString(superAdmin)); + + AdminVerifierSuperAdmin verifier = new DeployAdminVerifierSuperAdmin().run(); + + assertEq(verifier.owner(), superAdmin); + } +} From b45541a07a229b5e931b6e77039de051c80463ed Mon Sep 17 00:00:00 2001 From: fredo Date: Wed, 12 Aug 2026 13:11:37 +0200 Subject: [PATCH 2/2] test(gas): record management script snapshots --- .gas-snapshot | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gas-snapshot b/.gas-snapshot index f2854ac..06255c7 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -137,6 +137,8 @@ Initialize:test_isAdmin() (gas: 953761) InitializeWhitelist:test_initialNonWhitelistedUser() (gas: 19126) InitializeWhitelist:test_initialWhitelistState() (gas: 13110) InitializeWhitelist:test_isAdmin() (gas: 953761) +ManagementScriptsTest:test_DeployAdminVerifierSuperAdminUsesConfiguredOwner() (gas: 1190846) +ManagementScriptsTest:test_ManageAdminVerifiersRunAddsAndRemovesConfiguredVerifiers() (gas: 1019807) OperatorAdminCanManageOperators:testFuzz_RevertIf_nonOperatorAdminGrantsOperatorRole(address) (runs: 256, μ: 24963, ~: 24963) OperatorAdminCanManageOperators:testFuzz_RevertIf_nonOperatorAdminRevokesOperatorRole(address) (runs: 256, μ: 55290, ~: 55290) OperatorAdminCanManageOperators:test_isAdmin() (gas: 953739) @@ -272,4 +274,4 @@ TransferManager:testFuzz_changePendingManager(address,address) (runs: 256, μ: 1 TransferManager:testFuzz_transferManager(address) (runs: 256, μ: 194926, ~: 194926) TransferManager:test_RevertIf_transferManagerToZeroAddress() (gas: 169304) TransferManager:test_isAdmin() (gas: 953783) -WhitelistBase:test_isAdmin() (gas: 953761) \ No newline at end of file +WhitelistBase:test_isAdmin() (gas: 953761)