This proposal rotates the signer set of the StakedCelo MultiSig (0x78DaA21FcE4D30E74fF745Da3204764a0ad40179), the multisig that owns the stCELO protocol contracts. It replaces the six current owners with the six cLabs Security Council members and leaves the 3-of-6 threshold unchanged.
The rotation executes atomically in a single Celo Governance transaction routed through the MultiSig's governanceProposeAndExecute entrypoint. Routing it through Celo Governance — rather than the MultiSig's own internal signer flow — mirrors how other owner-gated stCELO changes are enacted (cgp-0239, cgp-0244) and places the transfer of control under the standard on-chain CELO governance process. No protocol contract, proxy, ownership, or balance is otherwise affected.
Keeping StakedCelo's default validator set healthy is an ongoing, owner-gated task. When a validator group becomes unhealthy or fully dead, the stake voted into it is stranded: it stops earning and cannot be rebalanced onto healthy groups until the MultiSig removes the dead group and adds healthy capacity. Adding and removing groups is gated to the MultiSig, so this upkeep is only as responsive as the MultiSig's signer set.
As of authoring, StakedCelo votes across 36 validator groups. 24 are healthy and 12 are unhealthy, and those 12 hold roughly 5.43M CELO of stranded stake:
| Category | Groups | Stake |
|---|---|---|
| Healthy | 24 | — |
| Unhealthy (total) | 12 | ~5.43M CELO |
| — of which dead (shut down for good) | 6 | ~2.73M CELO |
| — of which failing (not usable right now) | 6 | ~2.70M CELO |
This proposal aligns the MultiSig's signer set with the cLabs maintainers who actively operate stCELO — the same group that authors StakedCelo's governance actions (for example cgp-0239 and cgp-0244) — so that curation and recovery actions can be proposed and carried out by a responsive, security-focused signer set.
The six current signers of the MultiSig are replaced, one-for-one, with the six incoming signers. The 3-of-6 threshold and the owner count (6) are unchanged.
| Current signer (replaced) | New signer |
|---|---|
0x256F4B1F578Cd7bEaA440429caFb5AD21aBf6fd3 |
Marek 0x0Bd06B2b192BD9eC316f2880A0c296D9Bc3225e0 |
0x91f2437f5C8e7A3879e14a75a7C5b4CccC76023a |
Piers 0x21e595451bDD69a85cf946f37f5A6A356C3F875D |
0x3784a50f16af1C135b741914449BEa4AfdB0c5c4 |
Karl 0x812f7C111476D45998e6D0C615B41c180C362263 |
0x1f5979355411dF24c5Ce21Df5bD9f2fff418c194 |
Pavel 0x74bc9E59B52117Ccf5Ee457cFb0CBE83b339A065 |
0x4d82BfC8823a4F3AF82B0AdE52ff3e2d74A04757 |
Javi 0x4D89adf3a4a71b25FB1a6D702Cf059CF5BebD02d |
0x01AAe13F65fB90B490E6614adE0bffFA57AC5bbc |
Paul 0x8b4b85f78F799F8364198FFEd2266d3cb3EA0daE |
MultiSig.replaceOwner(address,address) is onlyWallet — it can only be called by the MultiSig itself (msg.sender == address(this)). A Governance proposal therefore cannot call replaceOwner directly. Instead, the MultiSig exposes a dedicated entrypoint for Celo Governance:
// staked-celo/contracts/common/MultiSig.sol
function governanceProposeAndExecute(
address[] calldata destinations,
uint256[] calldata values,
bytes[] calldata payloads
) external onlyGovernance {
for (uint256 i = 0; i < destinations.length; i++) {
bytes memory returnData = ExternalCall.execute(destinations[i], values[i], payloads[i]);
emit GovernanceTransactionExecuted(i, returnData);
}
}
onlyGovernance resolves the Celo Registry Governance entry, which is the Celo Governance proxy at 0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972. When Celo Governance invokes governanceProposeAndExecute, the MultiSig becomes the msg.sender of each forwarded replaceOwner call — and because each destination is the MultiSig itself, the onlyWallet check passes. This CGP therefore self-executes through Celo Governance; there is no separate multisig signer coordination and no multisig timelock on this path.
replaceOwner is a 1:1 swap that neither adds nor removes owners, so the required threshold (3) and owner count (6) are preserved throughout.
A single Celo Governance transaction:
StakedCelo MultiSig (0x78DaA21FcE4D30E74fF745Da3204764a0ad40179)governanceProposeAndExecute(address[] destinations, uint256[] values, bytes[] payloads)destinations[] — the MultiSig address, repeated six times (each replaceOwner targets the MultiSig itself)values[] — six entries, each 0payloads[] — six ABI-encoded replaceOwner(address,address) calldata blobs (selector 0xe20056e6), each pairing one current owner with its replacement, in the order listed under What ChangesThe six swaps apply atomically when the proposal executes.
See mainnet.json. It contains the single governanceProposeAndExecute transaction with the three array arguments fully expanded.
Key addresses:
0x78DaA21FcE4D30E74fF745Da3204764a0ad40179 — the contract whose owner set changes; exposes governanceProposeAndExecute(...) external onlyGovernance.0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972 — the onlyGovernance caller, resolved from the Celo Registry Governance entry.Confirm the current owner set and threshold (before execution):
cast call 0x78DaA21FcE4D30E74fF745Da3204764a0ad40179 "getOwners()(address[])" --rpc-url https://forno.celo.org
# expect the six current signers listed under "What Changes"
cast call 0x78DaA21FcE4D30E74fF745Da3204764a0ad40179 "required()(uint256)" --rpc-url https://forno.celo.org
# expect 3
After execution, getOwners() returns the six incoming signers and required() still returns 3.
Simulate the full proposal execution from Celo Governance (read-only eth_call, no state change). A non-reverting result confirms the authorization path and that all six swaps are valid:
cast call 0x78DaA21FcE4D30E74fF745Da3204764a0ad40179 \
"governanceProposeAndExecute(address[],uint256[],bytes[])" \
"[0x78DaA21FcE4D30E74fF745Da3204764a0ad40179,0x78DaA21FcE4D30E74fF745Da3204764a0ad40179,0x78DaA21FcE4D30E74fF745Da3204764a0ad40179,0x78DaA21FcE4D30E74fF745Da3204764a0ad40179,0x78DaA21FcE4D30E74fF745Da3204764a0ad40179,0x78DaA21FcE4D30E74fF745Da3204764a0ad40179]" \
"[0,0,0,0,0,0]" \
"[0xe20056e6000000000000000000000000256f4b1f578cd7beaa440429cafb5ad21abf6fd30000000000000000000000000bd06b2b192bd9ec316f2880a0c296d9bc3225e0,0xe20056e600000000000000000000000091f2437f5c8e7a3879e14a75a7c5b4cccc76023a00000000000000000000000021e595451bdd69a85cf946f37f5a6a356c3f875d,0xe20056e60000000000000000000000003784a50f16af1c135b741914449bea4afdb0c5c4000000000000000000000000812f7c111476d45998e6d0c615b41c180c362263,0xe20056e60000000000000000000000001f5979355411df24c5ce21df5bd9f2fff418c19400000000000000000000000074bc9e59b52117ccf5ee457cfb0cbe83b339a065,0xe20056e60000000000000000000000004d82bfc8823a4f3af82b0ade52ff3e2d74a047570000000000000000000000004d89adf3a4a71b25fb1a6d702cf059cf5bebd02d,0xe20056e600000000000000000000000001aae13f65fb90b490e6614ade0bfffa57ac5bbc0000000000000000000000008b4b85f78f799f8364198ffed2266d3cb3ea0dae]" \
--from 0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972 --rpc-url https://forno.celo.org
This simulation was run at authoring time and returned successfully (no revert). Each replaceOwner requires its current owner to exist and its incoming owner to be new; a non-reverting run therefore confirms all six pairings are valid against current on-chain state.
Medium. The change swaps signers only: the 3-of-6 threshold, the owner count, and every protocol contract, proxy, and balance are untouched. The incoming signers cannot self-onboard — the rotation is authorized solely by Celo Governance (a LockedGold referendum plus the Approver multisig), which is the deliberation and safeguard window for this change. The rotation concentrates the MultiSig's direct signer authority in the cLabs Security Council, a known, security-focused group; this is a deliberate trade of signer decentralization for operational responsiveness on the protocol's operational multisig.
contracts/common/MultiSig.sol