WeuFoundDev / Governance-token-contracts

Governance contract of INPUT (INT) | A development based minting tokens for developers and researchers ecosystem.
GNU General Public License v3.0
2 stars 0 forks source link

multisig docs #25

Open 123456788940 opened 1 year ago

123456788940 commented 1 year ago

This Solidity contract is a MultiSigWallet, which allows multiple owners to collectively manage a single wallet. The contract requires a certain number of confirmations from the owners before any transaction can be executed.

Here are the main components and functionalities of the contract:

  1. Constructor: It is the constructor of the contract. It initializes the contract by setting the initial owners and the required number of confirmations for executing a transaction.

  2. Events: The contract defines several events to track important activities such as depositing funds, submitting a transaction, confirming a transaction, revoking confirmation, and executing a transaction. These events are used to emit information about the contract state changes, and they can be listened to off-chain.

  3. Modifiers:

    • onlyOwner: A custom modifier that ensures the function can only be executed by the 75% quorum of total contract owners.
    • txExists: A custom modifier that checks if a given transaction index exists in the transactions array.
    • notExecuted: A custom modifier that verifies if a transaction with a given index has not been executed yet.
    • notConfirmed: A custom modifier that checks if the sender has not confirmed a specific transaction yet.
  4. Struct: The contract defines a struct named Transaction, which represents each transaction submitted to the contract. It contains fields such as to (recipient address), value (transaction value), data (transaction data), executed (flag to indicate if the transaction has been executed), and numConfirmations (number of confirmations received for the transaction).

  5. Mappings:

    • isOwner: A mapping that keeps track of whether an address is one of the owners of the wallet.
    • isConfirmed: A nested mapping that tracks the confirmation status of each transaction for each owner. It helps prevent duplicate confirmations.
  6. Arrays:

    • owners: An array that stores the addresses of all the owners of the wallet.
    • transactions: An array that stores all the submitted transactions.
  7. Fallback Function: The receive() function is a fallback function that allows the contract to receive usdt,usdc,DAI when FOUNDATION REVENUE POOL contract sends funds to it with providing specific function data for which minting pool the supply has to be added for. It emits a Deposit event when funds are received.

  8. Public Functions:

    • submitTransaction: Allows the devs and researchers to submit a burning transaction to the contract. The transaction details (recipient, value, and data) are provided as parameters . It emits a SubmitTransaction event .
    • confirmTransaction: Allows an 75% quorum of council members to confirm a specific transaction by providing its index. The function updates the confirmation status and emits a ConfirmTransaction event.
    • executeTransaction: Allows the 75% quorum to execute a confirmed transaction. The function verifies if the required number of confirmations is met, then executes the transaction by sending the specified amount to the recipient and calling the provided data if available. It emits an ExecuteTransaction event.
    • revokeConfirmation: Allows the 26% quorum of council members to revoke their confirmation for a specific transaction. It decreases the number of confirmations and emits a RevokeConfirmation event.
    • getOwners: Returns the array of wallet owners.
    • getTransactionCount: Returns the total number of submitted transactions.
    • getTransaction: Returns details of a specific transaction based on its index.
  9. Utility Function:

    • combineKeys: A pure function that takes an array of bytes32 values and returns a single bytes32 value by combining the keys using the keccak256/poseidon is more preferred as a hash function. This function can be used for various purposes within the contract.

Overall, the contract provides a basic implementation of a multi-signature wallet, allowing multiple owners to manage transactions with a required number of confirmations for execution.

WeuFoundDev commented 1 year ago

@123456788940 @shivasai780 @sscodez check out

sscodez commented 1 year ago

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MultiSigWallet {
    // Custom modifiers
    modifier onlyOwner() {
        require(isOwner[msg.sender], "You are not an owner");
        _;
    }

    modifier txExists(uint256 _txIndex) {
        require(_txIndex < transactions.length, "Transaction does not exist");
        _;
    }

    modifier notExecuted(uint256 _txIndex) {
        require(!transactions[_txIndex].executed, "Transaction already executed");
        _;
    }

    modifier notConfirmed(uint256 _txIndex) {
        require(!isConfirmed[_txIndex][msg.sender], "Transaction already confirmed");
        _;
    }

    // Events
    event Deposit(address indexed sender, uint256 value, bytes data);
    event SubmitTransaction(address indexed owner, uint256 indexed txIndex, address indexed to, uint256 value, bytes data);
    event ConfirmTransaction(address indexed owner, uint256 indexed txIndex);
    event RevokeConfirmation(address indexed owner, uint256 indexed txIndex);
    event ExecuteTransaction(address indexed owner, uint256 indexed txIndex);

    // Struct to represent a transaction
    struct Transaction {
        address to;
        uint256 value;
        bytes data;
        bool executed;
        uint256 numConfirmations;
    }

    // Contract variables
    address[] public owners;
    uint256 public requiredConfirmations;
    mapping(address => bool) public isOwner;
    mapping(uint256 => mapping(address => bool)) public isConfirmed;
    Transaction[] public transactions;

    // Constructor to initialize the contract
    constructor(address[] memory _owners, uint256 _requiredConfirmations) {
        require(_owners.length > 0, "Owners list cannot be empty");
        require(_requiredConfirmations > 0 && _requiredConfirmations <= _owners.length, "Invalid required confirmations");

        for (uint256 i = 0; i < _owners.length; i++) {
            address owner = _owners[i];
            require(owner != address(0), "Invalid owner address");
            require(!isOwner[owner], "Duplicate owner");
            isOwner[owner] = true;
            owners.push(owner);
        }

        requiredConfirmations = _requiredConfirmations;
    }

    // Fallback function to receive funds with data for minting pool
    receive() external payable {
        emit Deposit(msg.sender, msg.value, msg.data);
    }

    // Submit a transaction for confirmation
    function submitTransaction(address _to, uint256 _value, bytes memory _data) public onlyOwner {
        uint256 txIndex = transactions.length;
        transactions.push(Transaction({
            to: _to,
            value: _value,
            data: _data,
            executed: false,
            numConfirmations: 0
        }));

        emit SubmitTransaction(msg.sender, txIndex, _to, _value, _data);
    }

    // Confirm a transaction
    function confirmTransaction(uint256 _txIndex) public onlyOwner txExists(_txIndex) notConfirmed(_txIndex) {
        Transaction storage transaction = transactions[_txIndex];
        transaction.numConfirmations++;

        emit ConfirmTransaction(msg.sender, _txIndex);
    }

    // Execute a confirmed transaction
    function executeTransaction(uint256 _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) {
        Transaction storage transaction = transactions[_txIndex];
        require(transaction.numConfirmations >= requiredConfirmations, "Not enough confirmations");

        transaction.executed = true;
        (bool success, ) = transaction.to.call{value: transaction.value}((transaction.data));
        require(success, "Transaction execution failed");

        emit ExecuteTransaction(msg.sender, _txIndex);
    }

    // Revoke confirmation for a transaction
    function revokeConfirmation(uint256 _txIndex) public onlyOwner txExists(_txIndex) {
        Transaction storage transaction = transactions[_txIndex];
        require(isConfirmed[_txIndex][msg.sender], "Transaction not confirmed");
        transaction.numConfirmations--;

        emit RevokeConfirmation(msg.sender, _txIndex);
    }

    // Get the array of wallet owners
    function getOwners() public view returns (address[] memory) {
        return owners;
    }

    // Get the total number of submitted transactions
    function getTransactionCount() public view returns (uint256) {
        return transactions.length;
    }

    // Get details of a specific transaction
    function getTransaction(uint256 _txIndex) public view txExists(_txIndex) returns (address to, uint256 value, bytes memory data, bool executed, uint256 numConfirmations) {
        Transaction storage transaction = transactions[_txIndex];
        return (
            transaction.to,
            transaction.value,
            transaction.data,
            transaction.executed,
            transaction.numConfirmations
        );
    }

    // Utility function to combine multiple bytes32 keys into a single bytes32 key
    function combineKeys(bytes32[] memory _keys) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(_keys));
    }
}
WeuFoundDev commented 1 year ago

Is this the final update . As initially we need @shivasai780 to create multi sig aggregation and threshold with sesssion key functionality . update it

WeuFoundDev commented 1 year ago

Create docs based on multi sig agg and threshold

shivasai780 commented 1 year ago

@WeuFoundDev There is no session key functionality still in this contract

WeuFoundDev commented 1 year ago

yeah we have to update it. Vinay is doing it in the last issue , if you find the same functionality close it from here @shivasai780 @vinaykumar0103 , please take a review