Dados tipados e EIP-712¶
Assinatura de mensagem simples, coberta em Assinando Mensagens, tem um problema de usabilidade real: uma carteira só pode mostrar ao usuário uma string bruta, indiferenciada, para qualquer coisa além de uma mensagem de login curta, o usuário não tem maneira confiável de realmente entender o que eles estão aprovando. EIP-712 resolve isso fazendo dados assinados estruturado e legível para o homem, verificado aqui com uma assinatura real, funcionando.
O problema de assinatura simples cria¶
Recordar de Assinando Mensagens que um dapp malicioso pode apresentar uma mensagem disfarçada. Este risco é muito pior para a assinatura simples de qualquer coisa mais complexa do que uma frase de login curta, uma carteira mostrando um usuário uma parede de hex cru ou uma cadeia longa, não estruturada dá-lhes essencialmente nenhuma maneira prática de verificar o que uma autorização complexa (uma licença token, uma ordem para uma troca descentralizada) realmente diz antes de a aprovar.
Dados estruturados, digitados¶
import { verifyTypedData } from "viem";
const domain = {
name: "Example App",
version: "1",
chainId: 1,
verifyingContract: "0x000000000000000000000000000000000000dEaD" as const,
} as const;
const types = {
Order: [
{ name: "buyer", type: "address" },
{ name: "amount", type: "uint256" },
{ name: "price", type: "uint256" },
],
} as const;
const message = {
buyer: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" as const,
amount: 100n,
price: 5000n,
};
const signature = await account.signTypedData({
domain,
types,
primaryType: "Order",
message,
});
const isValid = await verifyTypedData({
address: account.address,
domain,
types,
primaryType: "Order",
message,
signature,
});
console.log("valid:", isValid);
Verificado: esta estrutura exata, executado com uma conta local real, corretamente assina e verifica. Uma carteira suportando EIP-712 mostra ao usuário o estrutura decodificada ("Ordem: comprador 0xd8dA..., quantidade 100, preço 5000") em vez de uma bolha opaca, deixando o usuário realmente avaliar o que eles estão aprovando nos mesmos termos que o próprio aplicativo usa.
O separador de domínio: evitar a repetição de aplicações cruzadas¶
A domain objeto (nome, versão, chain ID, e o endereço específico do contrato de verificação) é hashed em cada assinatura como um separador de domínio, garantindo uma assinatura válida para uma aplicação específica, numa cadeia específica, visando um contrato específico, não pode ser reproduzido contra uma aplicação diferente, uma cadeia diferente, ou um contrato diferente, mesmo que o descanso Os dados assinados são idênticos. Isso encerra uma categoria de risco real e documentada: sem separação de domínio, uma assinatura aprovada por um usuário para um propósito legítimo poderia, em princípio, ser capturada e reutilizada em algum lugar que o usuário nunca pretendeu que fosse aplicada.
Onde isso aparece na prática¶
As assinaturas EIP-712 são a base para Aprovação sem gás (o permit padrão, deixando um usuário autorizar um token gastar via assinatura sozinho, com um relé pagando o gás para enviá-lo on-chain, veja Subsídios e homologações), assinatura de ordem off-chain para trocas descentralizadas (um usuário assina um comércio pretendido uma vez; o motor de correspondência da troca só envia uma transação on-chain uma vez que uma contra-ordem é encontrada, economizando o custo de gás de postar cada ordem incomparável), e muitos outros padrões onde uma aplicação quer um compromisso criptograficamente vinculativo sem o custo imediato de uma transação on-chain.
Conceitos errôneos comuns¶
EIP-712 não torna uma assinatura inerentemente mais segura só porque é mais legível, uma carteira bem projetada mostrando uma solicitação claramente estruturada, mas ainda maliciosa (uma permissão que concede gastos ilimitados ao endereço de um atacante, claramente rotulado como tal) ainda é uma solicitação que um usuário descuidado pode aprovar; legibilidade ajuda os usuários a tomar uma decisão informada, não toma essa decisão por eles.
A permit-estilo assinatura EIP-712 não é o mesmo que uma on-chain approve transação em termos de quando produz efeito, a assinatura sozinho não concede nada até alguém (o usuário em si, ou um retransmissor em seu nome) submete-o em uma transação real que permit função, que é o que realmente atualiza o subsídio on-chain.
Outras leituras¶
- EIP-712: Hashing e assinatura de dados estruturados digitados
- EIP-2612: Autorização, 712 aprovações assinadas
← Anterior: Mensagens de assinatura · Voltar para Construindo Aplicações Web3 · Próximo: Receitas de transação →