Skip to content

Commit

Permalink
Multisig (#1193)
Browse files Browse the repository at this point in the history
* Add Multisig initial implementation

* Edit error messages

* Change Multisig naming: quorum instead of threshold

* Add Multisig mock

* Refactor Multisig not to store calls

* Add Multisig target mock

* Cover Multisig functionality with tests

* Add tests for signer management functionality

* Add more test cases for Multisig

* Run linter

* Address review comments

* Support review fixes in tests

* Change quorum and confirmations types to u32

* Optimize Multisig storage usage

* Solve confirmation issue when signer is removed

* Update changelog

* Fix review issues

* Run linter

* Add breaking change entry to changelog

* Make review fixes

* Fix review issues

* Document storage helpers

* Document events

* Document Multisig component itself

* Document all the Multisig functions

* Run linter

* Make minor doc fixes

* Fix in-code doc according to review comments

* Improve couple of comments
  • Loading branch information
immrsd authored Nov 8, 2024
1 parent 5fec9a5 commit 90bc317
Show file tree
Hide file tree
Showing 18 changed files with 2,459 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Multisig component (#1193)
- `is_valid_p256_signature` utility function to `openzeppelin_account::utils::signature` (#1189)
- `Secp256r1KeyPair` type and helpers to `openzeppelin_testing::signing` (#1189)
- `all_tokens_of_owner` function to `ERC721EnumerableComponent` fetching all owner's tokens in a single call (#1196)
Expand All @@ -27,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `DebugSecp256k1Point` replaced by a generic `DebugSecp256Point`
- Apply underscore pattern to the internal functions of `ERC2981Component` to prevent collisions
with new external functions (#1173)
- Move `Hash` and `PartialEq` impls of `Call` struct from `openzeppelin_governance::timelock::utils` to `openzeppelin_governance::utils` (#1193)

## 0.18.0 (2024-10-17)

Expand Down
4 changes: 1 addition & 3 deletions packages/account/src/account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ pub mod AccountComponent {
use openzeppelin_introspection::src5::SRC5Component::SRC5Impl;
use openzeppelin_introspection::src5::SRC5Component;
use starknet::account::Call;
use starknet::get_caller_address;
use starknet::get_contract_address;
use starknet::get_tx_info;
use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess};
use starknet::{get_caller_address, get_contract_address, get_tx_info};

#[storage]
pub struct Storage {
Expand Down
1 change: 1 addition & 0 deletions packages/governance/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ build-external-contracts = [
"openzeppelin_test_common::mocks::timelock::TimelockControllerMock",
"openzeppelin_test_common::mocks::timelock::MockContract",
"openzeppelin_test_common::mocks::timelock::TimelockAttackerMock",
"openzeppelin_test_common::mocks::multisig::MultisigTargetMock",
"openzeppelin_test_common::mocks::votes::ERC721VotesMock",
"openzeppelin_test_common::mocks::votes::ERC20VotesMock"
]
3 changes: 3 additions & 0 deletions packages/governance/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
pub mod multisig;

#[cfg(test)]
mod tests;

pub mod timelock;
pub mod utils;
pub mod votes;
6 changes: 6 additions & 0 deletions packages/governance/src/multisig.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub mod interface;
pub mod multisig;
pub mod storage_utils;

pub use interface::{TransactionID, TransactionState};
pub use multisig::MultisigComponent;
65 changes: 65 additions & 0 deletions packages/governance/src/multisig/interface.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts for Cairo v0.18.0 (governance/multisig/interface.cairo)

use starknet::ContractAddress;
use starknet::account::Call;

pub type TransactionID = felt252;

/// Represents the possible states of a Multisig transaction.
#[derive(Copy, Drop, Serde, PartialEq, Debug)]
pub enum TransactionState {
NotFound,
Pending,
Confirmed,
Executed
}

/// Interface of a contract providing the Multisig functionality.
#[starknet::interface]
pub trait IMultisig<TState> {
fn get_quorum(self: @TState) -> u32;
fn is_signer(self: @TState, signer: ContractAddress) -> bool;
fn get_signers(self: @TState) -> Span<ContractAddress>;
fn is_confirmed(self: @TState, id: TransactionID) -> bool;
fn is_confirmed_by(self: @TState, id: TransactionID, signer: ContractAddress) -> bool;
fn is_executed(self: @TState, id: TransactionID) -> bool;
fn get_submitted_block(self: @TState, id: TransactionID) -> u64;
fn get_transaction_state(self: @TState, id: TransactionID) -> TransactionState;
fn get_transaction_confirmations(self: @TState, id: TransactionID) -> u32;
fn hash_transaction(
self: @TState,
to: ContractAddress,
selector: felt252,
calldata: Span<felt252>,
salt: felt252
) -> TransactionID;
fn hash_transaction_batch(self: @TState, calls: Span<Call>, salt: felt252) -> TransactionID;

fn add_signers(ref self: TState, new_quorum: u32, signers_to_add: Span<ContractAddress>);
fn remove_signers(ref self: TState, new_quorum: u32, signers_to_remove: Span<ContractAddress>);
fn replace_signer(
ref self: TState, signer_to_remove: ContractAddress, signer_to_add: ContractAddress
);
fn change_quorum(ref self: TState, new_quorum: u32);
fn submit_transaction(
ref self: TState,
to: ContractAddress,
selector: felt252,
calldata: Span<felt252>,
salt: felt252,
) -> TransactionID;
fn submit_transaction_batch(
ref self: TState, calls: Span<Call>, salt: felt252
) -> TransactionID;
fn confirm_transaction(ref self: TState, id: TransactionID);
fn revoke_confirmation(ref self: TState, id: TransactionID);
fn execute_transaction(
ref self: TState,
to: ContractAddress,
selector: felt252,
calldata: Span<felt252>,
salt: felt252
);
fn execute_transaction_batch(ref self: TState, calls: Span<Call>, salt: felt252);
}
Loading

0 comments on commit 90bc317

Please sign in to comment.