Uma Auditoria – Fase 6 PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Uma Auditoria - Fase 6

Uma Auditoria – Fase 6 PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Introdução

UMA é uma plataforma que permite aos usuários celebrar contratos financeiros com confiança minimizada no blockchain Ethereum. Nós auditamos anteriormente o oráculo descentralizado, um modelo específico de contrato financeiro, algumas solicitações pull ad hoc, o modelo multipartidário perpétuo, várias solicitações pull incrementais em um envolvimento mais longo e a ponte segurada.

Nesta auditoria, revisamos uma nova proposta de contrato de governança, um mecanismo para estender o ecossistema UMA em múltiplas cadeias, um mecanismo para distribuir recompensas aos detentores de tokens ERC721 de acordo com uma especificação fora da cadeia e uma atualização da ponte segurada para apoiar WETH na cadeia do Otimismo.

O commit auditado é 0c4cea3c3d5e48da6f8984b8ba3afdfea4ce47cc e o escopo inclui os seguintes contratos:

  • oracle/implementation/Proposer.sol
  • cross-chain-oracle/* (excluindo contratos de teste e Polygon)
  • financial-templates/optimistic-rewarder/* (excluindo contratos de teste)

Também revisamos as alterações nos arquivos de solidez em Solicitação pull 3611.

Todo código externo e dependências de contrato foram assumidas para funcionar conforme documentado.

Visão geral do sistema

A corrente Governance O contrato permite que a Risk Labs Foundation proponha novas ações de governança que possam ser ratificadas pelos detentores do token UMA. O novo Proposer O contrato pretende assumir o papel de proponente, permitindo que qualquer pessoa faça novas propostas, desde que forneça um vínculo que será sacrificado caso a proposta fracasse. Não há incentivo específico para apresentação de propostas. A intenção é garantir que apenas serão propostas as acções que têm grande probabilidade de serem aceites.

O novo mecanismo cross-chain permite que a proposta de governança seja passada da rede principal Ethereum para as cadeias Optimism e Arbitrum. Desta forma, o mecanismo de governança UMA na camada 1 pode ser usado para governar contratos UMA nas cadeias de camada 2 suportadas. O mecanismo também permite que solicitações de preços e resoluções sejam encaminhadas entre as camadas, de modo que os Oráculos Otimistas nas cadeias da camada 2 possam ser protegidos pelo Mecanismo de Verificação de Dados da rede principal da mesma forma que o Oráculo Otimista da camada 1 é protegido pelo DVM.

É importante notar que essas mensagens são enviadas utilizando a mecânica de ponte nativa, o que significa que são limitadas pelas características das cadeias relevantes da camada 2. Em particular, as mensagens da camada 2 para a camada 1 podem levar uma semana ou mais para transitar pela ponte. Além disso, o mecanismo de governança UMA suporta propostas que incluem múltiplas transações ordenadas, mas isto apenas restringe a ordem em que podem ser adicionadas à ponte. É possível que algumas dessas transações sejam executadas em uma ordem diferente, ou nem sejam executadas, na camada 2.

O contrato do Optimistic Rewarder simplesmente emite tokens ERC721 para qualquer pessoa que os solicite. Também permite que qualquer pessoa associe dados arbitrários a qualquer token e deposite vários tokens ERC20 para serem distribuídos como recompensas. A interpretação dos dados arbitrários e a distribuição esperada de recompensas entre os detentores de tokens são determinadas usando um procedimento fora da cadeia não especificado. Qualquer um pode alegar que um token ERC721 específico deve um conjunto de recompensas se estiver disposto a depositar um título. O mecanismo padrão da Optimistic Oracle é usado para permitir que outra pessoa conteste a reivindicação, que será resolvida pelo DVM. As reivindicações que não são contestadas a tempo são consideradas válidas e o contrato distribui as recompensas de acordo. A única restrição (para simplificar a contabilidade) é que o token Oracle Bond não pode ser usado como token de recompensa.

Por último, PR3611 modifica o mecanismo de ponte segurada para evitar o envio de WETH através da ponte de token Optimism, que não é suportada. Em vez disso, qualquer L2 WETH depositado na caixa de depósito do Optimism é desembrulhado para L2 ETH antes de transitar pela ponte. Na camada 1, o ETH é convertido em WETH antes de ser encaminhado para o pool de pontes WETH.

Gravidade crítica

[C01] Não é possível contestar recompensa inválida

Ao contestar um pedido de recompensa, o OptimisticRewardBase contrato primeiro aciona uma proposta na SkinnyOptimisticOracle e depois contesta essa proposta. No entanto, a proposta define o tempo de expiração como uma compensação do tempo atual (disputa), enquanto a disputa especifica a expiração como uma compensação a partir do momento da solicitação de recompensa original. Na maioria dos casos, esta discrepância impedirá que o oráculo identifique a proposta a ser contestada, o que significa que disputas válidas não serão processadas e solicitações de recompensa inválidas serão aceitas.

Considere atualizar a invocação de disputa para especificar corretamente a proposta a ser contestada.

Update: Corrigido a partir do commit 9e15557 in PR3690.

[C02] Resolver propostas repetidamente

A resolveProposal função do Proposer contract simplesmente valida que o oráculo resolveu, mas não verifica se o título foi distribuído. Isso significa que a mesma proposta pode ser resolvida várias vezes, resultando em pagamentos duplicados de títulos. Considere sinalizar ou excluir propostas existentes quando elas forem resolvidas.

Update: Corrigido a partir do commit b152718 in PR3689.

Alta gravidade

Nenhum.

Gravidade média

[M01] Parâmetros de evento incorretos

A OptimisticRewarderBase contrato define um Requested evento que é emitido pelo requestRedemption funcionar quando um resgate é solicitado. Este evento é definido para emitir o prazo de vencimento do resgate como seu último parâmetro. No entanto, quando o evento é emitido, seu último parâmetro está configurado incorretamente para o hora atual.

Da mesma forma, o Redeemed evento lê o tempo de expiração após a exclusão do registro, portanto, será definido incorretamente como zero.

Dado que este evento pode ser usado para desencadear cálculos fora da cadeia, considere atualizar o valor emitido de forma adequada.

Update: Corrigido a partir do commit f04eef9 in PR3694.

Baixa gravidade

[L01] Falta de emissão de evento após disputa de resgate

A OptimisticRewarderBase contrato define um Disputed evento que se destina a ser acionado se um resgate for contestado. No entanto, este evento não é emitido dentro ou fora do OptimisticRewarderBase contrato.

Considere emitir o evento depois que alterações sensíveis ocorrerem no dispute função, para facilitar o rastreamento e notificar os clientes fora da rede após a atividade dos contratos.

Update: Corrigido a partir do commit c275e92 in PR3695.

[L02] Guarda de reentrada inconsistente

A Optimism_ParentMessenger e Arbitrum_ParentMessenger contratos aplicam inconsistentemente o nonReentrant modificador. Considere incluí-lo em todas as funções públicas.

Update: Corrigido a partir do commit 6275c39 in PR3677.

[L03] Comentários enganosos

Aqui estão alguns comentários enganosos que identificamos durante nossa análise:

  • ChildMessengerConsumerInterface.sol:
    • Linha 5 diz “mensageiro dos pais” em vez de “mensageiro das crianças”
  • GovernorSpoke.sol:
    • Linhas 49-51 links para um Gnosis arquivo, mesmo que o comentário diga que o snippet foi copiado de Governor.sol. Além disso, o snippet não é idêntico ao do Governor.sol

Update: Corrigido a partir do commit cc350f9 in PR3678.

[L04] Carimbo de dados auxiliares ausente

Ao solicitar um preço no OracleSpoke contrato, os dados auxiliares fornecidos está carimbado com o identificador da cadeia filho. No entanto, o hasPrice e getPrice funções não carimbam os dados auxiliares ao identificar a solicitação de preço. Isto obriga os contratos convocatórios a aplicarem eles próprios o selo, o que provoca uma inconsistência entre os mecanismos de solicitação de preços e de recuperação de preços. Considere aplicar o carimbo no hasPrice e getPrice funções.

Update: Corrigido a partir do commit fdb845d in PR3668.

[L05] Parâmetro NatSpec ausente

Muitas funções no OptimisticRewarderBase contract estão faltando o @return parâmetro em seus comentários de Especificação Natural. Considere incluí-lo para completar.

Update: Corrigido a partir do commit 8920f38 in PR3679.

[L06] Subsídio residual

Para invocar o Oráculo Otimista, o OptimisticRewarderBase contract concede-lhe um subsídio simbólico, para que possa retirar os pagamentos dos títulos. Se a proposta falhar, o resgate da recompensa foi cancelado mas o subsídio não é zerado. Portanto, o Oráculo Otimista reterá uma margem residual desnecessária até a próxima vez que uma disputa for desencadeada. Considere revogar o subsídio se a proposta falhar.

Update: Corrigido a partir do commit c2d444b in PR3698.

[L07] Endereço de reembolso inválido

O endereço L2 de reembolso do Arbitrum_ParentMessenger é inicializado ao proprietário do contrato, que deverá ser o Governador L1. Da mesma forma, o setRefundL2Address tem um comentário afirmando que deveria ser entregue ao governador. Entretanto, ao passar mensagens pela ponte, esse valor é definido como usuário L2, que é o endereço no Arbitrum que recebe o excesso de fundos após a resolução do ticket. Como o endereço do governador L1 não estará acessível no Arbitrum, quaisquer fundos enviados para este endereço serão perdidos.

Considere configurá-lo para um endereço L2 válido.

Update: Corrigido a partir do commit b3f2dd1 in PR3687.

[L08] Mecanismo para mudar mensageiros infantis

A GovernorSpoke e OracleSpoke cada contrato inicializa o mensageiro filho no construtor, sem nenhum mecanismo para atualizá-lo. Isto significa que quando o mensageiro infantil foi alterado, ambos os contratos falados tornam-se obsoletos.

Como os contratos dos raios são provavelmente mais estáveis ​​que os mensageiros, considere incluir um mecanismo para atualizar o mensageiro nos raios.

Update: Corrigido a partir do commit 7c9e061 in PR3688.

Notas e informações adicionais

[N01] Alterar token de título

A Proposer contrato inclui um mecanismo para o proprietário alterar o tamanho do título da proposta. Considere se eles também deveriam poder alterar o token do título. Observe que isso exigiria um mecanismo para identificar a moeda correta dos títulos quando as propostas existentes fossem resolvidas.

Update: Não é um problema. Declaração da UMA para este problema:

N01 recomenda permitir que o contrato proponente altere o token do título para algo diferente de UMA. Não temos intenção de oferecer suporte a nenhum token diferente de $UMA para esta função e, portanto, optamos por não fazer nenhuma alteração para esse problema. Além disso, um único token por contrato mantém esta lógica o mais simples possível. Por último, se fosse necessária uma mudança (no caso de uma migração de token, por exemplo), poderíamos simplesmente implantar um novo contrato de proponente com o outro token e iniciar uma proposta para migrar o sistema para usá-lo.

[N02] Interface incompleta

A ChildMessengerInterface não especifica um processMessageFromCrossChainParent função, mesmo que seja assumido que exista pelos mensageiros pais. Considere incluí-lo para completar.

Update: Não consertado. Declaração da UMA para este problema:

Optamos intencionalmente por deixar esta interface inconsistente, pois implementá-la dentro do ChildMessengerInterface quebra a compatibilidade com o Polygon_ChildMessenger, pois o método do Polygon para processar mensagens de outras cadeias requer uma lógica personalizada em que um método interno é chamado _processMessageFromRoot.

[N03] Interface incorreta

A GovernorSpoke contratar incorretamente utiliza o ChildMessengerConsumerInterface tipo para descrever seu messenger variável. Considere usar o ChildMessengerInterface ao invés.

Update: Corrigido a partir do commit f31a527 in PR3680.

[N04] Extrair tokens para armazenar

Em um artigo do auditoria anterior questionamos o propósito do Store contrato payOracleFeesErc20 função (na edição L19). A equipe UMA optou por manter a função para padronizar a interface para possíveis modificações futuras. Como a finalidade da função não está totalmente especificada, não está claro se ela deve ser acionada quando o Proposer contract confisca um título. Provavelmente deve ser usado quando o OracleHub paga por uma solicitação de preço. Considere se a função deve ser usada em qualquer um dos cenários.

Update: Reconhecido. Declaração da UMA para este problema:

N04 recomenda usar o método payOracleFeeErc20 da Loja para pagar taxas nos contratos do Proponente e do OracleHub para ser consistente com o uso da Loja. Optamos por não usar esta função, pois isso significaria a necessidade de importar uma interface adicional (para a loja) e exigir a conversão do valor do título para um FixedPoint (o que também exigiria uma importação adicional. Para manter o código simples e limpo optamos por não fazer isso. O feedback da OZ sobre payOracleFeeErc20 na fase de auditoria 1 em abril de 2020 foi válido, pois esse método não é realmente útil, tornando esse tipo de integração mais difícil de raciocinar.

[N05] TODOs no código

Existem comentários “TODO” na base de código que devem ser rastreados no backlog de problemas do projeto. Por exemplo:

  • Line 37 of Arbitrum_ParentMessenger contract
  • Line 25 of Optimism_ChildMessenger contract
  • Linhas 83 e 146 of OracleHub contrato.

Durante o desenvolvimento, ter comentários “TODO” bem descritos facilitará o processo de rastreamento e solução deles. Sem essas informações, esses comentários podem tender a apodrecer e informações importantes para a segurança do sistema podem ser esquecidas no momento em que são liberadas para produção.

Esses comentários TODO devem conter uma breve descrição da tarefa pendente e um link para o problema correspondente no repositório do projeto.

Considere atualizar os comentários TODO para adicionar essas informações. Para integridade e rastreabilidade, uma assinatura e um carimbo de data/hora podem ser adicionados. Por exemplo:

// TODO: point this at an interface instead.

// https://github.com/UMAprotocol/protocol/issues/XXXX

// --mrice32 - 20211209

Update: Corrigido a partir do commit 5d57b5b in PR3684.

[N06] Erros tipográficos

A base de código contém os seguintes erros tipográficos:

  • No Admin_ChildMessenger contrato, impleenting deveria estar implementing
  • No OptimisticRewarderBase contrato, timestap deveria estar timestamp.
  • No OptimisticRewarderBase contrato, liveness liveness deveria estar liveness.
  • No GovernorSpoke contrato, only called deveria estar only be called.
  • No Optimism_ChildMessenger contrato:

Update: Corrigido a partir do commit 9b92b0b in PR3681.

[N07] Importações não utilizadas

Para melhorar a legibilidade do código, considere remover as seguintes importações não utilizadas:

Update: Corrigido a partir do commit 40b7221 in PR3682.

[N08] Pedido de transação L2

A Governor garante as transações dentro de uma proposta são executadas em ordem. No entanto, quando essas transações envolvem transações entre cadeias, isso apenas garante que cheguem ao contrato da ponte L1 na ordem correta. No caso Arbitrum, eles podem ser reordenados antes de serem finalizados em L2. Portanto, as propostas de governança devem ser construídas para permitir a possibilidade de transações L2 reordenadas.

Update: Corrigido a partir do commit 0fb2e7b in PR3703. O GovernorHub agora pode retransmitir uma série de transações L2.

Conclusão

Dois problemas críticos foram encontrados na base de código. Um problema de gravidade média e várias vulnerabilidades menores foram encontrados, e foram sugeridas recomendações para correções.

Fonte: https://blog.openzeppelin.com/uma-audit-phase-6/?utm_source=rss&utm_medium=rss&utm_campaign=uma-audit-phase-6

Carimbo de hora:

Mais de Zepelim aberto