Multi-signature wallet smart contracts

Multi-signature (multisig) wallets are smart contracts that allow multiple signers to review and agree on an action on the blockchain before the action is executed. For example, a multisig wallet could be used to control ETH, or a smart contract, requiring signatures from at least M of N total signers to execute the action. More generally, it is a type of decentralized governance.

On-chain multisig wallets are made possible by the fact that smart contracts can call other smart contracts. To execute a multisig transaction, one would:

  1. Compose an unsigned transaction
  2. Wrap the unsigned transaction in a multisig transaction, producing a new unsigned transaction
  3. Sign and broadcast the wrapped transaction to the blockchain
  4. Notify the other N signers to review the transaction
  5. M of N signers compose an approval transaction
  6. The signers sign and submit their approval transactions to the blockchain
  7. When the last required signer submits their approval transaction, the resulting original transaction is executed

Steps 2 and 5 are extremely complex and not widely supported. MultiBaas makes this far easier by automatically recognizing when a transaction is a multisig transaction, and seamlessly wrapping the unsigned transaction in the appropriate multisig transaction (submitTransaction(), approveTransaction(), etc.).

The following example request, a call to mint(), illustrates the concept of wrapped transactions.

Request:

Copy
Copied
POST .../chains/ethereum/addresses/multisigtoken/contracts/mltitoken/methods/mint
Copy
Copied
{
    "args": [
        "123"
    ],
    "from": "0xc6cc1faAEcf365F8A5Bca1A19fa893F89C88823F",
    "signer": "0xF9450D254A66ab06b30Cfa9c6e7AE1B7598c7172",
    "signAndSubmit": true
}

Response:

Copy
Copied
{
    "status": 200,
    "message": "Success",
    "result": {
        "tx": {
            "from": "0xF9450D254A66ab06b30Cfa9c6e7AE1B7598c7172",
            "to": "0xc6cc1faAEcf365F8A5Bca1A19fa893F89C88823F",
            "value": "0",
            "gas": 151453,
            "gasPrice": "1",
            "data": "0xc6427474000000000000000000000000cb1d236be8bcc58bafc35be1c300ef4b8614cb7a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024a0712d68000000000000000000000000000000000000000000000000000000000001e07800000000000000000000000000000000000000000000000000000000",
            "nonce": 6,
            "hash": "0x4f2e9c59ceb467a9f68334136d6ad6554e20d97fabf6a05c4d70811bb2a73f87"
        },
        "submitted": true,
        "summarizedInputs": [
            null
        ]
    }
}

Note that in the request, the “from” and “signer” fields are different. The “from” field relates to the unsigned transaction, to eventually be executed, and should be the address of the multisig wallet, whereas the signer field should be the submitter.

In the response, the “data” field includes the wrapped transaction. The key parts of the “data” field can be dissected as follows:

  • 0xc6427474...: the wrapping outer function selector, which is the first four bytes of the Keccak256 hash of the multisig Solidity method signature. This is padded to 64 bytes, hence the trailing zeroes. Explicitly: 0xc6427474 == keccak256("submitTransaction(address,uint256,bytes)") [0:4]
  • This is followed by the three parameters to submitTransaction():
    • address destination (of the target smart contract): 0xcb1d236be8bcc58bafc35be1c300ef4b8614cb7a
    • uint256 value (of ETH to send): 0x0...0
    • bytes data (the wrapped inner function call and its parameters): see next bullet point
  • 0xa0712d68...: the wrapped inner function selector, which is the first four bytes of the Keccak256 hash of the Solidity method signature. Explicitly: 0xa0712d68 == keccak256("mint(uint256)") [0:4]
  • This is followed by the parameters to mint()

The go-ethereum transaction ABI encoder library used within MultiBaas may add additional parameters as required.

Multisig Wallet UI

The built-in Multisig wallet functionality can also be accessed via Multisig from the main menu.

To deploy a new Multisig wallet:

  1. Click New Wallet
  2. Enter a label to identify the new wallet
  3. Add one or more owners by clicking Add Owner for each owner even if there is only one owner
  4. Enter the required number of confirmations
  5. Select the account you wish to use to deploy from your wallet software and from the Signer Selector
  6. Click Deploy

Note: Both the owners and number of confirmations can be changed after deploying the wallet, but the changes must be approved according to the existing combination of owners and required confirmations.

To link a Multisig wallet that already exists on the blockchain for use within MultiBaas:

  1. Click New Wallet
  2. Select the Link tab from the Deploy / Link dialogue
  3. Enter a label to identify the new wallet
  4. Enter the address of the Multisig wallet contract
  5. Click Link

Deployed or linked Multisig wallets are available from the Signer Selector for signing transactions throughout the application.

Configuring a Multisig Wallet

  1. Select a wallet using its label in the Multisig Wallet Management section
  2. Click the expandable panel where the wallet's name and address are displayed to reveal the configuration settings
  3. Under Owners
  4. Click Remove to remove an existing owner
  5. Enter an address and click Add to add a new owner
  6. Under Required Confirmations
  7. Enter a new number of required confirmations and click Change
  8. Confirm the transaction using your wallet software

Confirming and Revoking Transactions

From the Multisig wallet page you can confirm or revoke pending transactions submitted by one of the owners. The transactions table shows the transaction id, the status, and the details of the transaction.

Select the address you wish to interact with using the Signer Selector.

  • If the selected address has submitted or confirmed the transaction, the status column will show "Revoke". Click Revoke to revoke the transaction.
  • If the selected address is an owner of the wallet but did not submit and has not yet confirmed the transaction, the status column will show "Confirm". Click Confirm to confirm the transaction.
  • If the selected address is not an owner of the wallet and the transaction has not been confirmed to the level of required confirmations, the status column will show "Pending".

When the required number of owners have all confirmed the transaction, the status column will show Executed and the transaction cannot be withdrawn.

Copyright © Curvegrid 2022. All right reserved.