ERC-7015: NFT 创建者署名
使用密码学安全创建者署名扩展 NFT。
Authors | indreams (@strollinghome) |
---|---|
Created | 2023-05-11 |
Requires | EIP-55, EIP-155, EIP-712, EIP-721, EIP-1155 |
摘要
本以太坊改进提案旨在解决非同质化代币 (NFT) 标准(ERC-721、ERC-1155)的创建者署名问题。 为此,本 EIP 提出了一种机制,其中 NFT 创建者签署创建 NFT 所需的参数,包括 NFT 元数据哈希以及任何其他相关信息。 然后,已签名的参数和签名在部署交易期间进行验证和发出,这允许 NFT 验证创建者,并允许NFT平台正确地署名。 这种方法确保即使不同的钱包发送部署交易,也会将正确的帐户归属为创建者。
动机
当前的 NFT 平台假定部署智能合约的钱包是 NFT 的创建者,这导致在不同的钱包发送部署交易的情况下出现署名错误。 当使用智能钱包帐户以及新的合约部署策略(例如第一个收集者部署 NFT 合约)时,这种情况经常发生。 本提案旨在通过允许创建者签署创建 NFT 所需的参数来解决该问题,以便任何钱包都可以发送部署交易,并以可验证的方式表明谁是创建者。
规范
本文档中的关键词“必须(MUST)”,“禁止(MUST NOT)”,“需要(REQUIRED)”,“应该(SHALL)”,“不应该(SHALL NOT)”,“应当(SHOULD)”,“不应当(SHOULD NOT)”,“推荐(RECOMMENDED)”,“可以(MAY)”和“可选(OPTIONAL)”应按照 RFC 2119 中的描述进行解释。
符合 ERC-721 和 ERC-1155 标准的合约可以实现此 NFT 创建者署名扩展,以提供一个可在合约创建时发出的标准事件,以定义 NFT 创建者。
本 EIP 利用了可以在部署合约之前预先计算合约地址这一事实。 无论 NFT 合约是通过另一个合约(工厂)还是通过 EOA 部署,都可以使用此规范正确地署名创建者。
签名机制
创建者通过签署与 EIP-712 兼容的消息来表示同意; 所有符合本 EIP 的签名必须包括所有已定义的字段。 签名的结构可以是定义如何创建代币的任何任意数据; 必须以符合 EIP-712 的格式(带有适当的 EIP-712 域)对其进行哈希处理。
以下显示了一些可以编码到 structHash
中的结构示例(如下定义):
// 可以在 `structHash` 中编码的结构示例;定义可以用 metadataUri 和价格创建代币:
struct TokenCreation {
string metadataUri;
uint256 price;
uint256 nonce;
}
签名验证
创建者署名通过签名验证给出,签名验证必须由正在部署的 NFT 合约进行验证,并且一个事件必须由 NFT 合约在部署交易期间发出。 该事件包括重建签名摘要并验证签名以确保其与指定的创建者匹配的所有必要字段。 该事件名称为 CreatorAttribution
,包括以下字段:
structHash
:用于部署 NFT 合约的哈希信息(例如,名称、符号、管理员等)。 这对应于 hashStruct 的 EIP-712 定义 标准中定义的hashStruct
值。domainName
:验证签名的合约的域名(用于 EIP-712 签名验证)。version
:验证签名的合约的版本(用于 EIP-712 签名验证)creator
:创建者的帐户signature
:创建者的签名
该事件定义如下:
event CreatorAttribution(
bytes32 structHash,
string domainName,
string version,
address creator,
bytes signature
);
请注意,虽然 chainId
参数对于 EIP-712 签名是必需的,但我们从事件中省略了该参数,因为可以通过交易数据推断出该参数。 类似地,签名验证的 verifyingContract
参数也被省略,因为它必须与交易中的 emitter
字段相同。 emitter
必须是代币。
平台可以通过使用发出的参数重建签名摘要并从 signature
参数中恢复签名者来验证创建者署名的有效性。 恢复的签名者必须与事件中发出的 creator
匹配。 如果存在 CreatorAttribution
事件,并且签名已正确验证,则必须将署名授予 creator
,而不是提交交易的帐户。
参考实现
签名验证器示例
pragma solidity 0.8.20;
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
abstract contract ERC7015 is EIP712 {
error Invalid_Signature();
event CreatorAttribution(
bytes32 structHash,
string domainName,
string version,
address creator,
bytes signature
);
/// @notice Define magic value to verify smart contract signatures (ERC1271).
// @notice 定义魔术值以验证智能合约签名 (ERC1271)。
bytes4 internal constant MAGIC_VALUE =
bytes4(keccak256("isValidSignature(bytes32,bytes)"));
function _validateSignature(
bytes32 structHash,
address creator,
bytes memory signature
) internal {
if (!_isValid(structHash, creator, signature)) revert Invalid_Signature();
emit CreatorAttribution(structHash, "ERC7015", "1", creator, signature);
}
function _isValid(
bytes32 structHash,
address signer,
bytes memory signature
) internal view returns (bool) {
require(signer != address(0), "cannot validate");
bytes32 digest = _hashTypedDataV4(structHash);
// if smart contract is the signer, verify using ERC-1271 smart-contract
/// signature verification method
// 如果智能合约是签名者,请使用 ERC-1271 智能合约签名验证方法
if (signer.code.length != 0) {
try IERC1271(signer).isValidSignature(digest, signature) returns (
bytes4 magicValue
) {
return MAGIC_VALUE == magicValue;
} catch {
return false;
}
}
// otherwise, recover signer and validate that it matches the expected
// signer
// 否则,恢复签名者并验证它是否与预期的签名者匹配
address recoveredSigner = ECDSA.recover(digest, signature);
return recoveredSigner == signer;
}
}
理由
通过标准化 CreatorAttribution
事件,本 EIP 使平台能够在不依赖隐式假设的情况下确定创建者署名。 建立创建者署名标准使平台能够管理部署合约的复杂方面,同时保留准确的链上创建者信息。 这种方法确保了一种更可靠和透明的识别 NFT 创建者的方法,从而在 NFT 生态系统的参与者之间建立信任。
ERC-5375 尝试解决相同的问题,尽管链下数据提供了改进的向后兼容性,但确保准确且不可变的创建者署名对于 NFT 至关重要。 用于创建者署名的标准化链上方法本质上更可靠和安全。
与本提案相比,ERC-5375 不便于指定 NFT 集合中所有代币的创建者,这是一种普遍的做法,尤其是在新兴用例中。
本提案和 ERC-5375 在基于地址的创建者署名方面存在类似的局限性:
该标准定义了一个协议来验证某个地址是否提供了同意。 但是,它不能保证该地址对应于预期的创建者 […]。 证明地址与背后的实体之间的链接超出了本文档的范围。
向后兼容性
由于该标准要求在 NFT 部署交易期间发出事件,因此现有 NFT 无法实现此标准。
安全考虑
利用本提案的一种潜在攻击可能涉及欺骗创建者无意中签署创建者署名同意消息。 因此,创建者必须确保所有签名字段都对应于签名之前所需的字段。
版权
版权及相关权利通过 CC0 放弃。
Citation
Please cite this document as:
indreams (@strollinghome), "ERC-7015: NFT 创建者署名 [DRAFT]," Ethereum Improvement Proposals, no. 7015, May 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7015.