Como funciona o contrato ERC721A? Como eu o utilizo? Quais são as HIDDEN GEMS (jóias ocultas) dentro dele que eu posso usar para obter dinheiro grátis?
O ERC721 é o padrão mais comum para NFTs (tokens não fungíveis). Ele regula como os contratos NFT devem se comportar, mas não como os contratos NFT devem implementar este comportamento.
Por um longo tempo a implementação do ERC721 da OpenZeppelin era sinônimo do padrão ERC721. O ERC721A, lançado em janeiro de 2022, foi o primeiro contrato mainstream a oferecer uma verdadeira abordagem alternativa.
Como funciona o ERC721A? Como ele é diferente do ERC721 OpenZeppelin ?
A principal ideia por trás do ERC721A é fornecer cunhagem com baixa taxa de gas às custas de fazer as transferências de tokens mais caras. Isto foi conseguido repensando a forma de armazenagem da propriedade do token.
Cunhagens de tokens no ERC721A
Aqui está um exemplo. Quando você cunhar 10 tokens em um contrato OpenZeppelin, você registra que é proprietário de cada token individualmente. Em contraste, quando você cunhar 10 tokens com ERC721A, você armazena apenas que você possui o primeiro token que você cunhou:
Armazenamento de propriedade: OpenZeppelin v. ERC721A
O armazenamento de 10x menos endereços obviamente torna a cunhagem muito mais barata. Mas como você determina quem possui (por exemplo) o token #6?
Com OZ é fácil: você procura a entrada para o token #6 na tabela e vê o middlemarch.eth ao lado dele. Com ERC721A, no entanto, esta entrada está em branco. E agora?
Quem possui o token #6? OpenZeppelin v. ERC721A
Para descobrir o proprietário do #6 você deve contar de trás para frente, verificando cada entrada na tabela até encontrar uma que não esteja em branco.
Neste caso, você verificaria 5, 4, 3, 2, 1 e 0, onde finalmente observaria uma entrada de propriedade que não esteja em branco (middlemarch.eth). Este endereço é o proprietário do token #6.
Este trabalho extra torna mais cara a determinação de quem possui um token - de O(1) no caso OZ para O(mintBatchSize) no caso do ERC721A.
Quando alguém cunhar muitos tokens de uma só vez, isto se torna bastante significativo. Para usar um exemplo extremo, se alguém cunhar 10.000 tokens de uma só vez, poderia custar mais de 1 eth para determinar quem possui o décimo milésimo token!
Em muitos casos, ownerOf()
é chamada em um contexto de visualização e, portanto, é gratuito. Entretanto, ela é chamada em um contexto de escrita em um importante caso de uso : transferência de token.
Transferências de token no ERC721A
Transferir o token #6 no ERC721A é duplamente caro. Primeiro, você tem que descobrir quem possui o token #6, conforme descrito acima. Depois, você deve fazer duas escritas: uma para atualizar a posse do token #6, e outro para atualizar a posse do token #7 (se ele estiver em branco):
Isto porque a propriedade em branco significa "contar até a primeira propriedade não em branco e este é o proprietário" e a primeira propriedade que não está em branco para o token #7 mudou de middlemarch.eth para vitalik.eth, mesmo que o #7 ainda seja propriedade da middlemarch.eth.
Devo usar ERC721A?
ERC721A adia a inicialização de propriedade do token da cunhagem à transferência. O ERC721A também gasta mais gas em geral. Isto se traduz em taxas mais altas ou mais baixas em eth? Como sempre em trade-offs, "depende". Mas aqui estão algumas considerações.
Consideração 1: Os preços do gas serão mais altos durante as cunhagens ou transferências?
Para as cunhagens competitivas, os usuários podem não ter a opção de esperar e cunhar quando o gas estiver baixo. Cunhagem hiper-competitiva pode até mesmo afetar as taxas globais de gas da Ethereum, tornando impossível a cunhagem por menos. Na medida em que os custos de gas são mais baixos durante as transferências do que nas cunhagens, a ERC721A se torna mais atraente.
Os documentos ERC721A utilizam este exemplo:
Consideração 2: Seu NFT valerá mais do que zero?
NFTs que valem zero não incorrem em taxas de transferência porque ninguém pagará gas para obtê-las! No entanto, ainda é preciso pagar para cunhar algo que valha zero. Se seu projeto é apenas por diversão, ou você não tem certeza de como ele irá funcionar, o ERC721A pode ser atraente, pois faz com que os usuários gastem mais gas somente no caso de o NFT valer alguma coisa.
Consideração 3: Você gosta de dinheiro gratuito?
Além da ideia principal de "cunhagens mais baratas, transferências mais caras", ERC721A contém várias inovações completamente independentes.
Estas são características que eu adoraria ver em implementações mais gerais do ERC721, e que você pode usar no ERC721A mesmo se você quiser sair de sua ideia principal, cunhando em lotes de 1!
ERC721A Dicas, truques e dinheiro gratuito!
Agora que abordamos o básico e os trade-offs do ERC721A, como podemos reduzir as desvantagens e até mesmo encontrar oportunidades para o dinheiro gratuito de tradeoff zero no ERC721A? Continue lendo e também leia a página de dicas do ERC721A !
Dica 1: Escolha os tamanhos de lotes razoáveis para seus usuários
A cunhagem de muitos tokens de uma vez torna a transferência extremamente cara. Uma solução aqui é limitar a quantidade que um usuário pode cunhar em uma única transação. Entretanto, eu não considero esta opção muito interessante.
Se você quiser permitir que os usuários cunhem quantos tokens eles quiserem em uma única transação, você deve cunhar em lotes como este:
Isto permite que o usuário cunhe um número ilimitado de tokens sem nunca exigir mais de 10 buscas para determinar a titularidade dos tokens no futuro.
Dinheiro gratuito através de um armazenamento de dados mais eficiente
Como o ERC721A pode fazer você ganhar dinheiro de graça? Além de adiar os custos da cunhagem, o ERC721A é mais inteligente que a implementação do OpenZeppelin em termos de como ele armazena os dados.
Por exemplo, a OZ armazena o número de NFTs que cada usuário possui em um inteiro de 256 bits:
Esta linha de código parece inócua, mas na verdade contém uma hipótese controversa: que seu contrato precisa apoiar um usuário que possua até 2 ^ 256 — 1
tokens. Isso é mais tokens do que há de átomos no universo conhecido!
A remoção desta exigência permite ao ERC721A armazenar mais informações úteis nos mesmos 256 bits. Especificamente, o ERC721A usa 64 bits para o saldo do usuário e os 192 bits restantes para armazenar:
- Número de tokens cunhados pelo endereço
- Número de tokens queimados pelo endereço
- 64 bits de “Aux Data” (Dados Auxiliares) para o que quer que o desenvolvedor deseje
Dica 2: use _numberMinted(address)
Como você pode usar esta informação? Suponha que você queira permitir apenas uma cunhagem por carteira, como o goblintown.wtf. Em vez de usar um mapeamento separado, você pode usar o ERC721A embutido _numberMinted(address)
:
Dica 3: use _setAux(address)
Suponha que os usuários possam cunhar o quanto quiserem, mas cada carteira receba apenas uma de graça. Você pode usar os dados auxiliares para isto (como sugerido no Tweet que inspirou este artigo):
O benefício aqui vem do fato de que a cunhagem e a configuração dos dados auxiliares atualizam o mesmo slot de armazenamento, que é 20k de gas mais eficiente do que a atualização de dois slots separados, como é o caso do mapeamento separado freeMintClaimed
.
Dica 4: use _extraData() for generative art
O próximo aprimoramento vem da otimização da forma como a OZ armazena as informações de propriedade. Aqui não estou me referindo à ideia de escrever preguiçosamente as informações de propriedade, mas sim, a quais dados são armazenados quando são escritos.
O OpenZeppelin armazena informações de propriedade como esta:
Isto é simples, mas um desperdício. Um endereço é 160 bits, mas armazená-lo custa o mesmo que armazenar 256 bits de informação. Isto deixa 96 bits sobre a mesa. O que o ERC721A faz com esses 96 bits? O mais interessante:
- O registro de hora da última transferência
- 24 bits de “Dados extras” para o que você quiser!
Na verdade, não tenho certeza porque o ERC721A armazena a hora em que o atual proprietário recebeu o token. Esta informação permite, por exemplo, recompensar titulares de longo prazo com um preço mais barato em outra cunhagem, mas casos de uso como este parecem ser um nicho para justificar os 64 bits de dados que ele requer.
Isto é duplamente verdadeiro, pois o conceito de registro da hora poderia ser capturado com o conceito mais geral e mais útil de "dados extras" na minha opinião (IMO). Os dados extras permitem armazenar 24 bits de dados por lote, o que significa que quaisquer dois tokens que compartilhem o mesmo registro de propriedade compartilharão os mesmos "dados extras".
O quanto isso poderia ser útil? O implementador original foi motivado pelo armazenamento de sementes para a arte generativa. Aqui está a ideia básica:
- O usuário cunha 5 NFTs (por exemplo).
- O contrato armazena o estado da blockchain como block.timestamp como dados extras no registro de propriedade correspondente ao lote.
- Para renderizar o NFT, gerar uma semente única puxando o registro de propriedade do token, pegando os dados extras e fazendo o hashing com a identificação do token (porque todos os tokens do lote compartilham os mesmos dados extras).
- Usar esta semente única para gerar a arte.
Aqui está como se faz isso, adaptado de Ethereal States, programado pelo legendário sfremaux / dievardump
.
Note que sua função mint()
não precisa estar ciente de dados extras já que a _extraData()
será chamada internamente por ERC721A em _mint()
.
E é isso! Todas essas "jóias ocultas" podem ser usadas independentemente do caso de uso de cunhagem do lote principal. Se você quiser um comportamento de cunhagem e transferência de OZ-esque, você pode cunhar em lotes de 1 token ou chamar _initializeOwnershipAt()
em cada id cunhado em um lote.
Agradecimentos especiais vão para dievardump e squeebo que me ensinaram tudo isso!
Esse artigo foi escrito por Tom Lehman (middlemarch.eth) e traduzido por Fátima Lima. Seu original pode ser lido aqui.
Latest comments (0)