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

feat: deploy multisig wallets and timelock contract to address centralization related risks #92

Merged
merged 9 commits into from
Sep 10, 2024

Conversation

adu-web3
Copy link
Collaborator

@adu-web3 adu-web3 commented Sep 6, 2024

Description

closes: #81

To address centralization related risks, we should transfer ownership to a multi-sig wallet to avoid single point failure, and even utilize timelock contract to make important operations like upgrading a contract transparent for community.

here are the steps needed to achieve the goal:

  • deploy a set of gnosis safe proxy factory contract and multisig singleton contract on Exocore testnet
  • create 2-of-3 multisig wallet on Holesky testnet from front end UI
  • create 2-of-3 multsig wallet on Exocore testnet with script
  • add CustomTimelockController
  • add fuzzing test for governance which utilizes CustomTimelockController and safe multisig
  • write documentation

Summary by CodeRabbit

  • New Features

    • Added support for the "safe-smart-account" library to enhance modularity.
    • Introduced a governance framework for smart contracts, detailing roles and operational protocols.
    • Implemented a new multisignature wallet deployment script using Gnosis Safe.
  • Documentation

    • Added a document outlining the governance structure and operational protocols for smart contracts.
    • Introduced JSON files for multisig wallet configurations and contract addresses.
  • Bug Fixes

    • Resolved import path issues for various components to improve code organization.
  • Tests

    • Added comprehensive tests for governance functionalities and multisig wallet interactions.

Copy link
Contributor

coderabbitai bot commented Sep 6, 2024

Walkthrough

This pull request introduces a new submodule for the "safe-smart-account" library, enhancing the project's modularity. It also adds governance documentation for a smart contract system, detailing a two-tier governance model, and introduces a new CustomTimelockController. Various Solidity scripts have been updated to reorganize import paths for better clarity, and new JSON files have been added to manage multisig wallet configurations and smart contract addresses.

Changes

Files Change Summary
.gitmodules Added submodule entry for "safe-smart-account" library.
docs/contract-governance.md Added governance structure and operational protocols for smart contracts.
lib/safe-smart-account Introduced new subproject for "safe-smart-account" library.
remappings.txt Added mapping for @safe-contracts to the new library path.
script/*.s.sol Moved import paths for BeaconProxyBytecode and CustomProxyAdmin to src/utils.
script/deployedMultisigWallets.json Added JSON file for multisig wallet configurations for "holesky" and "exocore".
script/safe_contracts_on_exocore.json Added JSON file for Gnosis Safe contract addresses.
src/utils/CustomTimelockController.sol Added new contract extending OpenZeppelin's TimelockController with pause functionality.
test/foundry/*.t.sol Updated import paths for BeaconProxyBytecode and CustomProxyAdmin.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MultisigWallet
    participant CustomTimelockController
    participant SafeSmartAccount

    User->>MultisigWallet: Propose Action
    MultisigWallet->>CustomTimelockController: Submit Proposal
    CustomTimelockController->>SafeSmartAccount: Execute Action
    SafeSmartAccount-->>User: Action Completed
Loading

Assessment against linked issues

Objective Addressed Explanation
Centralization Related Risks (81)

Possibly related PRs

Poem

🐇 In the meadow where the code does play,
A new smart account hops in today.
With governance strong and paths realigned,
Multisigs dance, all well-defined.
So let’s cheer for changes, both big and small,
In this rabbit's world, we welcome them all! 🌼

Tip

New review model

We have updated our review workflow to use the Anthropic's Claude family of models. Please share any feedback in the discussion post on our Discord.


New features

Walkthrough comment now includes:

  • Possibly related PRs: A list of potentially related PRs to help you recall past context.
  • Suggested labels: CodeRabbit can now suggest labels by learning from your past PRs. You can also provide custom labeling instructions in the UI or configuration file.

Notes:

  • Please share any feedback in the discussion post on our Discord.
  • Possibly related PRs, automatic label suggestions based on past PRs, learnings, and possibly related issues require data opt-in (enabled by default).

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@adu-web3
Copy link
Collaborator Author

For reviewer's convenience, I list some of the main changes:

  1. add a new utils directory under src directory, and move CustomProxyAdmin and BeaconProxyByteCode to this directory
  2. implement the CustomTimelockController that adds circuit breaker roles to pause target contract in emergency without waiting for timelock
  3. add script script/15_DeploySafeMulstisigWallet.s.sol to deploy multisig wallet on Exocore
  4. add test test/Governance.t.sol to test multisig and timelocker

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 806c050 and 302956e.

Files selected for processing (20)
  • .gitmodules (1 hunks)
  • docs/contract-governance.md (1 hunks)
  • lib/safe-smart-account (1 hunks)
  • remappings.txt (1 hunks)
  • script/12_RedeployClientChainGateway.s.sol (1 hunks)
  • script/14_CorrectBootstrapErrors.s.sol (1 hunks)
  • script/15_DeploySafeMulstisigWallet.s.sol (1 hunks)
  • script/2_DeployBoth.s.sol (1 hunks)
  • script/7_DeployBootstrap.s.sol (1 hunks)
  • script/BaseScript.sol (1 hunks)
  • script/deployedMultisigWallets.json (1 hunks)
  • script/integration/1_DeployBootstrap.s.sol (1 hunks)
  • script/safe_contracts_on_exocore.json (1 hunks)
  • src/storage/BootstrapStorage.sol (1 hunks)
  • src/utils/CustomTimelockController.sol (1 hunks)
  • test/foundry/ExocoreDeployer.t.sol (1 hunks)
  • test/foundry/Governance.t.sol (1 hunks)
  • test/foundry/unit/Bootstrap.t.sol (2 hunks)
  • test/foundry/unit/ClientChainGateway.t.sol (1 hunks)
  • test/foundry/unit/CustomProxyAdmin.t.sol (1 hunks)
Files skipped from review due to trivial changes (12)
  • lib/safe-smart-account
  • script/12_RedeployClientChainGateway.s.sol
  • script/14_CorrectBootstrapErrors.s.sol
  • script/2_DeployBoth.s.sol
  • script/7_DeployBootstrap.s.sol
  • script/BaseScript.sol
  • script/integration/1_DeployBootstrap.s.sol
  • src/storage/BootstrapStorage.sol
  • test/foundry/ExocoreDeployer.t.sol
  • test/foundry/unit/Bootstrap.t.sol
  • test/foundry/unit/ClientChainGateway.t.sol
  • test/foundry/unit/CustomProxyAdmin.t.sol
Additional context used
Gitleaks
script/safe_contracts_on_exocore.json

2-2: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

LanguageTool
docs/contract-governance.md

[uncategorized] ~36-~36: Possible missing article found.
Context: ...sig wallet, and the timelock period for timelock controller.

(AI_HYDRA_LEO_MISSING_THE)

Additional comments not posted (14)
script/deployedMultisigWallets.json (1)

1-18: LGTM!

The JSON file is well-structured and contains the necessary information about the multisig wallets and signers for the holesky and exocore networks. The changes are approved.

remappings.txt (1)

12-13: LGTM!

The addition of the new mapping entry for @safe-contracts is a good change that enhances the project's modularity by allowing the inclusion of safe smart contract functionalities. The changes are approved.

script/safe_contracts_on_exocore.json (2)

1-12: LGTM!

The JSON file is well-structured and contains the necessary information about the smart contract addresses deployed on the exocore network. The changes are approved.

Tools
Gitleaks

2-2: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


2-2: Ignore the static analysis warning.

The static analysis tool has incorrectly flagged the Ethereum address at line 2 as a potential generic API key. This is a false positive and can be safely ignored.

Tools
Gitleaks

2-2: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

.gitmodules (1)

25-27: LGTM!

The changes to add a new submodule for the "safe-smart-account" library are approved. This enhances the project's modularity by integrating an external library.

src/utils/CustomTimelockController.sol (1)

1-37: LGTM!

The CustomTimelockController contract is correctly implemented and enhances the governance model by introducing a circuit breaker role. The changes are approved.

script/15_DeploySafeMulstisigWallet.s.sol (1)

1-72: LGTM!

The script to deploy a Gnosis Safe multisig wallet on the Exocore testnet is correctly implemented. It sets up the owners, threshold, and other parameters correctly, reads the deployed Safe contracts from a JSON file, and creates a new Safe proxy. The changes are approved.

docs/contract-governance.md (1)

1-36: Excellent documentation of the governance model!

The document provides a clear and comprehensive overview of the two-tier governance model using a custom timelock controller and multisig wallets. Key points:

  • Privileged functions are accessible only to the contract owner and are used for configuration, pause/unpause, enabling messaging, and upgradeability.
  • The two-tier governance structure consists of a CustomTimelockController that owns the business contract and Safe Multisig wallets acting as proposer/canceler, executor, circuit breaker, and admin.
  • The CustomTimelockController inherits from OpenZeppelin's TimelockController and introduces a circuit breaker role for emergency contract pauses without waiting for the timelock period.
  • Safe Multisig wallets are created using the Safe contracts, with the addresses provided in the deployment JSON file.
  • Governance tests using fuzzing ensure the expected behavior of the governance model.
  • In production, the Safe Multisig wallets will be set up with the appropriate roles, thresholds, signers, and timelock period.

The document is well-structured, easy to understand, and provides a solid foundation for implementing the governance model.

Tools
LanguageTool

[uncategorized] ~36-~36: Possible missing article found.
Context: ...sig wallet, and the timelock period for timelock controller.

(AI_HYDRA_LEO_MISSING_THE)

test/foundry/Governance.t.sol (6)

35-128: LGTM: Contract structure and setup look good!

The GovernanceTest contract is well-structured and imports the necessary dependencies. The state variables and setUp function provide a solid foundation for the governance tests by:

  • Defining Player and Signature structs for signers and signatures.
  • Initializing state variables for signers, Gnosis Safe contracts, a custom timelock controller, and other contract instances.
  • Deploying and setting up the necessary contracts, including the Gnosis Safe contracts, custom timelock controller, and client chain gateway.

The setup process is clear and comprehensive, ensuring that the contract is ready for testing the governance model.


130-158: LGTM: Client chain gateway deployment looks good!

The _deployClientChainGateway function is responsible for deploying and setting up the necessary contracts for the client chain gateway. It follows a clear sequence of deployments and initializations:

  1. Deploys a beacon oracle by calling _deployBeaconOracle.
  2. Deploys vault and capsule implementations.
  3. Deploys vault and capsule beacons using the respective implementations.
  4. Deploys a beacon proxy bytecode contract.
  5. Deploys an ERC20 token with a fixed supply.
  6. Deploys a mock LayerZero endpoint.
  7. Deploys the client chain gateway logic contract with the necessary parameters.
  8. Deploys a proxy for the client chain gateway using the TransparentUpgradeableProxy pattern.
  9. Initializes the client chain gateway with the owner address.

The function is well-structured and sets up the client chain gateway correctly.


160-181: LGTM: Beacon oracle deployment looks good!

The _deployBeaconOracle function is responsible for deploying the beacon oracle contract. It follows these steps:

  1. Determines the genesis block timestamp based on the current chain ID. It supports mainnet, Goerli, Sepolia, and Holesky testnets.
  2. Reverts if the chain ID is not supported.
  3. Deploys a new instance of EigenLayerBeaconOracle with the determined genesis block timestamp.
  4. Returns the deployed beacon oracle instance.

The function correctly handles the genesis block timestamp for different chains and deploys the beacon oracle contract with the appropriate timestamp.


183-234: LGTM: Fuzzing test for immediate pausing looks good!

The testFuzz_MultisigCanPauseImmediately function tests the scenario where the multisig can pause the gateway immediately using the circuit breaker role. It uses fuzzing to test different combinations of signers. The test follows these steps:

  1. Assumes that the signersMask is between 1 and 7 (inclusive) to ensure at least one signer and constrain to 3 bits.
  2. Selects the Holesky testnet fork.
  3. Prepares a multisig transaction to call the pause function on the timelock contract.
  4. Selects the signers based on the signersMask using the selectSigners function.
  5. Signs the transaction using the selected signers.
  6. If there are enough signers (at least 2), it executes the multisig transaction and checks if the gateway is paused.
  7. If there are not enough signers, it expects the transaction to revert and checks that the gateway is not paused.

The test is well-structured and covers the cases where there are enough signers and where there are not enough signers. It ensures that the multisig can pause the gateway immediately using the circuit breaker role.


236-354: LGTM: Fuzzing test for timelock delay on unpausing looks good!

The testFuzz_MultisigNeedsDelayToUnpause function tests the scenario where the multisig needs to wait for the timelock delay to unpause the gateway. It uses fuzzing to test different combinations of signers for pausing, scheduling, and executing the unpause transaction. The test follows these steps:

  1. Assumes that each of the pauseSignersMask, scheduleSignersMask, and executeSignersMask is between 1 and 7 (inclusive).
  2. Selects the Holesky testnet fork.
  3. Pauses the gateway using the pauseSignersMask and checks if the gateway is paused. If there are not enough signers, it expects the transaction to revert and exits the test.
  4. Prepares an unpause transaction and schedules it using the scheduleSignersMask. If there are not enough signers, it expects the transaction to revert and exits the test.
  5. Tries to execute the unpause transaction immediately and expects it to revert.
  6. Waits for the timelock delay using vm.warp.
  7. Executes the unpause transaction using the executeSignersMask.
  8. If there are enough signers for execution, it checks if the gateway is unpaused. Otherwise, it expects the transaction to revert and checks that the gateway is still paused.

The test is well-structured and covers the cases where there are enough signers and where there are not enough signers for each step. It ensures that the multisig needs to wait for the timelock delay to unpause the gateway.


356-416: LGTM: Signer selection and multisig transaction signing look good!

The selectSigners and signMultisigTransaction functions are well-implemented and serve their intended purposes in the governance tests.

The selectSigners function:

  • Takes a signersMask parameter and returns an array of selected Player instances based on the mask.
  • Initializes an array of 3 Player instances and a signerCount variable.
  • Checks each bit of the signersMask and adds the corresponding Player instance to the selectedSigners array if the bit is set.
  • Resizes the selectedSigners array to match the actual number of selected signers using assembly, avoiding unnecessary memory allocation.

The signMultisigTransaction function:

  • Takes the transaction details and an array of Player instances and returns the packed signature bytes.
  • Calculates the transaction hash using the getTransactionHash function of the multisig contract.
  • Sorts the signers array based on their addresses using bubble sort.
  • Generates the sorted signatures by iterating over the sorted signers array, signing the transaction hash with each signer's private key, and packing the signatures.

Both functions are correctly implemented and contribute to the effective testing of the governance model.

Copy link
Collaborator

@bwhour bwhour left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks good.

@adu-web3 adu-web3 added this pull request to the merge queue Sep 10, 2024
Merged via the queue into ExocoreNetwork:main with commit b769c58 Sep 10, 2024
7 checks passed
@adu-web3 adu-web3 deleted the multisig branch September 10, 2024 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Problem: Centralization Related Risks
4 participants