---
title: "How to Verify if an Address is Multi-Sig Inside Sui Smart Contracts"
description: "Enable secure accounts accessible by multiple people through a multi-signature contract."
author: "Kostas Chalkias"
datePublished: 2024-05-10
dateModified: 2026-07-30
category: "Developer Resources"
readTime: "6 min"
canonical: https://www.sui.io/blog/write-multi-signature-multisig-move-contracts
---

# How to Verify if an Address is Multi-Sig Inside Sui Smart Contracts

Multi-signature (multi-sig) wallets and accounts allow for enhanced key management by enabling either multiple parties to access shared assets under predefined conditions, or a single user to implement additional security measures. For example, a multi-sig wallet could be used to manage a decentralized autonomous organization’s (DAO) treasury, requiring consent from a certain percentage of members before executing transactions, or it could serve an individual seeking extra protection by distributing access across multiple devices or locations.

Sui native multi-sig wallets offer a plethora of applications. They can be used to create interactive game elements or commerce platforms that necessitate collective user actions for access. Establishing a user quorum or other conditions for access ensures that digital assets remain protected against unauthorized use by any individual key/member.

The Sui Move multi-sig smart contract detailed in this article confirms whether a Sui address is multi-sig and accommodates various key combinations, such as 2-of-3 or any M-of-N. Integrating multisig functionality directly into smart contracts, rather than through SDKs, provides distinct benefits. This method grants developers precise control over access and authorization within the contract’s logic, allowing them to stipulate specific conditions—like signatures from a designated subset of addresses—before permitting function execution. Such detailed control bolsters security by guarding against unsanctioned changes to the contract or asset transfers.

Incorporating multi-sig directly into smart contracts is pivotal for creating secure and resilient applications with adaptable governance models. This fosters a foundation of trust and cooperation within decentralized networks.

On-chain multi-sig is crucial because it offers transparency and verifiability in decentralized operations. It ensures that actions, such as executing smart contract functions, are only performed when they meet the agreed-upon criteria among stakeholders. For example, knowing if the caller of a smart contract function is a multi-sig address allows for the implementation of nuanced constraints. If a transaction is signed by 3 out of 5 members, up to 1,000 coins could be moved. Conversely, if only 1 out of 5 members signs, the transaction limit could be set to 100 coins. This flexibility in setting transaction thresholds based on the level of consensus provides a balance between security and functionality, making on-chain multisig an indispensable feature for collective asset management and decision-making in the blockchain space.

# Creating and using the multi-sig checker contract in Move

A multi-sig address is a special type of address that requires multiple signatures to authorize a transaction. A multi-sig checker smart contract derives a multi-sig address from a set of public keys, weights, and a threshold, and compares it with an expected address. 

Multi-sig addresses require multiple signatures to authorize a transaction. They are often used to enhance the security of funds by distributing control among multiple parties. For example, a 2-of-3 multi-sig address requires at least two out of three signers to approve a transaction. Multi-sig addresses can also be used for governance, escrow, or backup purposes.

The multi-sig smart contract performs three functions:

1.  It derives multi-sig addresses
2.  It verifies multi-sig addresses
3.  It can check if a sender is a multi-sig address

## Derive multi-sig addresses

The multisig module defines the `derive_multisig_address_quiet` which takes three parameters: `pks`, `weights`, and `threshold`. 

The `pks` parameter is a vector of vectors of bytes, representing the public keys of the signers.

The `weights` parameter is a vector of bytes, representing the weights of each signer.

The `threshold` parameter is a 16-bit unsigned integer, representing the minimum sum of weights required to execute a transaction from the multi-signature address.

The function returns an address, which is the derived multi-signature address.

`public fun derive_multisig_address_quiet(           pks: vector<vector<u8>>,           weights: vector<u8>,           threshold: u16,       ): address {`

 The function performs the following steps:

It defines a variable, `multiSigFlag`, of type 8-bit unsigned integer and assigns it the value `0x03`, which is the flag for multi-signature addresses.

`let multiSigFlag = 0x03;`

It creates an empty vector of bytes called `hash_data`, which will store the data to be hashed.

`let hash_data = vector<u8>[];`

It gets the lengths of the `pks` and `weights` vectors and checks that they are equal. If not, it aborts the execution with an error code: `ELengthsOfPksAndWeightsAreNotEqual`.

`let pks_len = pgs.length();   let weights_len = weights.length();   assert!(pks_len == weights_len, ELengthsOfPksAndWeightsAreNotEqual);`

It initializes a variable, `sum`, of type 16-bit unsigned integer and assigns it the value 0. It then loops through the `weights` vector and adds the values of each element to the `sum`. It then checks that the `threshold` is positive and not greater than the `sum`. If not, it aborts the execution with an error code: `EThresholdIsPositiveAndNotGreaterThanTheSumOfWeights`.

       `let mut sum = 0;           let mut i = 0;           while (i < weights_len) {               let w = weights[i] as u16;               sum = sum + w;               i = i + 1;           };           assert!(threshold > 0 && threshold <= sum, EThresholdIsPositiveAndNotGreaterThanTheSumOfWeights);`

 It pushes the `multiSigFlag` to the `hash_data` vector. It then serializes the threshold using the `bcs::to_bytes` function and appends the result to the `hash_data` vector.

       `hash_data.push_back(multiSigFlag);          let threshold_bytes: vector<u8> = bcs::to_bytes(&threshold);          hash_data.append(threshold_bytes);`

It loops through the `pks` and `weights` vectors and appends the elements of each pair to the `hash_data` vector.

        `let mut i = 0;           while (i < pks_len) {   hash_data.append(pks[i]);   hash_data.push_back(weights[i]);             i = i + 1;           };`

It hashes the `hash_data` vector using the `blake2b256` function and converts the result to an address using the `address::from_bytes` function. It then assigns the address to a variable, `ms_address`, and returns it.

        `let ms_address = address::from_bytes(blake2b256(&hash_data));           ms_address       }`

It derives a multi-sig address and returns the multi-sig address.

## Verifying multi-sig addresses

The `multisig` module also defines the `check_multisig_address_eq`, which checks if the created multi-sig address matches the expected address. As we mentioned above, a multi-sig address is a special type of address that requires multiple signatures to authorize a transaction. A multi-sig address is defined by a set of public keys, weights, and a threshold.

The function `check_multisig_address_eq` takes four parameters: `pks`, `weights`, `threshold`, and `expected_address`. The first three parameters are the same as the ones we used in the previous function, `derive_multisig_address_quiet`. The last parameter, `expected_address`, is an address value that we want to compare with the multi-sig address.

   `public entry fun check_multisig_address_eq(           pks: vector<vector<u8>>,           weights: vector<u8>,           threshold: u16,           expected_address: address,       ): bool {`

The function first calls the function, `derive_multisig_address_quiet`, which creates a multi-sig address from the given `public keys`, `weights`, and `threshold`. This function uses a hash-based algorithm to combine the public keys and the threshold into a 16-byte value, which is then converted into an address.

`let ms_address = derive_multisig_address_quiet(pks, weights, threshold);`

 The function then compares the multi-sig address with the expected address and returns true if the addresses are equal, and false otherwise.

`return (ms_address == expected_address)`

The function `check_multisig_address_eq` can be used to verify that a multi-sig address is correct and matches the expected value. This can be useful for testing, debugging, or auditing purposes. For example, one could use this function to check that a multi-sig address is consistent with the public keys and the threshold that were agreed upon by the signers.

## Checking the sender’s multi-sig address

Finally, the `multisig` module also defines the `check_if_sender_is_multisig_address`, which checks if the sender is the same multi-sig address that is derived from the provided `pks`, `weights`, and `threshold`.

The `check_if_sender_is_multisig_address` takes four parameters: `pks`, `weights`, `threshold`, and `ctx`. The first three parameters define the multi-sig address scheme, while the last parameter provides the transaction context.

The `pks` parameter is a vector of vectors of bytes, representing the public keys of the signers.

The `weights` parameter is a vector of bytes, representing the weights of each signer.

The `threshold` parameter is a 16-bit unsigned integer, representing the minimum sum of weights required to execute a transaction from the multi-sig address.

Finally, the `ctx` is a mutable reference to the TxContext, which contains information about the current transaction, such as the sender.

   `public fun check_if_sender_is_multisig_address(           pks: vector<vector<u8>>,           weights: vector<u8>,           threshold: u16,           ctx: &mut TxContext       ): bool {`

The `check_if_sender_is_multisig_address` function calls the `check_multisig_address_eq` function, which compares the multi-sig address with the sender address.

      `check_multisig_address_eq(pks, weights, threshold, ctx.sender())               }`

The function `check_multisig_address_eq` returns true if the sender address matches the multi-sig address scheme, and false otherwise.

# Get started with multi-sig

Multi-sig addresses are useful for scenarios where there is a need for enhanced security, accountability, or collaboration among multiple parties. Given the valuable digital assets stored on Sui, a multi-sig address can help keep those assets secure.

The smart contract described in this article can help you get started building applications designed for collaboration and joint custody of assets. As a further resource, you can look at the [source code and documentation for this project](https://github.com/MystenLabs/multisig-move) on GitHub.
