Whitepaper · 08
Estrutura de Segurança
Modelo de ameaças, invariantes, controle de acesso, o limite de confiança dos hooks, gestão das chaves de enforcement, segurança das atualizações e postura de auditoria da implementação de referência do A-REX Core.
A postura de segurança em um parágrafo
O token de referência tem um único ponto de passagem (_update), uma ordem fixa de avaliação, uma trava de reentrância em torno de toda a sequência de hooks, uma autoridade baseada em papéis que nunca deriva de saldos, armazenamento ERC-7201 e uma superfície pequena: oito funções externas que alteram estado, além das do ERC-1155. As capacidades mais poderosas — congelamento, transferência forçada, administração de hooks, atualizações — são papéis separados, destinados a multisigs e timelocks, e todo uso delas é um evento.
Invariantes
| Invariante | Garantido por | Testado por |
|---|---|---|
totalSupply(id) é igual à soma dos saldos de id | ERC1155Supply do OpenZeppelin; transform queima e depois cunha por meio de _update | testes de linhagem (divisão, união, processamento) |
status == 255 é terminal | setBatchStatus reverte com ARexInvalidStatusTransition | testes de status |
| Um lote baixado não pode ser cunhado nem transferido, apenas queimado | _update | teste de lote baixado |
amount ≤ balance − frozen para movimentações iniciadas pelo titular | _update; forcedTransfer reduz frozen para balance − amount | testes de congelamento/transferência forçada |
| Nenhum hook pode reentrar em uma função que altera saldos | trava de armazenamento definida antes das verificações e liberada depois das notificações | teste ReentrantHook |
| Os hooks são avaliados na ordem de registro; a remoção preserva a ordem | deslocamento do array em removeHook | teste de ordenação |
| Uma operação rejeitada não altera nenhum saldo e não emite nenhuma transferência | as verificações são executadas antes de super._update | teste de rejeição (contagem de execuções inalterada) |
| A autoridade nunca deriva do saldo | toda função que altera estado é protegida por papel ou por aprovação do ERC-1155 | testes "possuir tokens não confere nada" |
canTransfer == (transferCheck == 0) | canTransfer é definido dessa forma | testes de conformidade |
Modelo de ameaças
Atores e capacidades
| Ator | Pode | Não pode |
|---|---|---|
| Titular | transferir unidades não congeladas a destinatários elegíveis; queimar; reagrupar a mesma commodity/unidade com quantidade conservada | alterar o status, cunhar, processar em outra commodity, mover unidades congeladas |
| Operador aprovado | o mesmo que o titular, em relação à conta que o aprovou | qualquer coisa que um titular não possa |
ISSUER_ROLE | criar lotes | mover tokens de terceiros |
TRANSFORMER_ROLE | transformações de processamento de tokens que detém ou para os quais tem aprovação | transformar tokens sem aprovação |
STATUS_ROLE | alterar o status (inclusive dar baixa), atualizar metadados | mover tokens |
ENFORCER_ROLE | congelar qualquer quantidade; forçar qualquer transferência | contornar os hooks (eles são executados com OP_FORCED_TRANSFER) |
HOOK_ADMIN_ROLE | adicionar/remover hooks | alterar saldos diretamente |
PAUSER_ROLE | interromper tudo, exceto as transferências forçadas | — |
UPGRADER_ROLE | substituir a implementação | — (este é um poder total; ver gestão de chaves) |
| Contrato de hook | rejeitar operações; observá-las; responder sobre elegibilidade | reentrar; alterar saldos |
Cenários
Hook malicioso ou com defeito (negação de serviço). Um hook que sempre rejeita bloqueia todas as transferências do token; um que reverte em check faz o mesmo. Mitigação: HOOK_ADMIN_ROLE pode remover qualquer hook a qualquer momento (ordem preservada); PAUSER_ROLE pode interromper a operação durante a investigação; as transferências forçadas continuam sendo executadas, de modo que o enforcement não se perde. O registro verifica o suporte a ERC-165 e flags diferentes de zero, e rejeita EOAs. Recomendação: auditar os hooks antes de registrá-los; manter seu número pequeno; colocar a administração atrás de um timelock, para que as mudanças de hooks sejam visíveis antes de entrarem em vigor.
Reentrância de hook. O onExecuted de um hook chama de volta safeTransferFrom. Mitigação: a trava; a chamada reverte com ARexReentrantCall. Observe-se que o callback de recebimento do ERC-1155 (onERC1155Received) é executado depois de a trava ser liberada, como em todo token ERC-1155; o estado do token já é definitivo nesse momento.
Chave de enforcement comprometida. Quem detém ENFORCER_ROLE pode mover quaisquer tokens. Mitigação: multisig com um procedimento documentado (ordem judicial, contrato de penhor, notificação de sanções); toda ação emite ForcedTransfer/Frozen; os hooks podem exigir uma referência de ordem nos dados da transferência (OP_FORCED_TRANSFER não está isento dos hooks). Pode-se considerar um timelock para o enforcement não urgente.
Atualizador comprometido. Comprometimento total. Mitigação: multisig mais timelock; validações de atualização do OpenZeppelin na CI; armazenamento ERC-7201 para evitar acidentes de layout.
Abuso de status. STATUS_ROLE pode dar baixa em um lote detido por terceiros. Isso é intencional — um armazém, um inspetor ou um regulador declarando um lote impróprio — e deve ser divulgado aos titulares. Mitigação: atribuir a uma instituição responsável; toda mudança é um evento com um motivo.
Fraude do emissor. ISSUER_ROLE pode criar um lote que não existe fisicamente. O token não pode impedir isso; torna o fato atribuível (issuer, originRef, metadataHash) e permite exigir, antes da transferência, atestações de partes independentes (armazém, inspetor, registro) por meio de AttestationHook.
Substituição de metadados. setBatchMetadata altera o hash e a URI. Mitigação: protegida por papel; os eventos BatchMetadataUpdated e URI mantêm o histórico; documentos anteriores continuam verificáveis em relação aos hashes anteriores.
Front-running de transferCheck. Uma verificação prévia pode ficar desatualizada antes de a transação ser executada (o estado de um hook muda). A transação reavalia; o pior caso é uma reversão com um código preciso.
Gas griefing por meio de hooks. Cada hook acrescenta uma chamada externa por id afetado por fase. Um hook com laços ilimitados torna as transferências financeiramente inviáveis. Mitigação: regras de autoria de hooks (check limitado), revisão antes do registro.
Confiança em hooks atualizáveis. Um hook implantado atrás de um proxy pode mudar a política de transferência sem qualquer alteração no token. Mitigação: tratar as chaves de administração dos hooks com o mesmo cuidado dado a HOOK_ADMIN_ROLE; preferir hooks imutáveis em produção.
Modelo de controle de acesso
O AccessControl do OpenZeppelin, com oito papéis no token e um no registro de atestações; DEFAULT_ADMIN_ROLE administra todos eles. Disposição recomendada para produção:
| Papel | Titular |
|---|---|
DEFAULT_ADMIN_ROLE, UPGRADER_ROLE, HOOK_ADMIN_ROLE | multisig de governança atrás de um timelock |
ENFORCER_ROLE | multisig de enforcement (conformidade + jurídico) |
PAUSER_ROLE | chave de resposta a incidentes (rápida) |
ISSUER_ROLE, STATUS_ROLE, TRANSFORMER_ROLE | serviços operacionais com privilégio mínimo, com rotação |
ATTEST_ADMIN_ROLE | autoridade de certificação ou plataforma |
initialize concede tudo a um único administrador por conveniência; a lista de verificação de implantação exige a redistribuição antes da produção.
Semântica de enforcement e de pausa
- A pausa bloqueia cunhagens, transferências, queimas e transformações; não bloqueia as transferências forçadas, de modo que uma ordem legal possa ser executada durante um incidente.
- As transferências forçadas dispensam
canSend/canReceivee a verificação de saldo congelado, reduzem o valor congelado ao que resta e ainda executam os hooks comOP_FORCED_TRANSFER. Os hooks de referência retornamOKpara essa operação; um hook que trate de enforcement pode exigir referências de ordem emdata. - O congelamento pode exceder o saldo (ERC-7943), de modo que um gravame pode cobrir depósitos futuros.
Segurança das atualizações
- UUPS;
_authorizeUpgradeprotegido porUPGRADER_ROLE. - Estrutura de armazenamento com namespace ERC-7201; somente acréscimos.
- As validações do plugin de atualizações do OpenZeppelin são executadas nos testes e deveriam ser executadas na CI antes de qualquer transação de atualização.
- A configuração
optimizer.runs = 1por arquivo mantém a implementação abaixo do EIP-170; uma alteração que a ultrapasse falha em tempo de compilação, com um aviso, e na implantação, com um revert.
Segurança de dependências e de build
- OpenZeppelin Contracts e Contracts-Upgradeable fixados na versão 5.3.0; lockfile versionado; a CI usa
npm ci. - Solidity 0.8.22, viaIR, EVM
paris(sem dependência de armazenamento transitório, implantável em redes que não adotaram o Cancun). - Nenhuma biblioteca externa vinculada; nenhum delegatecall fora do proxy UUPS.
Postura de auditoria
- 46 testes sobre a implementação de referência, os hooks e as extensões cobrem todas as invariantes acima, inclusive uma execução de invariantes randomizada com semente.
- O gás e o tamanho são medidos por scripts do repositório.
- Uma auditoria de terceiros de
ARexToken,ARexAttestationse dos hooks de referência é uma pré-condição declarada para uma âncora de produção e para a submissão do ERC (ver Desenvolvimentos Futuros). - A verificação formal das invariantes do pipeline está no roteiro; as invariantes são pequenas o bastante para serem enunciadas como propriedades.
Riscos residuais que o padrão não elimina
- A existência física e a qualidade de um lote são atestadas, e não comprovadas; o token torna as afirmações atribuíveis, e não verdadeiras.
- A disponibilidade dos metadados off-chain depende do armazenamento escolhido; o hash garante a integridade, e não a disponibilidade.
- A governança de hooks e módulos é tão boa quanto as chaves que a controlam.