EIP-1271 Link to heading
EIP-1271 解决的核心问题:智能合约签名验证 Link to heading
传统的签名验证只能处理 EOA(外部账户)的签名:
- 使用
ecrecover
从签名中恢复签名者地址 - 只适用于私钥控制的账户
但随着智能合约钱包的普及,出现了新问题:
- 多签钱包:需要多个签名才能执行操作
- 智能合约钱包:使用复杂逻辑控制资产
- DAO 治理:需要验证组织的"集体签名"
EIP-1271 定义了统一的接口,让智能合约能够:
- 实现自定义的签名验证逻辑
- 与现有的签名验证系统兼容
- 支持复杂的多签、阈值签名等场景
EIP-1271 标准接口 Link to heading
interface IERC1271 {
/**
* @dev 验证签名是否有效
* @param hash 要验证的数据哈希
* @param signature 签名数据
* @return magicValue 验证通过返回 0x1626ba7e,否则返回其他值
*/
function isValidSignature(
bytes32 hash,
bytes memory signature
) external view returns (bytes4 magicValue);
}
说明:
- 成功:
0x1626ba7e
(bytes4(keccak256(“isValidSignature(bytes32,bytes)”))) - 失败:返回任何其他值
示例 Link to heading
多签钱包实现 Link to heading
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract MultiSigWallet {
using ECDSA for bytes32;
// EIP-1271 魔数
bytes4 constant internal MAGICVALUE = 0x1626ba7e;
address[] public owners;
uint256 public threshold; // 需要的最少签名数
constructor(address[] memory _owners, uint256 _threshold) {
require(_threshold > 0 && _threshold <= _owners.length, "Invalid threshold");
owners = _owners;
threshold = _threshold;
}
// EIP-1271 实现
function isValidSignature(
bytes32 hash,
bytes memory signature
) external view returns (bytes4 magicValue) {
// 解析多个签名
require(signature.length % 65 == 0, "Invalid signature length");
uint256 sigCount = signature.length / 65;
require(sigCount >= threshold, "Not enough signatures");
address[] memory signers = new address[](sigCount);
// 验证每个签名
for (uint256 i = 0; i < sigCount; i++) {
bytes memory sig = new bytes(65);
for (uint256 j = 0; j < 65; j++) {
sig[j] = signature[i * 65 + j];
}
address signer = hash.recover(sig);
require(_isOwner(signer), "Invalid signer");
// 检查重复签名
for (uint256 k = 0; k < i; k++) {
require(signers[k] != signer, "Duplicate signature");
}
signers[i] = signer;
}
return MAGICVALUE;
}
function _isOwner(address addr) internal view returns (bool) {
for (uint256 i = 0; i < owners.length; i++) {
if (owners[i] == addr) {
return true;
}
}
return false;
}
}
通用签名验证器 Link to heading
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract UniversalSignatureValidator {
using ECDSA for bytes32;
bytes4 constant internal MAGICVALUE = 0x1626ba7e;
/**
* @dev 通用签名验证函数
* @param signer 签名者地址(可能是 EOA 或合约)
* @param hash 要验证的哈希
* @param signature 签名数据
*/
function isValidSignature(
address signer,
bytes32 hash,
bytes memory signature
) public view returns (bool) {
// 检查是否为合约地址
if (signer.code.length > 0) {
// 合约签名:调用 EIP-1271
try IERC1271(signer).isValidSignature(hash, signature) returns (bytes4 result) {
return result == MAGICVALUE;
} catch {
return false;
}
} else {
// EOA 签名:使用 ecrecover
address recovered = hash.recover(signature);
return recovered == signer;
}
}
}
与 EIP-712 结合使用 Link to heading
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
contract OrderValidator is EIP712 {
struct Order {
address maker;
address taker;
uint256 amount;
uint256 deadline;
}
bytes32 private constant ORDER_TYPEHASH =
keccak256("Order(address maker,address taker,uint256 amount,uint256 deadline)");
constructor() EIP712("OrderValidator", "1") {}
function validateOrder(
Order memory order,
bytes memory signature
) external view returns (bool) {
bytes32 structHash = keccak256(
abi.encode(ORDER_TYPEHASH, order.maker, order.taker, order.amount, order.deadline)
);
bytes32 hash = _hashTypedDataV4(structHash);
// 使用通用验证器
UniversalSignatureValidator validator = UniversalSignatureValidator(0x...);
return validator.isValidSignature(order.maker, hash, signature);
}
}
应用场景 Link to heading
-
多签钱包
- 需要多个所有者签名才能执行操作
- 支持阈值签名(如 3/5 多签)
-
智能合约钱包
- 基于规则的签名验证
- 社交恢复、时间锁等高级功能
-
DAO 治理
- 验证提案的"组织签名"
- 支持委托投票等复杂场景
-
DeFi 协议集成
- 让智能合约钱包能够使用 permit 功能
- 支持复杂的 DeFi 操作授权
与其他 EIP 的关系 Link to heading
- EIP-712 + EIP-1271:让智能合约能够签署和验证结构化数据
- ERC-2612 + EIP-1271:让智能合约钱包也能使用 permit 功能
- EIP-4494 + EIP-1271:智能合约钱包的 NFT permit 支持
安全注意事项 Link to heading
- 重放攻击防护:结合 nonce、chainId、deadline 等机制
- 签名唯一性:防止同一签名被多次使用
- 权限验证:确保只有授权的签名者能够通过验证
- 合约升级:考虑签名验证逻辑的升级兼容性
小结 Link to heading
- EIP-1271 为智能合约提供了标准的签名验证接口
- 支持多签、阈值签名等复杂的验证逻辑
- 与 EIP-712 结合,实现结构化数据的合约签名
- 是智能合约钱包和 DeFi 生态的重要基础设施