rcxcob2016/eip712

生成用于签名的 Eip712 哈希

v1.0.1 2024-01-16 08:45 UTC

This package is auto-updated.

Last update: 2024-09-16 10:12:29 UTC


README

PHP codecov Licensed under the MIT License

这是一个 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

在另一边见!