diff --git a/ethereum/contracts/zksync/facets/Admin.sol b/ethereum/contracts/zksync/facets/Admin.sol index 9177afb71b94..0990a13cf391 100644 --- a/ethereum/contracts/zksync/facets/Admin.sol +++ b/ethereum/contracts/zksync/facets/Admin.sol @@ -40,7 +40,7 @@ contract AdminFacet is Base, IAdmin { /// @notice Starts the transfer of admin rights. Only the current governor or admin can propose a new pending one. /// @notice New admin can accept admin rights by calling `acceptAdmin` function. /// @param _newPendingAdmin Address of the new admin - function setPendingAdmin(address _newPendingAdmin) external onlyGovernorOrAdmin { + function setPendingAdmin(address _newPendingAdmin) external onlyGovernor { // Save previous value into the stack to put it into the event later address oldPendingAdmin = s.pendingAdmin; // Change pending admin diff --git a/ethereum/test/foundry/unit/concrete/Admin/Authorization.t.sol b/ethereum/test/foundry/unit/concrete/Admin/Authorization.t.sol new file mode 100644 index 000000000000..f390a62d45f7 --- /dev/null +++ b/ethereum/test/foundry/unit/concrete/Admin/Authorization.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.20; + +import {AdminTest} from "./_Admin_Shared.t.sol"; + +contract AuthorizationTest is AdminTest { + function test_SetPendingAdmin_RevertWhen_AdminNotGovernanceOwner() public { + address newAdmin = address(0x1337); + vm.prank(owner); + vm.expectRevert(bytes.concat("1g")); + proxyAsAdmin.setPendingAdmin(newAdmin); + } +} diff --git a/ethereum/test/foundry/unit/concrete/Admin/_Admin_Shared.t.sol b/ethereum/test/foundry/unit/concrete/Admin/_Admin_Shared.t.sol new file mode 100644 index 000000000000..a632f77b6532 --- /dev/null +++ b/ethereum/test/foundry/unit/concrete/Admin/_Admin_Shared.t.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {DiamondProxy} from "solpp/zksync/DiamondProxy.sol"; +import {DiamondInit} from "solpp/zksync/DiamondInit.sol"; +import {VerifierParams} from "solpp/zksync/Storage.sol"; +import {Diamond} from "solpp/zksync/libraries/Diamond.sol"; +import {AdminFacet} from "solpp/zksync/facets/Admin.sol"; +import {Governance} from "solpp/governance/Governance.sol"; + +contract AdminTest is Test { + DiamondProxy internal diamondProxy; + address internal owner; + address internal securityCouncil; + address internal governor; + AdminFacet internal adminFacet; + AdminFacet internal proxyAsAdmin; + + function getAdminSelectors() private view returns (bytes4[] memory) { + bytes4[] memory dcSelectors = new bytes4[](10); + dcSelectors[0] = adminFacet.setPendingGovernor.selector; + dcSelectors[1] = adminFacet.acceptGovernor.selector; + dcSelectors[2] = adminFacet.setPendingAdmin.selector; + dcSelectors[3] = adminFacet.acceptAdmin.selector; + dcSelectors[4] = adminFacet.setValidator.selector; + dcSelectors[5] = adminFacet.setPorterAvailability.selector; + dcSelectors[6] = adminFacet.setPriorityTxMaxGasLimit.selector; + dcSelectors[7] = adminFacet.executeUpgrade.selector; + dcSelectors[8] = adminFacet.freezeDiamond.selector; + dcSelectors[9] = adminFacet.unfreezeDiamond.selector; + return dcSelectors; + } + + function setUp() public { + owner = makeAddr("owner"); + securityCouncil = makeAddr("securityCouncil"); + governor = makeAddr("governor"); + DiamondInit diamondInit = new DiamondInit(); + + VerifierParams memory dummyVerifierParams = VerifierParams({ + recursionNodeLevelVkHash: 0, + recursionLeafLevelVkHash: 0, + recursionCircuitsSetVksHash: 0 + }); + + adminFacet = new AdminFacet(); + + bytes memory diamondInitCalldata = abi.encodeWithSelector( + diamondInit.initialize.selector, + 0x03752D8252d67f99888E741E3fB642803B29B155, + governor, + owner, + 0x02c775f0a90abf7a0e8043f2fdc38f0580ca9f9996a895d05a501bfeaa3b2e21, + 0, + 0x0000000000000000000000000000000000000000000000000000000000000000, + 0x70a0F165d6f8054d0d0CF8dFd4DD2005f0AF6B55, + dummyVerifierParams, + false, + 0x0100000000000000000000000000000000000000000000000000000000000000, + 0x0100000000000000000000000000000000000000000000000000000000000000, + 500000, // priority tx max L2 gas limit + 0 + ); + + Diamond.FacetCut[] memory facetCuts = new Diamond.FacetCut[](1); + facetCuts[0] = Diamond.FacetCut({ + facet: address(adminFacet), + action: Diamond.Action.Add, + isFreezable: false, + selectors: getAdminSelectors() + }); + + Diamond.DiamondCutData memory diamondCutData = Diamond.DiamondCutData({ + facetCuts: facetCuts, + initAddress: address(diamondInit), + initCalldata: diamondInitCalldata + }); + + diamondProxy = new DiamondProxy(block.chainid, diamondCutData); + proxyAsAdmin = AdminFacet(address(diamondProxy)); + } +}