rcxcob2016 / eip712
生成用于签名的 Eip712 哈希
Requires
- illuminate/collections: ^8.0|^9.0|^10.9
- illuminate/support: ^8.0|^9.0|^10.9
- kornrunner/keccak: ^1.1
- kornrunner/solidity: ^0.2.0
- sleefinance/simple-web3-php: ^0.12.0
Requires (Dev)
- barryvdh/laravel-ide-helper: ^2.13
- orchestra/testbench: ^8.5
README
这是一个 Laravel / PHP 库,用于帮助生成基于 EIP-712 的签名和验证消息的 EIP712 哈希。它完全为 php 8.0 编写,目前仅与 EIP-712 的最新规范兼容(eth_signTypedData_v4)。
https://eips.ethereum.org/EIPS/eip-712
注意,这个库目前不处理签名本身。为此,您可以使用类似 kornrunner\Secp256k1
的工具。以下是一些示例。
安装
$ composer require sleepfinance/eip712
入门指南
首先,将您的类型数据定义为 EIP-712 指定的 JSON 模式下的 JSON 字符串或 PHP 数组。例如
{ "types": { "EIP712Domain": [ { "name": "name", "type": "string" }, { "name": "version", "type": "string" }, { "name": "chainId", "type": "uint256" }, { "name": "verifyingContract", "type": "address" } ], "Person": [ { "name": "name", "type": "string" }, { "name": "wallet", "type": "address" } ], "Mail": [ { "name": "from", "type": "Person" }, { "name": "to", "type": "Person" }, { "name": "contents", "type": "string" } ] }, "primaryType": "Mail", "domain": { "name": "Ether Mail", "version": "1", "chainId": 1, "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" }, "message": { "from": { "name": "Cow", "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" }, "to": { "name": "Bob", "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" }, "contents": "Hello, Bob!" } }
示例
use SleepFinance\Eip712; use kornrunner\Secp256k1; // import the EIP-712 json fil; $mailTypedJson = file_get_contents('path/to/your-json-file.json'); $eip712 = new Eip712($mailTypedJson); $hashToSign = $eip712->hashTypedDataV4(); //signing with account 0xf3022686aa43B98362c989659561b9B348977897 $pvk="0x2870b52bfe2401ac0eed7f62fd4bd03eb579c61369c6b4dd6931fb4a57d71b09"; $secp256k1 = new Secp256k1(); $signed = $secp256k1->sign($hashToSign, $pvk); //Hex $signatureToSubmit = $signed->toHex();
允许数组
use SleepFinance\Eip712; use kornrunner\Secp256k1; $mailTypedData = [ "types" => [ "EIP712Domain" => [ [ "name" => "name", "type" => "string" ], [ "name" => "version", "type" => "string" ], [ "name" => "chainId", "type" => "uint256" ], [ "name" => "verifyingContract", "type" => "address" ] ], "Person" => [ [ "name" => "name", "type" => "string" ], [ "name" => "wallet", "type" => "address" ] ], "Mail" => [ [ "name" => "from", "type" => "Person" ], [ "name" => "to", "type" => "Person" ], [ "name" => "contents", "type" => "string" ] ] ], "primaryType" => "Mail", "domain" => [ "name" => "Ether Mail", "version" => "1", "chainId" => 1, "verifyingContract" => "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" ], "message" => [ "from" => [ "name" => "Cow", "wallet" => "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" ], "to" => [ "name" => "Bob", "wallet" => "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" ], "contents" => "Hello, Bob!" ] ]; $eip712 = new Eip712($mailTypedData); $hashToSign = $eip712->hashTypedDataV4(); //signing with account 0xf3022686aa43B98362c989659561b9B348977897 $pvk="0x2870b52bfe2401ac0eed7f62fd4bd03eb579c61369c6b4dd6931fb4a57d71b09"; $secp256k1 = new Secp256k1(); $signed = $secp256k1->sign($hashToSign, $pvk); //Hex $signatureToSubmit = $signed->toHex();
有时您可能需要重新组合签名!!
有时 $signatureToSubmit = $signed->toHex();
的十六进制不工作。您可能需要重新组合签名
$signed = $secp256k1->sign($hashToSign, $pvk); //$signatureToSubmit = $signed->toHex(); $r = $this->hexup(gmp_strval($signed->getR(), 16)); $s = $this->hexup(gmp_strval($signed->getS(), 16)); $v = dechex((int) $signed->getRecoveryParam() + 27); $signatureToSubmit = "0x$r$s$v"; ---- function hexup(string $value): string { return strlen($value) % 2 === 0 ? $value : "0{$value}"; }
编码函数
以下是对编码器中可用函数的简要描述。有关更详细的示例,请参阅 src/tests
。
Encoder::encode(SleepFinance\Eip712 $typedData)
此函数将返回要使用 Keccak256 签名哈希的完整 EIP-191 编码的消息。
use SleepFinance\Encoder; $mailTypedJson = file_get_contents('path/to/your-json-file.json'); $eip712 = new Eip712($mailTypedJson); $hashToSign = Encoder::encode($eip712); dump($hashToSign); //be609aee343fb3c4b28e1df9e632fca64fcfaede20f02e86244efddf30957bd2
Encoder::getStructHash(SleepFinance\Eip712 $typedData, $type, $data)
此函数返回单个结构类型的 Keccak-256 哈希(例如 EIP712Domain,Person 或 Mail)。
use SleepFinance\Encoder; $mailTypedJson = file_get_contents('path/to/your-json-file.json'); $eip712 = new Eip712($mailTypedJson); $hash = Encoder::getStructHash($eip712, "EIP712Domain", $eip712->domain); dump($hash); // f2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f
Encoder::encodeData(Eip712 $typedData, string $type, data)
此函数返回结构类型的原始 ABI 编码数据。
use SleepFinance\Encoder; $mailTypedJson = file_get_contents('path/to/your-json-file.json'); $eip712 = new Eip712($mailTypedJson); $abiEncodedData = Encoder::encodeData($eip712, "EIP712Domain", $eip712->domain); dump($abiEncodedData); // 8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400fc70ef06638535b4881fafcac8287e210e3769ff1a8e91f1b95d6246e61e4d3c6c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cccccccccccccccccccccccccccccccccccccccc
Encoder::getTypeHash(Eip712 $typedData, string $type)
此函数返回结构类型的类型哈希。这与 Keccak256(EIP712Domain(string name,string version,uint256 chainId,address verifyingContract))
相同,并支持自动包含可选子类型。
use SleepFinance\Encoder; $mailTypedJson = file_get_contents('path/to/your-json-file.json'); $eip712 = new Eip712($mailTypedJson); $typeHash = Encoder::getTypeHash($eip712, "EIP712Domain"); dump($typeHash); // 8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f
Encoder::encodeType(Eip712 $typedData, string $type)
此函数返回在哈希之前要编码的类型字符串,例如 EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)
,并自动包含可选子类型。
use SleepFinance\Encoder; $mailTypedJson = file_get_contents('path/to/your-json-file.json'); $eip712 = new Eip712($mailTypedJson); $encodedType = Encoder::encodeType($eip712, "EIP712Domain"); dump($encodedType); // EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)
目前尚未测试非标准域!
如果您想使用 EIP-712 的自定义实现,可以像 CIP-23 规范一样使用自定义域格式。
为此,用您的自定义域初始化 EIP172;将跳过模式验证!
$eip712 = new Eip712($mailTypedJson, 'MyCustomDomain');
twitter Telegram