BDS
smart-contracts, security-audits, ethereum-solidity

Atualizando contratos inteligentes por meio de padrões de proxy: um guia completo

February 23, 2026
12 min
c
Arquitetura do padrão proxy mostrando a interação entre o contrato proxy, o contrato de implementação e as interfaces de utilizador

Introdução

Os contratos inteligentes são programados para serem permanentes e imutáveis depois de serem implementados numa rede blockchain. Essa imutabilidade é uma fonte de segurança e confiança, mas também apresenta desafios quando os programadores precisam corrigir bugs ou adicionar novos recursos.

Quando são necessárias modificações, os programadores têm de lançar um contrato completamente novo com um endereço diferente. Embora essa permanência seja ótima para a segurança, ela pode ser limitante em situações em que as coisas dão errado ou precisam ser melhoradas.

A história mostra que as vulnerabilidades dos contratos inteligentes podem resultar em perdas financeiras catastróficas. Um exemplo específico é um incidente grave que causou a perda de milhões de dólares devido a uma falha explorável.

Esses incidentes mostram como é importante poder resolver problemas de segurança e bugs depois da implementação. Tornar os contratos atualizáveis permite um mecanismo para corrigir problemas sem perder o estado atual e a experiência do utilizador, o que é um aspecto fundamental da atualizabilidade dos contratos inteligentes.

Essa capacidade pode ser importante para evitar perdas significativas e preservar a integridade do sistema.

Existem várias maneiras de implementar contratos inteligentes atualizáveis, como padrões de proxy de contratos inteligentes e técnicas de separação de dados. Este artigo é especificamente sobre como implementar a atualizabilidade usando padrões de proxy, que é uma maneira popular de resolver isso no espaço de desenvolvimento de blockchain.

Entendendo o padrão proxy

O padrão proxy é um padrão de design estrutural em que um contrato implementa uma interface para outro contrato. Essa arquitetura tem duas partes principais: o contrato proxy e o contrato de implementação.

Em vez de o utilizador comunicar diretamente com o contrato de implementação, ele vai comunicar com o contrato proxy, que vai passar as solicitações conforme necessário.

Nesta configuração, tanto o contrato proxy como o contrato de implementação não são alterados após serem implementados. No entanto, a capacidade de atualização é alcançada ao permitir que o proxy se refira a diferentes contratos de implementação ao longo do tempo.

Isso significa que os utilizadores podem continuar a usar o mesmo endereço e interface enquanto a funcionalidade subjacente é atualizada. Do ponto de vista do utilizador, a aplicação continua a funcionar perfeitamente, mesmo que a lógica de back-end mude.

O contrato proxy é responsável pelas interações do utilizador e pelo armazenamento de todos os dados. Ele mantém o endereço do contrato de implementação num local de armazenamento especial.

Quando os utilizadores chamam funções no contrato proxy, uma função de fallback é chamada. A função a seguir usa um mecanismo delegatecall ethereum para invocar o código do contrato de implementação, mas quaisquer alterações de estado são guardadas no armazenamento do contrato proxy.

Principais implementações de padrões de proxy

Padrão de proxy transparente

O padrão Transparent Proxy coloca a funcionalidade de atualização no próprio contrato proxy. O proxy tem um método upgradeTo que é usado para atualizar o endereço que aponta para o contrato de implementação.

Isso apresenta um problema potencial: se tanto o contrato proxy quanto o contrato de implementação contiverem um método upgradeTo, não fica claro qual deles deve ser chamado quando um utilizador invocar essa função.

Para resolver essa ambiguidade, foi criada uma solução em que a decisão sobre a quem delegar é baseada em quem está a chamar o contrato.

Se o chamador for o administrador do proxy, as chamadas são tratadas pelo próprio contrato do proxy. Caso contrário, as chamadas são delegadas ao contrato de implementação. Essa abordagem garante que as funções sejam executadas de forma clara e que não haja confusão entre as operações administrativas e as operações regulares do utilizador.

Padrão universal de proxy atualizável

O Padrão Universal de Proxy Atualizável tem uma abordagem diferente, colocando a funcionalidade de atualização no contrato de implementação, e não no proxy. O proxy delega todas as chamadas para o contrato de implementação, que tem o método upgradeTo para apontar para versões mais recentes.

Esse padrão dá aos programadores mais controlo sobre o caminho de atualização. Se um programador decidir não incluir mais o método upgradeTo numa versão futura, o contrato agora é permanentemente imutável e não pode ser atualizado mais.

Isso pode ser útil quando um contrato foi bem testado e a equipa de desenvolvimento quer congelá-lo no seu estado final.

Como a lógica de atualização está no contrato de implementação, não há necessidade da função de fallback do proxy verificar se o chamador é um administrador antes de delegar chamadas.

Isso torna o padrão mais eficiente em termos de gás do que o Padrão de Proxy Transparente. O potencial conflito de nomenclatura também é eliminado, uma vez que o método upgradeTo só existe no contrato de implementação.

Padrão de proxy de beacon

O padrão Beacon Proxy apresenta uma arquitetura de três componentes: o contrato proxy, um contrato beacon e o contrato de implementação. Em vez de guardar o endereço da implementação, o proxy guarda o endereço do contrato beacon.

O contrato beacon, por sua vez, contém o endereço do contrato de implementação.

Quando um utilizador chama o proxy, primeiro ele obtém o endereço do contrato do beacon e, em seguida, chama o beacon para obter o endereço do contrato de implementação. Por fim, ele deixa a chamada para o contrato de implementação.

Essa camada extra de indireção tem um objetivo bem específico.

Esse padrão é especialmente útil quando vários contratos proxy precisam usar a mesma implementação. Em padrões mais simples, para atualizar a implementação, seria necessário atualizar o endereço em cada contrato proxy individualmente. Com o padrão beacon, apenas o contrato beacon precisa ser atualizado e todos os proxies associados a ele apontam automaticamente para a nova implementação.

Principais implementações de padrões de proxy

Padrão Diamond Proxy

O padrão Diamond Proxy resolve o problema da limitação de tamanho dos contratos inteligentes, que geralmente são limitados a cerca de 24 kilobytes. Esse padrão separa a funcionalidade em vários contratos menores, conhecidos como facetas.

O contrato proxy mantém um mapeamento entre os seletores de função e o endereço das facetas que contêm essas funções.

Quando uma função é chamada no proxy, ele usa o seletor de função para procurar a faceta que contém a função e delega a chamada da função para a faceta apropriada.

As atualizações são feitas modificando os endereços das facetas no proxy. Esse padrão permite uma funcionalidade total muito maior, distribuindo a funcionalidade por vários contratos, com cada faceta permanecendo abaixo do limite de tamanho.

Comparando abordagens de padrões proxy

Cada padrão de proxy tem características diferentes que o tornam adequado para diferentes casos de uso. Todos os quatro padrões precisam de um contrato de proxy e usam delegação para encaminhar chamadas para contratos de implementação.

O padrão Proxy Transparente localiza funções de atualização no contrato proxy e o UUPS localiza funções de atualização no contrato de implementação. O padrão Beacon coloca a capacidade de atualização no seu próprio contrato beacon e o padrão Diamond normalmente coloca a capacidade de atualização nos contratos de implementação, mas não especificado de forma rigorosa.

No que diz respeito à imutabilidade, os padrões UUPS e Diamond podem tornar os contratos permanentemente imutáveis, removendo a função de atualização de versões futuras. Os padrões Transparent e Beacon não oferecem essa flexibilidade.

Ao lidar com vários proxies, o padrão Beacon tem uma vantagem definitiva. Com os padrões Transparent, UUPS e Diamond, cada proxy precisa ser alterado individualmente ao implementar uma nova implementação.

Com o padrão Beacon, só o contrato do beacon precisa ser atualizado, e todos os proxies vão usar automaticamente a nova implementação.

A eficiência de gás é diferente para cada padrão. O padrão Transparente exige que verifique se o chamador é um administrador antes de cada delegação, por isso é mais caro.

O UUPS é mais eficiente, pois não requer essa verificação. Todos os padrões, exceto o Diamond, têm custos adicionais de gás devido às operações de pesquisa extras.

Todos os padrões, exceto o Diamond, estão limitados a 24 kilobytes por contrato. O padrão Diamond permite que cada faceta tenha até 24 kilobytes, o que possibilita uma funcionalidade total muito maior em várias facetas.

Domine a segurança dos contratos inteligentes

Aprenda técnicas avançadas para criar contratos seguros e atualizáveis com os nossos cursos ministrados por especialistas.

Considerações importantes e riscos

Problemas de colisão de armazenamento

As colisões de armazenamento são um risco sério ao implementar padrões de proxy. As variáveis do contrato são armazenadas em slots de armazenamento específicos e, se as variáveis do contrato proxy e as variáveis do contrato de implementação forem armazenadas nos mesmos slots de armazenamento, elas vão interferir umas nas outras.

Além disso, se a ordem das variáveis no contrato de implementação mudar de uma versão para a outra, os slots de armazenamento podem ser reatribuídos, causando corrupção de dados.

Contratos de implementação não inicializados

Os contratos de implementação devem ser inicializados exatamente uma vez por meio de uma função de inicialização, que é um conceito semelhante a um construtor em contratos tradicionais.

Os programadores também se esquecem de inicializar a implementação ou não incluem proteções para impedir que a função de inicialização seja chamada mais de uma vez.

Quando isso acontece, os atacantes podem invocar a função de inicialização e, potencialmente, assumir o controlo do contrato ou manipular o seu estado.

Incidentes de segurança no mundo real

Um programa de recompensa por bugs encontrou uma vulnerabilidade crítica nos contratos proxy do cofre, onde os contratos de implementação não foram inicializados corretamente. Essa falha poderia ter sido usada por um invasor para destruir o contrato de implementação, tornando os contratos proxy associados inúteis. Em outro incidente ocorrido em um determinado período de julho, os contratos inteligentes foram hackeados devido a uma vulnerabilidade no código de inicialização, no qual a função de inicialização poderia ser chamada várias vezes.

Abordagens alternativas para a atualizabilidade

Padrão de separação de dados

Uma alternativa aos padrões de proxy é a abordagem de separação de dados. Essa abordagem se baseia no uso de contratos separados para armazenamento e lógica. O contrato de lógica se comunica com o contrato de armazenamento para ler ou atualizar dados.

Embora seja possível substituir o contrato lógico por novas versões, o contrato de armazenamento é fixo e imutável. Isso oferece um modelo diferente de atualização que pode ser apropriado em algumas circunstâncias.

Camadas de verificação

Nenhum dos padrões de proxy comumente usados tem mecanismos para verificar se um novo contrato de implementação é válido antes da atualização ser feita.

É obrigatório que as novas versões incluam toda a lógica de negócio necessária, funções de fallback e outros componentes essenciais.

Isso pode ser feito introduzindo uma camada de verificação que acompanha a camada de proxy, a camada de lógica de negócios e a camada de armazenamento. Essa camada extra garante que as atualizações cumpram alguns critérios antes de serem permitidas.

Melhores práticas para contratos atualizáveis

Os programadores que estão a projetar contratos atualizáveis devem seguir algumas diretrizes importantes para garantir a segurança e a confiabilidade:

  • Em vez disso, confie em implementações bem testadas de bibliotecas bem testadas que foram cuidadosamente revisadas e auditadas
  • Certifique-se sempre de inicializar os contratos de implementação corretamente e certifique-se de que as funções de inicialização só possam ser chamadas uma vez
  • Nunca inicialize variáveis de estado na sua declaração ou num construtor, use a função de inicialização para toda a configuração de estado
  • Não altere a ordem ou os tipos de variáveis de estado ao criar novas versões de contratos de implementação
  • Se forem necessárias novas variáveis, elas devem ser adicionadas depois de todas as variáveis existentes
  • Para implementações do padrão Diamond, usa métodos de armazenamento especiais otimizados para esse padrão
  • O método UUPS é preferível ao padrão de proxy transparente, quando possível, porque requer menos gás para operações de rotina
  • Certifique-se de que a conta de administrador do proxy seja altamente segura, pois essa conta controla o processo de atualização e é um ponto crítico de segurança
  • Por fim, manda todos os contratos para uma auditoria profissional por especialistas experientes em segurança de contratos inteligentes antes de implementá-los

Considerações finais

Os padrões de proxy oferecem um mecanismo poderoso para atualizar contratos inteligentes, mantendo o mesmo endereço e estado. O contrato proxy usa delegateCall para passar a execução para contratos de implementação, de modo que a lógica subjacente possa ser alterada sem modificar a interface do utilizador.

No entanto, se os contratos atualizáveis não forem implementados corretamente, eles podem causar sérias vulnerabilidades de segurança.

Os programadores precisam considerar cuidadosamente as vantagens e desvantagens entre os diferentes tipos de padrões de proxy, aderir às melhores práticas estabelecidas e garantir que auditorias de segurança adequadas sejam realizadas para criar contratos inteligentes confiáveis, seguros e atualizáveis.

Comparação de padrões de proxy

Ao comparar qual padrão de proxy usar, há vários fatores que devem ser levados em consideração:

Comparação de padrões de proxy

RecursoTransparenteUUPSBeaconDiamante
Localização da atualizaçãoContrato de ProxyContrato de ImplementaçãoContrato BeaconContratos de implementação
Imutabilidade permanenteNãoSimNãoSim
Vários proxiesAtualizações individuaisAtualizações individuaisAtualização única do BeaconAtualizações individuais
Eficiência de combustívelCusto mais elevado (verificação administrativa)Custo mais baixoMédio (Pesquisa extra)Médio (Pesquisa por Faceta)
Limite de tamanho do contrato24 KB24 KB24 KB24 KB por Facet
Complexidade da implementaçãoMédioMédioMédioMédio

Considerações sobre a seleção de padrões

Considerações importantes para a seleção de padrões:

  • Todos os padrões precisam de um contrato proxy e usam delegação para passar chamadas
  • O padrão Transparent Proxy é usado para armazenar as funções de atualização no próprio contrato proxy
  • O UUPS coloca as funções de atualização no contrato de implementação
  • O padrão Beacon usa um contrato beacon separado para atualizações
  • O padrão Diamond geralmente coloca funções de atualização em contratos de implementação, mas a especificação não exige que isso seja feito
  • Apenas os padrões UUPS e Diamond têm a opção de tornar os contratos permanentemente imutáveis, removendo a função de atualização das versões futuras
  • O padrão Beacon é ideal se tiveres vários proxies para atualizar ao mesmo tempo, porque só o beacon precisa ser atualizado e não cada proxy
  • O tamanho máximo do contrato é de 24 kilobytes para os padrões Transparent, UUPS e Beacon
  • O padrão Diamond suporta cada faceta com um tamanho máximo de 24 kilobytes, pelo que é possível suportar uma funcionalidade total muito maior
  • Todos os padrões têm complexidade de implementação média e existem bibliotecas bem estabelecidas para os padrões Transparent, UUPS e Beacon

FAQ

#proxy patterns
#smart contract upgradeability
#blockchain security
BDS

Pioneiros no futuro da tecnologia blockchain com soluções inovadoras que capacitam empresas e indivíduos em todo o mundo.

+1 929 560 3730 (EUA)
+44 2045 771515 (Reino Unido)
+372 603 92 65 (Estônia)
Condado de Harju, Tallinn, Lasnamäe, Katusepapi tn 6-502, 11412, Estônia

Fique atualizado

Receba as últimas notícias de blockchain diretamente na sua caixa de entrada.