Skip to content

Commit ececf8e

Browse files
committed
Create and initialize SystemSignerRegistry keeping track of signers
1 parent 2d06562 commit ececf8e

File tree

3 files changed

+88
-2
lines changed

3 files changed

+88
-2
lines changed

scripts/foundry/InitializeL1ScrollOwner.s.sol

+22-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol";
2121
import {ScrollOwner} from "../../src/misc/ScrollOwner.sol";
2222
import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol";
2323

24+
import {SystemSignerRegistry} from "../../src/L1/system-contract/SystemSignerRegistry.sol";
25+
26+
2427
// solhint-disable max-states-count
2528
// solhint-disable state-visibility
2629
// solhint-disable var-name-mixedcase
@@ -81,7 +84,8 @@ contract InitializeL1ScrollOwner is Script {
8184
configL1GatewayRouter();
8285
configL1CustomERC20Gateway();
8386
configL1ERC721Gateway();
84-
configL1ERC1155Gateway();
87+
configL1ERC1155Gateway();
88+
configSystemContract();
8589

8690
configL1USDCGateway();
8791
configEnforcedTxGateway();
@@ -272,4 +276,21 @@ contract InitializeL1ScrollOwner is Script {
272276
owner.updateAccess(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR, _selectors, SCROLL_MULTISIG_NO_DELAY_ROLE, true);
273277
owner.updateAccess(L1_ENFORCED_TX_GATEWAY_PROXY_ADDR, _selectors, EMERGENCY_MULTISIG_NO_DELAY_ROLE, true);
274278
}
279+
280+
function configSystemContract() internal {
281+
// If we already have deployed it, just do:
282+
SystemSignerRegistry sys = SystemSignerRegistry(SYSTEM_CONTRACT_ADDR);
283+
284+
// sys has a normal constructor that set the "owner" to `ScrollOwner`.
285+
// Now we want to let the Security Council call `addSigner(...)` with no delay.
286+
bytes4[] memory selectors = new bytes4[](1);
287+
selectors[0] = sys.addSigner.selector;
288+
289+
owner.updateAccess(
290+
SYSTEM_CONTRACT_ADDR, // the system contract
291+
selectors, // array of function selectors (onlyOwner)
292+
SECURITY_COUNCIL_NO_DELAY_ROLE,
293+
true
294+
);
295+
}
275296
}

src/L1/L1ScrollMessenger.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// SPDX-License-Identifier: MIT
2-
32
pragma solidity =0.8.24;
43

54
import {IScrollChain} from "./rollup/IScrollChain.sol";
@@ -10,6 +9,7 @@ import {IScrollMessenger} from "../libraries/IScrollMessenger.sol";
109
import {ScrollMessengerBase} from "../libraries/ScrollMessengerBase.sol";
1110
import {WithdrawTrieVerifier} from "../libraries/verifier/WithdrawTrieVerifier.sol";
1211

12+
1313
import {IMessageDropCallback} from "../libraries/callbacks/IMessageDropCallback.sol";
1414

1515
// solhint-disable avoid-low-level-calls
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity =0.8.24;
3+
4+
import "@openzeppelin/contracts/access/Ownable.sol";
5+
6+
/**
7+
* @dev Example "SystemSignerRegistry" storing `(startBlock, signer)` pairs.
8+
* The getSigners() function returns parallel arrays for block numbers and addresses,
9+
*
10+
*/
11+
contract SystemSignerRegistry is Ownable {
12+
struct Signer {
13+
uint64 startBlock;
14+
address signer;
15+
}
16+
17+
Signer[] private signers;
18+
19+
constructor(address _owner) {
20+
_transferOwnership(_owner);
21+
}
22+
23+
/**
24+
* @dev Add a (startBlock, signer) pair. Only the owner can do this.
25+
*/
26+
function addSigner(uint64 _startBlock, address _signer) external onlyOwner {
27+
require(_signer != address(0), "Zero address not allowed");
28+
signers.push(Transition({startBlock: _startBlock, signer: _signer}));
29+
}
30+
31+
/**
32+
* @dev Remove a signer by matching both startBlock & signer, or just signer (you choose).
33+
*
34+
*/
35+
function removeSigner(uint64 _startBlock, address _signer) external onlyOwner {
36+
uint256 length = signers.length;
37+
for (uint256 i = 0; i < length; i++) {
38+
// If you only want to match signer, ignore _startBlock
39+
if (signers[i].startBlock == _startBlock && signers[i].signer == _signer) {
40+
if (i < length - 1) {
41+
signers[i] = signers[length - 1];
42+
}
43+
signers.pop();
44+
return;
45+
}
46+
}
47+
revert("Transition not found");
48+
}
49+
50+
/**
51+
* @dev Return two parallel arrays: blockNumbers and signers.
52+
*
53+
*/
54+
function getSigners() external view returns (uint64[] memory, address[] memory) {
55+
uint256 len = transitions.length;
56+
uint64[] memory blocks = new uint64[](len);
57+
address[] memory addrs = new address[](len);
58+
59+
for (uint256 i = 0; i < len; i++) {
60+
blocks[i] = signers[i].startBlock;
61+
addrs[i] = signers[i].signer;
62+
}
63+
return (blocks, addrs);
64+
}
65+
}

0 commit comments

Comments
 (0)