How do multisig accounts work on Sui?
November 3, 2026
Multisig on Sui is built into the protocol; no smart contract is involved. You choose up to 10 public keys, give each a weight, and set a threshold. Hashing those values gives a normal-looking Sui address. A transaction from that address is valid when the members who signed have weights that add up to at least the threshold. Members can use Ed25519, Secp256k1 or Secp256r1 keys, and also zkLogin and passkey signers, in any mix.
The rules
From crates/sui-types/src/multisig.rs and the Sui docs:
- At most 10 members (
MAX_SIGNER_IN_MULTISIG = 10). - Weights are
u8(1–255) and the threshold is au16. - Valid when the sum of the weights of the members who signed is at least the threshold, and each member signs at most once.
- Address:
BLAKE2b-256(0x03 || threshold || flag_1 || pk_1 || weight_1 || ... || flag_n || pk_n || weight_n). The0x03is the multisig flag and the threshold is little-endian.
The address depends on every key, weight and threshold, and on their order. Change any of them and you get a different address. There is no "add a signer" operation; to rotate members, create a new multisig and move the assets to it.
Create and use one with the CLI
Get each member's Base64 public key (flag || pk) from sui keytool list, then derive the address:
sui keytool multi-sig-address \
--pks $PK_1 $PK_2 $PK_3 \
--weights 1 1 1 \
--threshold 2Fund that address, then build an unsigned transaction from it:
sui client transfer --to $RECIPIENT --object-id $OBJECT_ID \
--gas-budget 10000000 --serialize-unsigned-transactionEach member signs the printed transaction bytes with their own key:
sui keytool sign --address $MEMBER_1 --data $TX_BYTES
sui keytool sign --address $MEMBER_2 --data $TX_BYTESCombine the partial signatures. Pass the same --pks, --weights and --threshold in the same order. Then execute:
sui keytool multi-sig-combine-partial-sig \
--pks $PK_1 $PK_2 $PK_3 --weights 1 1 1 --threshold 2 \
--sigs $SIG_1 $SIG_2
sui client execute-signed-tx --tx-bytes $TX_BYTES --signatures $MULTISIGThe same thing in TypeScript
import { MultiSigPublicKey } from '@mysten/sui/multisig'
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519'
const a = Ed25519Keypair.generate()
const b = Ed25519Keypair.generate()
const c = Ed25519Keypair.generate()
const multisig = MultiSigPublicKey.fromPublicKeys({
threshold: 2,
publicKeys: [
{ publicKey: a.getPublicKey(), weight: 1 },
{ publicKey: b.getPublicKey(), weight: 1 },
{ publicKey: c.getPublicKey(), weight: 1 },
],
})
console.log(multisig.toSuiAddress())
// Each member signs the same transaction bytes
const sigA = (await a.signTransaction(txBytes)).signature
const sigB = (await b.signTransaction(txBytes)).signature
const combined = multisig.combinePartialSignatures([sigA, sigB])Send txBytes with combined as its signature through your client, for example SuiGrpcClient from @mysten/sui/grpc. If the multisig includes zkLogin members, pass client to fromPublicKeys so the SDK can verify them.
Patterns that work well
- Weighted control. With weights
1 2 3and threshold3, the weight-3 key can sign alone, and the other two must sign together. - Recovery for zkLogin or passkeys. A 1-of-2 multisig across two OAuth providers, or a passkey plus a hardware-wallet key, protects you against losing a single login.
- Admin capabilities. The Sui docs recommend holding privileged objects such as
AdminCapandUpgradeCapin a multisig rather than with one key. See What is an UpgradeCap, and what upgrade policies exist?.
Gotchas
- Gas. The multisig address pays for gas unless you use a sponsored transaction. Fund it before anyone signs.
- Object versions. Everyone has to sign the same bytes. If the gas coin or an input object changes in the meantime, rebuild the transaction and collect the signatures again.
- Keep the configuration. Store the member public keys, weights, threshold and their order somewhere safe. Without them you can't rebuild the multisig public key, and you need it to sign.
Sources
- Multisig, Sui documentation
- Sui CLI keytool reference, Sui documentation
crates/sui-types/src/multisig.rsandbase_types.rs, MystenLabs/sui