Texto original: "Vanity Addresses" por foobar
Compilação: Mingau noturno, o caminho do DeFi
160 milhões de dólares americanos desapareceram e Wintermute perdeu os fundos. Wintermute é um dos fundos de criação de mercado mais astutos do setor. Certa manhã de setembro, quando o responsável pelo Wintermute acordou, ele descobriu que uma de suas carteiras importantes havia perdido 9 dígitos. Então, o que levou ao roubo de Wintermute? Isso é causado pela baixa aleatoriedade em um gerador de endereços personalizados. Hackers de chapéu preto forçam com força bruta o par de chave privada e endereço público do zero e, em seguida, uma grande quantidade de ativos criptográficos é transferida.
Há também uma história sobre o Indexed Finance ter sido hackeado, onde $ 16 milhões foram roubados em outubro de 2021, e os fundos roubados foram então transferidos para endereços começando com 0xba5ed…. O que eles não sabiam era que o endereço personalizado também foi afetado pela vulnerabilidade de aleatoriedade que assolou Wintermute e, em setembro de 2022, todo o dinheiro foi roubado novamente, indo para outro endereço de carteira hackeado. Os ladrões são implacáveis.
Então, quais problemas esses desenvolvedores talentosos encontraram e o que podemos aprender com eles?
À esquerda está o endereço normal usado para o contrato WETH. À direita está um lindo endereço com 14 zeros à esquerda para otimização do robô MEV. O tipo mais comum de endereço personalizado é aquele com muitos zeros à esquerda.
Em primeiro lugar, o que é um endereço personalizado (também conhecido como endereço personalizado)? Um endereço personalizado refere-se a um endereço público que um usuário cria deliberadamente para associar à sua carteira ou contrato inteligente. Talvez comece com 0x0000000, talvez comece com 0xdeadbeef, talvez seja algum outro endereço regular. Existem vários motivos para sua popularidade:
1. Otimização de gás: Wintermute economizou US$ 15.000 usando um endereço EOA com vários zeros à esquerda. Parece bobagem? Muitas pessoas concordam, mas é assim que funciona o EVM. Se você tiver muitos zeros em seu endereço, a taxa de transação pode cair! Portanto, se você usar um endereço de contrato inteligente com muitos zeros à esquerda, os usuários ficarão felizes ao interagir com ele, pois isso economiza dinheiro.
O Ethereum Yellow Paper descreve como os endereços zero iniciais podem permitir gás mais barato
2. Marca do contrato. Você sabia que o contrato do Token de 1 polegada começa com 0x111111111...?
Contrato de token de 1 polegada
3. Repetibilidade de múltiplas cadeias. Na minha opinião, esta é uma prioridade máxima e é por isso que todo protocolo deve usar um endereço personalizado para sua implantação. Seu aplicativo pode residir em 15 cadeias EVM diferentes e ter o mesmo endereço em todos os lugares! Isso não seria mais fácil para desenvolvedores e usuários?
Então, quando um endereço bonito é seguro?
Existem dois tipos de endereços Ethereum: contas de propriedade externa (EOA) e contas de contrato inteligente. Se você usou uma carteira como a MetaMask, cada endereço nela contido é um EOA, que é usado para assinar mensagens e processar transações. Compare isso com uma conta de contrato inteligente, como o contrato Uniswap, com o qual as pessoas podem interagir, mas não podem realizar suas próprias ações sem serem acionadas. Resumindo, é muito simples. Os endereços de números bons não são seguros para contas EOA, mas são seguros para contas de contrato inteligente.
Então, por que isso acontece? Explicaremos isso com mais detalhes a seguir, mas depende de como o endereço personalizado é gerado. Para contas EOA, você percorre milhões de chaves privadas até encontrar uma que corresponda a um endereço público bonito. No entanto, a chave privada controla os fundos dentro de uma conta EOA, portanto, se a aleatoriedade que você usa para percorrer a chave privada for comprometida, toda a sua conta será arruinada. Por outro lado, a criação de endereços personalizados de contratos inteligentes requer apenas a passagem de sementes públicas, que não concedem quaisquer direitos administrativos ao contrato inteligente.
É por isso que o Wintermute falha e o OpenSea é bem-sucedido – gerar chaves privadas em memória insegura com software inseguro é ruim. Mas gerar sementes públicas dessa forma é muito bom! Portanto, um bom endereço EOA é um caminho para a falência, enquanto um bom endereço de contrato inteligente é um caminho para o sucesso.
Por que o protocolo exige um endereço bonito?
Documentação mais simples! Você pode apontar para um endereço de contrato em todas as cadeias;
Verificável pelo usuário! O mesmo endereço do contrato aparecerá somente se e somente se o bytecode for correspondido byte por byte;
Os desenvolvedores podem verificar! Como endereços de contrato idênticos ocorrem apenas no caso de uma correspondência exata, você pode detectar pequenas modificações complicadas em seu script de implantação;
Integração mais fácil! Outros protocolos podem codificar o endereço do seu contrato em seu multi-chaincode sem ter que usar instruções if baseadas em chainId.
NOTA: Estamos prestes a nos aprofundar em um manual de instruções detalhado. Juntando todas as peças pela primeira vez, estamos nos aprofundando no espaço técnico e visando desenvolvedores de contratos inteligentes com experiência na implantação de contratos inteligentes na cadeia. Se tiver interesse, continue lendo, mas se não for para você, não se preocupe em acompanhar. Há um desafio técnico adicional no final (com recompensas).
Endereço bonito do contrato inteligente
Existe uma maneira de gerar endereços personalizados de contratos inteligentes que sejam 100% seguros, não importa qual software você use, não importa se a tecnologia iterativa vaza publicamente. É chamado de “método de fábrica CREATE2” e não apenas fornece um endereço bonito, mas também é uma maneira infalível de garantir que você tenha o mesmo endereço de implantação de contrato em várias cadeias. Ele também permite que outros implantem código em seu nome sem qualquer compartilhamento de chave privada ou suposições de uso único.
Primeiro, uma rápida visão geral de como escolher um endereço de contrato inteligente. Existem duas opções de implantação, CREATE e CREATE2. Ao implantar um contrato inteligente diretamente do EOA, o processo padrão é CREATE. O endereço é determinado pelo hash do endereço do criador do contrato com o nonce do criador do contrato. Este nonce refere-se a quantas transações um endereço enviou, portanto, uma nova carteira começa em 0 e é incrementada em 1 cada vez que uma nova transação é enviada. Aqui está a fórmula mágica para o endereço de contrato inteligente implantado pelo CREATE:
novo_address = hash(remetente, nonce)
Menos comum, mas mais interessante, é o endereço de contrato inteligente implantado usando CREATE2, e aqui está sua fórmula:
novo_address = hash(0xFF, remetente, salt, bytecode)
O primeiro parece mais simples, certo? No entanto, vamos dar um exemplo de onde esta simplicidade pode ser prejudicial em comparação com o processo CREATE2 mais robusto.
Airy Alice: Há um problema com multi-chain
Imagine que uma desenvolvedora de criptografia chamada Alice crie dois contratos inteligentes: um fork do Uniswap chamado GriddleSwap e um projeto NFT chamado ph00ts. Eles são todos primitivos independentes e imutáveis, o que significa que não há dependências externas ou riscos de pontes entre cadeias. Alice implanta GriddleSwap no Ethereum usando nonce 0 e, em seguida, implanta ph00ts no Ethereum usando nonce 1. Infelizmente, Alice tem pouca atenção e se distraiu no Twitter criptográfico por alguns minutos antes de implantar seu trabalho na Binance Smart Chain (BSC), a segunda maior plataforma de contratos inteligentes.
Ops, baguncei a ordem de implantação!
Mas espere! Ela bagunçou a ordem de implantação e implantou ph00ts antes do GriddleSwap. Como o endereço do contrato inteligente depende apenas do endereço do criador e no blockchain implantado, o Ethereum gridleswap tem exatamente o mesmo endereço que o BSC ph00ts. Para piorar a situação, o endereço do Ethereum ph00ts é o mesmo que o endereço do BSC GriddleSwap. Pensar que os usuários finais ficarão confusos é um eufemismo. Na verdade, pode ser abusado por implantadores mal-intencionados para induzir as pessoas a pensarem que o comportamento do contrato na cadeia é o mesmo - o que é uma suposição justa, dado o mesmo endereço!
Cuidado Alice: Ainda haverá problemas
Mesmo que Alice seja cuidadosa ao implantar e nunca confunda a ordem de seus nonces, existem outros problemas. Se Alice implantar corretamente no Ethereum e no BSC, mas depois fizer uma transação não relacionada no Polygon, o nonce 0 terá sido usado. Ela nunca poderá implantar o GriddleSwap lá porque seu nonce foi incrementado. Portanto, as chaves privadas do implementador devem ser protegidas a todo custo. Se Alice vazar, um sabotador malicioso poderá fazer transações não relacionadas. Se Alice o perder, ela também perderá a capacidade de implantar nesse endereço novamente em uma nova cadeia. Esta é uma vulnerabilidade permanente que depende de um indivíduo honesto para proteger a chave privada. Se nem mesmo os principais desenvolvedores do Bitcoin conseguem fazer isso, como o resto de nós pode fazer isso?
Solução: CRIAR2
Felizmente, existe uma maneira melhor de obter endereços consistentes entre cadeias – uma que não dependa de chaves privadas secretas, não dependa de um único implementador e seja resistente a erros do implementador ao longo do caminho. Lembre-se da fórmula para encontrar o endereço de um contrato inteligente implantado usando CREATE2:
novo_address = hash(0xFF, remetente, salt, bytecode)
O primeiro parâmetro 0xFF é um valor constante que pode ser ignorado. O segundo parâmetro (endereço do remetente) pode ser tornado consistente selecionando a implantação CREATE2Factory 0x0000000000FFe8B47B3e2130213B802212439497 do z0age na maioria das cadeias EVM. O terceiro parâmetro é um sal selecionado pelo usuário, que podemos usar para encontrar um bom endereço e mantê-lo inalterado na cadeia. O quarto é o bytecode do contrato, que serve como uma verificação de integridade útil para garantir que estamos implantando exatamente a mesma funcionalidade na cadeia. Todos os quatro parâmetros podem permanecer os mesmos, não importa o que qualquer implementador faça.
Por que isso é melhor? Ao contrário da chave privada, o salt selecionado pelo implementador pode se tornar público. Conhecer o salt permite implantar o contrato, mas você não tem controle sobre os ativos ou funcionalidades do contrato. Como não vincula nenhuma informação secreta, qualquer pessoa pode implantar o contrato na nova cadeia sem revelar ou compartilhar a chave privada. O parâmetro bytecode também garante que essas novas implantações sem permissão terão o mesmo endereço se e somente se o bytecode for o mesmo. Portanto, os usuários finais obtêm garantias mais fortes sem precisar fazer diferenças detalhadas no código.
Para uma visão geral mais aprofundada, consulte o popular artigo científico do OpenZeppelin.
Crie seu próprio lindo endereço
Você acha que o Proof of Work (PoW) será inútil após a fusão da Ethereum? Pense de novo! Os mesmos recursos de GPU que ajudam a encontrar pré-imagens de hash com um grande número de zeros à esquerda para blocos Bitcoin também são excelentes para encontrar pré-imagens de hash com um grande número de zeros à esquerda para contratos inteligentes EVM. z0age da OpenSea (graças à explicação deste post) encontrou uma configuração simples para criar seu próprio endereço personalizado.
1. Use vasto.ai para iniciar uma instância de exemplo de GPU, que tenta cerca de 2 bilhões de vezes por segundo e custa cerca de 25 centavos/hora:
Imagem: nvidia / opencl
GPU: 1x RTX 3090
Espaço em disco necessário para ser alocado: 1,83 GB
2. SSH e instale ferrugem + create2crunch
sudo apt install build-essential -y; curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y; fonte "$HOME/.cargo/env"; clone git https://github.com/0age/create2crunch && cd create2crunch; sed -i 's/0x4/0x40/g' src/lib.rs
3. Execute uma pesquisa inicial. Para variáveis de ambiente, INIT_CODE_HASH é o keccak256 do código de criação do contrato. Uma impressão de um exemplo de teste de fundição pode ser encontrada aqui - certifique-se de verificá-lo antes de consumir grandes quantidades de recursos computacionais! LEADING deve ser o número de zero bytes iniciais que você deseja e TOTAL deve ser o número total de zero bytes que você deseja no endereço do contrato.
exportar FÁBRICA = "0x0000000000ffe8b47b3e2130213b802212439497"; exportar CALLER="0x0000000000000000000000000000000000000"; exportar INIT_CODE_HASH="0xabc...def"; exportar LEAD=5; exportar TOTAL=7; execução de carga --release $FACTORY $CALLER $INIT_CODE_HASH 0 $LEADING $TOTAL
Quando z0age lançou seu repositório pela primeira vez, ele era capaz de executar 1,9 bilhão de tentativas por segundo no hardware de IA vasto mencionado acima. Desde então, a vetorização enlouqueceu em alguns núcleos OpenGL e observei 2,15 bilhões de tentativas por segundo. Isso significa que encontrar um endereço com 5 zero bytes à esquerda levaria 256 ^ 5/(2150000000 * 60) ~= 8 minutos, e encontrar um endereço com 6 zero bytes à esquerda levaria 256 ^ 6/(2150000000 * 3600) ~ = 36 horas. Um endereço de 7 bytes zero à esquerda leva 256^7/(2150000000 * 86400) ~= 387 dias. Observe que um byte é igual a dois caracteres hexadecimais, portanto, um endereço de 5 bytes iniciais terá 10 zeros. É claro que esta busca pode ser totalmente paralelizada e a probabilidade real de sucesso ao longo do tempo seguirá uma distribuição de Poisson.
Implantar a fábrica CREATE2
Leitores astutos devem ter notado que o CREATE2 Factory já existe em 0x0000000000FFe8B47B3e2130213B802212439497 em todas as cadeias. É um problema do ovo e da galinha. Como a implantação consistente de endereços depende da implantação consistente de endereços?
Quando aprendi sobre essa abordagem, pensei que era apenas uma chave privada mantida por alguém mais inteligente do que eu (o cenário da "Alice observadora" acima). Mas na verdade é muito mais robusto do que isso! A abordagem de "transações sem chave" do fundador do ENS, Nick Johnson, explora o fato de que você pode recuperar o endereço público de qualquer assinatura de transação sem saber a chave privada correspondente que a assinou. Portanto, é possível criar uma transação ("implantar uma fábrica create2") e então inventar uma assinatura forjada para ela, por exemplo, uma assinatura composta apenas por 2's. A chave privada para esta assinatura forjada existe, mas ninguém sabe o que é. Mas podemos recuperar o endereço público correspondente à “assinatura sem chave”, enviar-lhe algum ETH e depois enviar a transação assinada ao mempool. Apesar da obscuridade deste método, é uma transação válida e, na verdade, a única transação válida que pode ser enviada deste endereço público.
O resultado? Qualquer pessoa pode implantar uma fábrica em uma nova cadeia sem qualquer informação proprietária, evitando ao mesmo tempo que agentes mal-intencionados causem danos. Criar um EOA de propósito único que possa implantar apenas uma transação é uma técnica muito inteligente.
Endereços e contratos específicos criados durante transações sem chave
Isso pode ser feito com três comandos simples de "forjar elenco". O bytecode é muito longo para copiar aqui, mas você pode seguir as instruções em https://github.com/ProjectOpenSea/seaport/blob/main/docs/Deployment.md sem permissão em qualquer cadeia de sua escolha. Implante CREATE2 Factory facilmente!
Obviamente, se já tiver sido implantado, não há necessidade de implantá-lo novamente.
Nota lateral: os requisitos do EIP-155 são terríveis
Uma breve tentativa de apoiar minhas aventuras de governança L1. Fique à vontade para avançar. EIP-155 é uma proposta apresentada por Vitalik em 2016, que introduz o conceito de “ID de cadeia” para evitar ataques de repetição. Cada cadeia tem seu próprio identificador exclusivo – 1 para Ethereum, 56 para BSC e 137 para Polygon – que será incluído nas transações assinadas para evitar ataques de repetição, que foi rapidamente adotado pela Ethereum, e todas as outras cadeias EVM seguiram esta proposta. Isso é ótimo, mas o problema surge quando algumas cadeias são selecionadas, como a Evmos, que recentemente decidiu banir explicitamente as transações antes do EIP-155, o que, por razões estranhas, evita um erro operacional onde o Optimism enviou 20 milhões de tokens OP para um multisig (sim, eles de novo) endereço que Wintermute não existe, afirma possuir, mas nunca foi inicializado. No entanto, desabilitar transações pré-155 quebraria significativamente todo um conjunto de implantações entre cadeias, como a fábrica CREATE2 e projetos importantes como o Seaport. Estas propostas de governação devem ser revertidas imediatamente, e detalhes de protecção como este devem vir da carteira e não da camada de consenso. Se multi-chain for o futuro, então essas restrições desnecessárias serão um enorme obstáculo para a implantação de projetos importantes em seu blockchain.
Coisas divertidas: implantando recompensas
Hoje https://delegate.cash está implantado em 7 cadeias EVM diferentes (Ethereum, Polygon, Optimism, Celo, Avalanche, Fantom e Arbitrum) e 7 testnets correspondentes a essas cadeias. O endereço do contrato para todos eles é o mesmo: 0x00000000000076A84feF008CDAbe6409d2FE638B.
Então isso é suficiente? Não, precisamos de mais correntes. Como o delegadocash é uma primitiva independente com zero dependências, isso significa que o risco de múltiplas cadeias é efetivamente zero. Isso é puro benefício! Portanto, para as primeiras 5 pessoas que implantarem e verificarem o contrato inteligente delegadocash para a nova rede e testnet correspondente, concederei um bônus de 100 USDC!
Você precisa usar o script de implantação do repositório de código aberto aqui. Isso pode exigir a implantação do CREATE2 Factory se ele não existir, e não se esqueça da verificação Etherscan! Boa implantação e aproveite o aprendizado experiencial!
