WEB3DEV

Cover image for Proxy — Padrão de Proxy Transparente e UUPS
Diogo Jorge
Diogo Jorge

Posted on

Proxy — Padrão de Proxy Transparente e UUPS

Para entender melhor os padrões de proxy, você deve saber como funciona o proxy. Se você não sabe, aqui é o meu post anterior explicando isso. Ok, agora vamos nos concentrar no assunto principal deste post.

Seletor de proxy conflitante

Todas as funções da interface pública dos contratos inteligentes são identificadas pelo identificador de 4 bytes. Como obter esse identificador, escrevi em meu post anterior sobre delegatecall.

São apenas 4 bytes, então são (2³)⁴ = 4096 combinações (porque 1 byte = 8 bits, e um bit pode ser definido como “1” ou “0”, então há apenas duas opções). Como vemos, o número de possibilidades do nosso seletor é pequeno e quando definirmos 4097 teremos 100% das funções com o mesmo seletor. Mas não precisa ter tantas funções definidas para ter um seletor que caiba em duas funções ao mesmo tempo. Esse problema é chamado de conflito do seletor de proxy.

Por que no nome desse problema vemos a palavra “proxy”, se isso poderia acontecer mesmo em um contrato inteligente comum que não usa proxy? A resposta é simples, neste contrato inteligente comum não teremos esse tipo de problema. É porque, a nova versão do compilador Solidity verifica se cada função tem identificador diferente, e, se não tiver, veremos um erro durante a compilação.

Então, se o compilador nos protege desse problema, por que nos incomodamos com isso? A chave é a estrutura do proxy. Quando criamos o proxy ou a lógica do proxy, compilamos apenas um deles. Então, o compilador não sabe que existe outro contrato e não pode nos proteger. Portanto, temos que nos proteger por nós mesmos.

Padrões de proxy

Portanto, o conflito do seletor de proxy é um problema que precisa de dois contratos inteligentes separados, porque em apenas um deles não teremos problema graças ao compilador. Vamos imaginar uma situação em que os contratos de proxy e de lógica tenham funções definidas com o mesmo nome e recebam o mesmo tipo de argumento. Portanto, se quisermos chamar essa função, haverá um problema sobre qual função ela deve usar. Normalmente, utilizará a função definida no contrato do proxy, pois a conexão com a lógica é pelo_ fallback_, que é chamado quando nenhuma outra função chama sendvalue. Portanto, nunca poderemos chamar essa função através do contrato da lógica. Claro, poderíamos de alguma forma escrever nosso contrato de proxy para usar essa função dentro da lógica, mas não poderemos usar este no proxy. Além disso, esta solução é complicada e inflexível. Portanto, existem outras soluções.

Padrão de Proxy Transparente

Este padrão usa msg.sender como uma chave cuja função será usada: a partir do proxy ou a partir da lógica. Se msg.sender for o endereço do administrador do proxy, nenhuma função será chamada pelo _delegatecall. _Se msg.sender não for igual ao endereço do administrador, então o proxy usará apenas _delegatecall, _e nenhuma outra função definida no proxy. Esta solução simples separa a lógica do proxy e, graças a isso, não temos um seletor de proxy em conflito.

UUPS (Padrão de Proxy Atualizável Universal)

O UUPS funciona de maneira semelhante ao padrão de proxy transparente. Usamos msg.sender como uma chave da mesma forma que no padrão explicado anteriormente. A única diferença é onde colocamos a função para atualizar o contrato da lógica: no proxy ou na lógica. No Transparent Proxy Pattern, a função a atualizar está no contrato do proxy, e a forma de alterar a lógica é a mesma para todos os contratos de lógica.

A logica é alterada no UUPS. A função de atualizar para nova versão é implementada no contrato da lógica, portanto, o mecanismo de atualização pode mudar ao longo do tempo. Além disso, se a nova versão da lógica não tiver o mecanismo de atualização, todo o projeto será imutável e não poderá ser alterado. Portanto, se você quiser usar esse padrão, deve ter muito cuidado para não tirar acidentalmente de si mesmo a opção de atualizar.

Espero que você ache este post útil. Se você tiver alguma ideia de como eu poderia melhorar minhas postagens, me avise. Estou sempre pronto para aprender. Você pode se conectar comigo no LinkedIn e Telegram.

Se você quiser conversar comigo sobre este ou qualquer outro tópico que escrevi, fique à vontade. Estou aberto para conversas.

Feliz aprendizado!

Este artigo foi escrito por Eszymi e traduzido por Diogo Jorge. O artigo original pode ser encontrado aqui.

Oldest comments (0)