Checklist para o Desenvolvimento Seguro de Contratos Inteligentes
Conforme apresentado em uma postagem anterior , desenvolvemos um checklist de quatorze itens indispensáveis para o desenvolvimento seguro de contratos inteligentes. Estamos felizes em divulgar esta lista de verificação como um recurso para ajudar a comunidade de desenvolvimento de contratos. Adicionamos o feedback de nosso parceiro de auditoria, Trail of Bits , e agradecemos feedback sobre qualquer coisa que possa ser melhorada. Nossa política é implementar esses procedimentos 100% para todos os novos contratos inteligentes que desenvolvemos. Nos contratos atuais, desativamos as alterações relacionadas à API para evitar problemas.
O checklist é esse:
- Crie uma nova GitHub organization para hospedar contratos relacionados à produção. Por exemplo, nosso reposiório é o parity-contracts . Todos os contratos neste repositório devem ser mantidos ativos ou em estado de desenvolvimento ativo para produção. Não deve haver projetos obsoletos ou legados neste repositório.
- Colocar cada contrato em um repositório separado. (“Cada contrato” também pode significar um módulo de contratos fortemente acoplados — por exemplo, Operations.sol e OperationsProxy.sol, que funcionam juntos e não são usados separadamente.)
- Juntar asa dependências para tornar a métrica de cobertura de código mais significativa e facilitar o raciocínio sobre toda a base de código do contrato. Todas as fontes duplicadas devem ser listadas como tal (com links cruzados!) no README de cada repositório em que são copiadas.
- Certifique-se de que cada contrato no repositório atenda aos seguintes critérios de qualidade de código:
O código atual, que está implantado, de cada contrato deve ficar em uma ramificação master
protegida. O master mais recente deve sempre refletir o código atual implantado . Ninguém tem permissão para fazer um commit no master. As correções para todos os códigos dependentes devem ser enviadas logo após essa implantação, na mesma Pull Request. A ramificação master
deve ser o padrão para o repositório, portanto, navegar no GitHub mostra o contrato implantado mais recente (e seus endereços) imediatamente.
Também pode ser útil ter uma branch de development
para salvar alterações nocontrato ainda não implantadas, seguindo essas condições:
-development
também é uma branch protegida, com todas as verificações desta seção (testes, revisões, linting etc) exigidas
- existe um procedimento, com um responsável e prazo acordado, para que este contrato seja implantado e adicionado aomaster
.
b. Os testes devem ser escritos em uma linguagem diferente do Solidity (provavelmente JavaScript + Truffle) para garantir que bugs relacionados a peculiaridades de sintaxe e mal-entendidos sejam descobertos com testes.
c. Os testes são cobertos pela CI. Se os contratos estão disponíveis publicamente, é recomendado a execução dos testes em Travis ou CircleCI. A aprovação de todos os testes é obrigatória para a realização do merge e e deve ser aplicado para todos nas configurações do GitHub.
d. O linting deve ser habilitado para todos os arquivos de origem do contrato no repositório do contrato, incluindo as dependências. O linter deve ser incluído na execução dos testes, e se não passar no lint, o merge não é liberado. Exceções são permitidas, desde que o motivo e explicação de segurança sejam descritos no comentário.
e. Cada repositório deve ter pelo menos dois proprietários definidos, conforme descrito aqui. É uma boa prática definir proprietários de código em todo o repositório (também conhecido como 'curinga') para cobrir quaisquer contratos em que os proprietários não estejam definidos.
f. Revisões são necessárias para solicitações de Pull Requests(PR). Dois revisores devem aprovar o PR para que seja feito o merge e pelo menos um dos revisores deve ser um Proprietário do Código. Você pode usar reviewable.io para rastrear “quem revisou o quê”. Não há problema para o remetente do PR implantar a versão “greenlit” do PR no blockchain para obter seu endereço e modificar o mapeamento no README no mesmo PR. É responsabilidade do **submissor** certificar-se de que seu PR está recebendo as avaliações adequadas; chamar a atenção nas salas de bate-papo dos desenvolvedores é uma boa maneira de fazer com que as revisões aconteçam.
g. O rebase para o master
mais recente deve ser obrigatório para que nenhum PR sofra um merge sem testes aprovados.
5. Certifique-se que todos os repositórios tenham o bytecode e API atualizados no master
. É dever do remetente do PR garantir que a API e o bytecode sejam atualizados adequadamente.
6. Todo contrato deve ter um README com a lista de todos os endereços de implantação em todas as redes. Quando possível, esse endereço deve ser vinculado a um serviço de exploração de blockchain (por exemplo, Etherscan), que deve conter uma guia de “código verificado” para este endereço e fonte do contrato.
7. Certifique-se de que o README contém uma seção separada “Update Strategy”. Nessa seção, enumere o que precisa ser feito para realizar uma atualização do contrato corretamente. Exemplos de perguntas a serem abordadas nesta seção:
- Existe um contrato de proxy?
- Quais outros sistemas precisam ser atualizados?
- Como mover dados de contrato para contrato?
8. No topo do README, coloque uma indicação clara do estado de “prontidão de produção” do contrato (como um crachá):
- alfa — contratos que estão em desenvolvimento ativo e podem ainda não estar adequados.
- beta — contratos que estão prontos prontos para uso em testnet, mas ainda não foram auditados. Estes NÃO DEVEM ser usados na rede principal.
- stable — contratos devidamente auditados, implantados na rede principal e em uso ativo.
- deprecated — contratos que não são mais suportados e usados, mas você deseja manter por algum motivo. (Evite mantê-los por perto! Excluir um repositório é quase sempre uma ideia melhor.)
10. Incorpore todos os pontos aplicáveis em um arquivo PULL_REQUEST_TEMPLATE.md no repositório. Formate este arquivo como um checklist.
11. Certifique-se de que o arquivo principal de cada contrato tenha sua URL na seção de comentários no cabeçalho. Isso permite que qualquer pessoa rastreie o código de volta ao repositório.
12. Certifique-se de que os contratos tenham as view ou funções puras (ou apenas definições de constantes públicas, com getters criados automaticamente) contract_name e contract_version definidas. Essas funções devem ter as seguintes propriedades:
a. contract_name deve corresponder ao repositório do repositório. Como estamos seguindo uma política de “um contrato por repo”, esse identificador deve ser exclusivo o suficiente.
b. contract_version deve conter versões inteiras. É obrigatório dar um bump nesta versão em cada PR.
12. Certifique-se de que as versões implantadas no master tenham as tags git correspondentes. Essas tags devem ser criadas/carregadas somente após a implantação para não eliminar as tags durante os possíveis ciclos de redeploys
13. Certifique-se de que cada repositório tenha uma licença definida.
14. Permita apenas que os endereços dos READMEs das sejam referenciados a partir do código de produção , para que você saiba que esses contratos são testados, mantidos e têm suas implantações documentadas adequadamente. A referência a um endereço deve sempre ser acompanhada de um link permanente para o repositório de contrato correspondente. Os revisores desses PRs devem verificar se:
- a. O endereço implantado do README está correto.
- b. É a versão mais recente implantada.
- c. O uso do contrato de outro código corresponde ao seu objetivo declarado.
- d. As APIs estão corretas.
Esperamos que esta lista de verificação ajude a comunidade a se desenvolver com segurança. Sinta-se à vontade para postar no bate-papo do watercooler da Parity se tiver alguma dúvida sobre a lista de verificação.
Artigo original: https://www.parity.io/blog/paritys-checklist-for-secure-smart-contract-development/