EIP-7702
2025年6月19日大约 1 分钟
EIP-7702
EIP-7702 让 EOA(Externally Owned Account)在一笔交易期间,临时变成了 OA(合约账户,Contract Account),拥有合约账户的“超能力”。
- 多签名
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract EIP7702Multisig {
uint256 public threshold;
mapping(address => bool) public isSigner;
event Executed(address target, uint256 value, bytes data);
constructor(address[] memory _signers, uint256 _threshold) {
require(_signers.length >= _threshold, "Invalid threshold");
for (uint256 i = 0; i < _signers.length; i++) {
isSigner[_signers[i]] = true;
}
threshold = _threshold;
}
function execute(
address target,
uint256 value,
bytes calldata data,
bytes[] calldata signatures
) external returns (bytes memory result) {
bytes32 txHash = getTxHash(target, value, data);
_validateSignatures(txHash, signatures);
(bool success, bytes memory res) = target.call{value: value}(data);
require(success, "Call failed");
emit Executed(target, value, data);
return res;
}
function getTxHash(
address target,
uint256 value,
bytes memory data
) public view returns (bytes32) {
return keccak256(abi.encodePacked(address(this), block.chainid, target, value, data));
}
function _validateSignatures(
bytes32 txHash,
bytes[] calldata signatures
) internal view {
uint256 valid = 0;
address[] memory seen = new address[](signatures.length);
for (uint256 i = 0; i < signatures.length; i++) {
address signer = recoverSigner(txHash, signatures[i]);
require(isSigner[signer], "Invalid signer");
// Ensure no duplicates
for (uint256 j = 0; j < i; j++) {
require(seen[j] != signer, "Duplicate signer");
}
seen[i] = signer;
valid++;
}
require(valid >= threshold, "Not enough valid signatures");
}
function recoverSigner(bytes32 hash, bytes memory signature) public pure returns (address) {
bytes32 ethSignedHash = toEthSignedMessageHash(hash);
(bytes32 r, bytes32 s, uint8 v) = splitSignature(signature);
return ecrecover(ethSignedHash, v, r, s);
}
function toEthSignedMessageHash(bytes32 hash) public pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
function splitSignature(
bytes memory sig
) public pure returns (bytes32 r, bytes32 s, uint8 v) {
require(sig.length == 65, "Bad sig length");
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
}
receive() external payable {}
}