Back to Blog

Protegendo o Ecossistema Solana (6) — Multi-Sig2

24 de abril de 2022
6 min read

0. Revisão

1. Visão Geral

No post anterior, discutimos a implementação do Multi-Sig. No entanto, a implementação pressupõe que as assinaturas de múltiplos usuários podem ser coletadas ao mesmo tempo fora da cadeia. Neste post, apresentamos um programa Multi-Sig mais geral que permite aos usuários assinar totalmente na cadeia.

2. Design do Programa de Teste

O programa multi-sig permite que assinantes válidos assinem a proposta separadamente, e qualquer pessoa pode executar a proposta assim que ela for aprovada (assinaturas suficientes forem coletadas). Todo o código de teste pode ser encontrado aqui.

3. Revisão de Código

Este programa apresenta mais duas structs: TransactionAccount e Transaction. A struct TransactionAccount foi projetada para registrar as informações de conta utilizadas na transação proposta. A struct Transaction é usada para registrar as informações de uma proposta. Observe que o atributo signers é usado para registrar o número de assinaturas válidas. did_execute e is_initialized garantem que a execução e a inicialização só possam ser realizadas uma única vez.

O programa fornece cinco instruções diferentes. A instrução AllocatePDA tem como objetivo criar uma conta PDA única e utilizá-la como a conta multisig. Ela registrará todas as informações dos assinantes válidos. Na instrução InitializeMultisig, definimos o número de assinaturas necessárias para executar a instrução, bem como o array de chaves públicas dos assinantes válidos. A instrução CreateTransaction é usada para criar uma proposta, enquanto o assinante pode aprovar a proposta por meio da instrução approve. Assim que o número de aprovações atingir o limiar definido em multisig, a instrução ExecuteTransaction pode ser invocada para executar a transação.

Para submeter uma proposta, os usuários podem invocar a instrução createTransaction(). Ela recebe três contas: a conta transaction criada e as duas contas seguintes são usadas pela transação alvo. Para evitar que a conta seja reinicializada por usuários mal-intencionados, verificamos o atributo is_initialized (linhas 161-163). Em seguida, inicializamos a struct TransactionAccount com os dados especificados e a serializamos na conta de dados (linha 188).

Na função Approve(), verificamos primeiro se a conta Transaction e a conta multisig são de propriedade do programa. Observe que contas criadas por outros programas podem ser usadas por usuários mal-intencionados aqui, caso não haja verificação. Em seguida, comparamos a chave pública do assinante com as chaves armazenadas na conta multisig. Se houver correspondência, a assinatura será validada e o valor será alterado para true correspondentemente.

Na instrução ExecuteTransaction(), contamos o número de assinaturas válidas. Se o número não atingir o limiar, o programa será revertido.

Em seguida, inicializamos a Instruction alvo com os atributos especificados e invocamos a instrução do programa alvo por meio da função invoke_signed(). Por fim, definimos o atributo did_execute como verdadeiro para evitar que a proposta seja executada repetidamente.

Implantamos o programa na testnet e ele pode ser encontrado no seguinte link.

https://explorer.solana.com/address/CPzn7ptnJntjUB4NGKqQGRai8NFLNwFaspmJ7nEGbMHe?cluster=testnet

4. Enviar Transação

Após a implantação, criamos primeiro a conta multisig e a definimos como administradora da conta config ao inicializá-la. As transações relacionadas são mostradas abaixo, e a ordem é: createMultisig() (em General-Multisig) -> Implantar programa PriviligeOwner -> Allocate() (em PrivligeOwner) -> InitializeConfig() (em PrivligeOwner).

https://explorer.solana.com/tx/2vXHmwbCsARstx8wi4eLACbrb6PuZZMktsqU8VnJLp64fvrpaE62QSTn5QLczzxnTvxRLWMSR3dKLGYXZasGMn69?cluster=testnet
https://explorer.solana.com/tx/2EMq9y6HNnXq1n2XsqrBkJd8RGL27PCj5T4JyJ71ZoA3ipUggT6dF6S6uDv4TtxGGKk8BmiAJHS7BFRgZqWjkWVb?cluster=testnet
https://explorer.solana.com/tx/3UhXKsTubUiPqRtLyNYskxvbyrTKHsbeptxuAfJQ348AU4b8gQET2HAMaqxwud6Wo3MKTYHWBneqa9z2WhCpwV6t?cluster=testnet
https://explorer.solana.com/tx/5NA7Yw23uRf48Q3BYM21dtS7gD9YMECij43ZaRLMPe7svt3bsv2TPWwbCRP5akDmttjLEHWZtpqrZrVLNr9QLyJY?cluster=testnet

Em seguida, invocamos a instrução InitializeMultisig(). Passamos quatro contas: a conta multisig e as contas de três assinantes válidos. Definimos o valor de m como 2, o que significa que as assinaturas de dois dos três assinantes são necessárias para executar funções privilegiadas.

Na função CreateTransaction(), passamos a conta Transaction criada, a chave pública do programa alvo (PrivilegeOwner) e a chave pública da conta config (linha 306 - linha 307). Além disso, também devemos definir _data como 3, o que corresponde à instrução unlock() no programa PrivilegeOwner.

No primeiro teste, apenas um assinante aprova a proposta criada. Nesse caso, ExecuteTransaction() falha, pois assinaturas insuficientes foram coletadas. O console exibe a seguinte saída.

Outro assinante aprova a proposta criada e invoca ExecuteTransaction(). O número total de assinaturas atingiu o limiar, de modo que a proposta pode ser executada com sucesso.

https://explorer.solana.com/tx/55Qy93RxybsT7c5v9AFgN8Dt1h3AVJfbsosLbstYVB6paY1wmau5sdtLfGpfryXnZTsBNRauvwLSmAu2nABFxVCe?cluster=testnet
https://explorer.solana.com/tx/4XF4MUhL4oftkDt4sn7NoREmGqcDMVP6HGypvJQMtiAbBKiCuy4B98vhQKtvm4mPv7SprrDDVsiwgb6pNwgJcTwz?cluster=testnet

4. Resumo

Neste artigo, apresentamos a implementação geral do multisig no Solana. A implementação faz uso do recurso de PDA, que permite ao programa assinar a transação por meio do PDA automaticamente quando o número de assinaturas válidas atende ao requisito. Continue acompanhando, e compartilharemos mais nos próximos posts.

Leia outros artigos desta série:

Sobre a BlockSec

A BlockSec é uma empresa pioneira em segurança de blockchain, fundada em 2021 por um grupo de especialistas em segurança de renome mundial. A empresa está comprometida em aprimorar a segurança e a usabilidade para o emergente mundo Web3, a fim de facilitar sua adoção em massa. Para isso, a BlockSec oferece serviços de auditoria de segurança de contratos inteligentes e cadeias EVM, a plataforma Phalcon para desenvolvimento de segurança e bloqueio proativo de ameaças, a plataforma MetaSleuth para rastreamento e investigação de fundos, e a extensão MetaSuites para construtores web3 que navegam com eficiência no mundo cripto.

Até o momento, a empresa atendeu mais de 300 clientes renomados, como MetaMask, Uniswap Foundation, Compound, Forta e PancakeSwap, e recebeu dezenas de milhões de dólares em duas rodadas de financiamento de investidores proeminentes, incluindo Matrix Partners, Vitalbridge Capital e Fenbushi Capital.

Site oficial: https://blocksec.com/

Conta oficial no Twitter: https://twitter.com/BlockSecTeam

Sign up for the latest updates
Como a solução de segurança de pagamentos da BlockSec ajuda instituições a se manterem seguras na era da IA
Security Services

Como a solução de segurança de pagamentos da BlockSec ajuda instituições a se manterem seguras na era da IA

Descubra como a BlockSec ajuda instituições de pagamento a proteger recursos financeiros e dados, além de fortalecer sua resiliência por meio de avaliações de segurança, testes e monitoramento contínuo.

Perdas de ~5,57 milhões USD: exploração de falhas no X100 Freezer e no NEM | Boletim semanal da BlockSec
Security Insights

Perdas de ~5,57 milhões USD: exploração de falhas no X100 Freezer e no NEM | Boletim semanal da BlockSec

Este relatório semanal aborda dois incidentes de segurança na Ethereum e na BNB Chain no período de 19/10/2026–25/10/2026. Ele examina uma tomada de controle da governança do X100 Freezer financiada por um empréstimo-relâmpago e uma falha na liquidação de impostos que afetou um pool de liquidez de um token NEM na BNB Chain. As perdas estimadas no escopo do relatório totalizam aproximadamente 5,57 milhões USD: cerca de 4,75 milhões USD da transação representativa do X100 e cerca de 820 mil USD do incidente no pool do NEM. O total exclui as extrações subsequentes do X100 relatadas separadamente.

Perdas de ~3,87 milhões USD: ataques à Autheo Network e à UNCX | Resumo semanal da BlockSec
Security Insights

Perdas de ~3,87 milhões USD: ataques à Autheo Network e à UNCX | Resumo semanal da BlockSec

Este relatório semanal aborda 3 incidentes de segurança no período de 12/10/2026–18/10/2026, com perdas totais estimadas em aproximadamente 3,87 milhões USD. A Autheo Network sofreu um comprometimento de chave privada com perdas de cerca de 1,76 milhões USD, a Qubic Wallet perdeu cerca de 1,30 milhões USD devido à geração de seeds fracas, e os contratos Smart Token Vesting V2 da UNCX Network sofreram um erro contábil de cerca de 807 mil USD nas redes Ethereum, BNB Chain, Base e Robinhood Chain. A análise em destaque da UNCX explica como um cálculo incorreto do total de cotas misturou parcelas de vesting criadas com diferentes proporções entre tokens e cotas, permitindo saques acima do devido de pools compartilhados.