Created
October 5, 2023 18:17
-
-
Save xinbenlv/55fe92093f53964233891bc19067a21e to your computer and use it in GitHub Desktop.
Demonstrate Old and New Output from eip712-codegen
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.8.13; | |
// SPDX-License-Identifier: MIT | |
struct SignedReplayProtection { | |
ReplayProtection message; | |
bytes signature; | |
address signer; | |
} | |
bytes32 constant signedReplayProtectionTypehash = keccak256("SignedReplayProtection(ReplayProtection message,bytes signature,address signer)ReplayProtection(uint nonce,uint queue)"); | |
struct EIP712Domain { | |
string name; | |
string version; | |
uint256 chainId; | |
address verifyingContract; | |
} | |
bytes32 constant eip712DomainTypehash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); | |
struct Invocation { | |
Transaction transaction; | |
SignedDelegation[] authority; | |
} | |
bytes32 constant invocationTypehash = keccak256("Invocation(Transaction transaction,SignedDelegation[] authority)Caveat(address enforcer,bytes terms)Delegation(address delegate,bytes32 authority,Caveat[] caveats)SignedDelegation(Delegation delegation,bytes signature)Transaction(address to,uint256 gasLimit,bytes data)"); | |
struct Invocations { | |
Invocation[] batch; | |
ReplayProtection replayProtection; | |
} | |
bytes32 constant invocationsTypehash = keccak256("Invocations(Invocation[] batch,ReplayProtection replayProtection)Caveat(address enforcer,bytes terms)Delegation(address delegate,bytes32 authority,Caveat[] caveats)Invocation(Transaction transaction,SignedDelegation[] authority)ReplayProtection(uint nonce,uint queue)SignedDelegation(Delegation delegation,bytes signature)Transaction(address to,uint256 gasLimit,bytes data)"); | |
struct Transaction { | |
address to; | |
uint256 gasLimit; | |
bytes data; | |
} | |
bytes32 constant transactionTypehash = keccak256("Transaction(address to,uint256 gasLimit,bytes data)"); | |
struct ReplayProtection { | |
uint nonce; | |
uint queue; | |
} | |
bytes32 constant replayProtectionTypehash = keccak256("ReplayProtection(uint nonce,uint queue)"); | |
struct Delegation { | |
address delegate; | |
bytes32 authority; | |
Caveat[] caveats; | |
} | |
bytes32 constant delegationTypehash = keccak256("Delegation(address delegate,bytes32 authority,Caveat[] caveats)Caveat(address enforcer,bytes terms)"); | |
struct Caveat { | |
address enforcer; | |
bytes terms; | |
} | |
bytes32 constant caveatTypehash = keccak256("Caveat(address enforcer,bytes terms)"); | |
abstract contract ERC1271Contract { | |
/** | |
* @dev Should return whether the signature provided is valid for the provided hash | |
* @param _hash Hash of the data to be signed | |
* @param _signature Signature byte array associated with _hash | |
* | |
* MUST return the bytes4 magic value 0x1626ba7e when function passes. | |
* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) | |
* MUST allow external calls | |
*/ | |
function isValidSignature( | |
bytes32 _hash, | |
bytes memory _signature) | |
public | |
view | |
virtual | |
returns (bytes4 magicValue); | |
} | |
abstract contract EIP712Decoder { | |
function getDomainHash () public view virtual returns (bytes32); | |
/** | |
* @dev Recover signer address from a message by using their signature | |
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. | |
* @param sig bytes signature, the signature is generated using web3.eth.sign() | |
*/ | |
function recover(bytes32 hash, bytes memory sig) internal pure returns (address) { | |
bytes32 r; | |
bytes32 s; | |
uint8 v; | |
// Check the signature length | |
if (sig.length != 65) { | |
return (address(0)); | |
} | |
// Divide the signature in r, s and v variables | |
assembly { | |
r := mload(add(sig, 32)) | |
s := mload(add(sig, 64)) | |
v := byte(0, mload(add(sig, 96))) | |
} | |
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions | |
if (v < 27) { | |
v += 27; | |
} | |
// If the version is correct return the signer address | |
if (v != 27 && v != 28) { | |
return (address(0)); | |
} else { | |
return ecrecover(hash, v, r, s); | |
} | |
} | |
function getSignedReplayProtectionPacketHash (SignedReplayProtection memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
signedreplayprotectionTypehash, | |
getReplayProtectionPacketHash(_input.message), | |
keccak256(_input.signature), | |
_input.signer | |
); | |
return keccak256(encoded); | |
} | |
function getEip_712DomainPacketHash (EIP712Domain memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
eip712DomainTypehash, | |
keccak256(bytes(_input.name)), | |
keccak256(bytes(_input.version)), | |
_input.chainId, | |
_input.verifyingContract | |
); | |
return keccak256(encoded); | |
} | |
function getInvocationPacketHash (Invocation memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
invocationTypehash, | |
getTransactionPacketHash(_input.transaction), | |
getSignedDelegationArrayPacketHash(_input.authority) | |
); | |
return keccak256(encoded); | |
} | |
function getSignedDelegationArrayPacketHash (SignedDelegation[] memory _input) public pure returns (bytes32) { | |
bytes memory encoded; | |
// HELLO | |
for (uint i = 0; i < _input.length; i++) { | |
encoded = abi.encodePacked(encoded, getSignedDelegationPacketHash(_input[i])); | |
} | |
return keccak256(encoded); | |
} | |
function getInvocationArrayPacketHash (Invocation[] memory _input) public pure returns (bytes32) { | |
bytes memory encoded; | |
// HELLO | |
for (uint i = 0; i < _input.length; i++) { | |
encoded = abi.encodePacked(encoded, getInvocationPacketHash(_input[i])); | |
} | |
return keccak256(encoded); | |
} | |
function getInvocationsPacketHash (Invocations memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
invocationsTypehash, | |
getInvocationArrayPacketHash(_input.batch), | |
getReplayProtectionPacketHash(_input.replayProtection) | |
); | |
return keccak256(encoded); | |
} | |
function getTransactionPacketHash (Transaction memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
transactionTypehash, | |
_input.to, | |
_input.gasLimit, | |
keccak256(_input.data) | |
); | |
return keccak256(encoded); | |
} | |
function getReplayProtectionPacketHash (ReplayProtection memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
replayprotectionTypehash, | |
_input.nonce, | |
_input.queue | |
); | |
return keccak256(encoded); | |
} | |
function getDelegationPacketHash (Delegation memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
delegationTypehash, | |
_input.delegate, | |
_input.authority, | |
getCaveatArrayPacketHash(_input.caveats) | |
); | |
return keccak256(encoded); | |
} | |
function getCaveatArrayPacketHash (Caveat[] memory _input) public pure returns (bytes32) { | |
bytes memory encoded; | |
// HELLO | |
for (uint i = 0; i < _input.length; i++) { | |
encoded = abi.encodePacked(encoded, getCaveatPacketHash(_input[i])); | |
} | |
return keccak256(encoded); | |
} | |
function getCaveatPacketHash (Caveat memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
caveatTypehash, | |
_input.enforcer, | |
keccak256(_input.terms) | |
); | |
return keccak256(encoded); | |
} | |
function verifySignedReplayProtection(SignedReplayProtection memory _input) public view returns (address) { | |
bytes32 packetHash = getReplayProtectionPacketHash(_input.message); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
getDomainHash(), | |
packetHash | |
) | |
); | |
if (_input.signer == 0x0000000000000000000000000000000000000000) { | |
address recoveredSigner = recover( | |
digest, | |
_input.signature | |
); | |
return recoveredSigner; | |
} else { | |
// EIP-1271 signature verification | |
bytes4 result = ERC1271Contract(_input.signer).isValidSignature(digest, _input.signature); | |
require(result == 0x1626ba7e, "INVALID_SIGNATURE"); | |
return _input.signer; | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.8.13; | |
// SPDX-License-Identifier: MIT | |
struct SignedReplayProtection { | |
ReplayProtection message; | |
bytes signature; | |
address signer; | |
} | |
bytes32 constant signedreplayprotectionTypehash = keccak256("SignedReplayProtection(ReplayProtection message,bytes signature,address signer)ReplayProtection(uint nonce,uint queue)"); | |
struct EIP712Domain { | |
string name; | |
string version; | |
uint256 chainId; | |
address verifyingContract; | |
} | |
bytes32 constant eip712domainTypehash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); | |
struct Invocation { | |
Transaction transaction; | |
SignedDelegation[] authority; | |
} | |
bytes32 constant invocationTypehash = keccak256("Invocation(Transaction transaction,SignedDelegation[] authority)Caveat(address enforcer,bytes terms)Delegation(address delegate,bytes32 authority,Caveat[] caveats)SignedDelegation(Delegation delegation,bytes signature)Transaction(address to,uint256 gasLimit,bytes data)"); | |
struct Invocations { | |
Invocation[] batch; | |
ReplayProtection replayProtection; | |
} | |
bytes32 constant invocationsTypehash = keccak256("Invocations(Invocation[] batch,ReplayProtection replayProtection)Caveat(address enforcer,bytes terms)Delegation(address delegate,bytes32 authority,Caveat[] caveats)Invocation(Transaction transaction,SignedDelegation[] authority)ReplayProtection(uint nonce,uint queue)SignedDelegation(Delegation delegation,bytes signature)Transaction(address to,uint256 gasLimit,bytes data)"); | |
struct Transaction { | |
address to; | |
uint256 gasLimit; | |
bytes data; | |
} | |
bytes32 constant transactionTypehash = keccak256("Transaction(address to,uint256 gasLimit,bytes data)"); | |
struct ReplayProtection { | |
uint nonce; | |
uint queue; | |
} | |
bytes32 constant replayprotectionTypehash = keccak256("ReplayProtection(uint nonce,uint queue)"); | |
struct Delegation { | |
address delegate; | |
bytes32 authority; | |
Caveat[] caveats; | |
} | |
bytes32 constant delegationTypehash = keccak256("Delegation(address delegate,bytes32 authority,Caveat[] caveats)Caveat(address enforcer,bytes terms)"); | |
struct Caveat { | |
address enforcer; | |
bytes terms; | |
} | |
bytes32 constant caveatTypehash = keccak256("Caveat(address enforcer,bytes terms)"); | |
abstract contract ERC1271Contract { | |
/** | |
* @dev Should return whether the signature provided is valid for the provided hash | |
* @param _hash Hash of the data to be signed | |
* @param _signature Signature byte array associated with _hash | |
* | |
* MUST return the bytes4 magic value 0x1626ba7e when function passes. | |
* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) | |
* MUST allow external calls | |
*/ | |
function isValidSignature( | |
bytes32 _hash, | |
bytes memory _signature) | |
public | |
view | |
virtual | |
returns (bytes4 magicValue); | |
} | |
abstract contract EIP712Decoder { | |
function getDomainHash () public view virtual returns (bytes32); | |
/** | |
* @dev Recover signer address from a message by using their signature | |
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. | |
* @param sig bytes signature, the signature is generated using web3.eth.sign() | |
*/ | |
function recover(bytes32 hash, bytes memory sig) internal pure returns (address) { | |
bytes32 r; | |
bytes32 s; | |
uint8 v; | |
// Check the signature length | |
if (sig.length != 65) { | |
return (address(0)); | |
} | |
// Divide the signature in r, s and v variables | |
assembly { | |
r := mload(add(sig, 32)) | |
s := mload(add(sig, 64)) | |
v := byte(0, mload(add(sig, 96))) | |
} | |
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions | |
if (v < 27) { | |
v += 27; | |
} | |
// If the version is correct return the signer address | |
if (v != 27 && v != 28) { | |
return (address(0)); | |
} else { | |
return ecrecover(hash, v, r, s); | |
} | |
} | |
function getSignedreplayprotectionPacketHash (SignedReplayProtection memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
signedreplayprotectionTypehash, | |
getReplayprotectionPacketHash(_input.message), | |
keccak256(_input.signature), | |
_input.signer | |
); | |
return keccak256(encoded); | |
} | |
function getEip712DomainPacketHash (EIP712Domain memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
eip712domainTypehash, | |
keccak256(bytes(_input.name)), | |
keccak256(bytes(_input.version)), | |
_input.chainId, | |
_input.verifyingContract | |
); | |
return keccak256(encoded); | |
} | |
function getInvocationPacketHash (Invocation memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
invocationTypehash, | |
getTransactionPacketHash(_input.transaction), | |
getSigneddelegationArrayPacketHash(_input.authority) | |
); | |
return keccak256(encoded); | |
} | |
function getSigneddelegationArrayPacketHash (SignedDelegation[] memory _input) public pure returns (bytes32) { | |
bytes memory encoded; | |
// HELLO | |
for (uint i = 0; i < _input.length; i++) { | |
encoded = abi.encodePacked(encoded, getSigneddelegationPacketHash(_input[i])); | |
} | |
return keccak256(encoded); | |
} | |
function getInvocationArrayPacketHash (Invocation[] memory _input) public pure returns (bytes32) { | |
bytes memory encoded; | |
// HELLO | |
for (uint i = 0; i < _input.length; i++) { | |
encoded = abi.encodePacked(encoded, getInvocationPacketHash(_input[i])); | |
} | |
return keccak256(encoded); | |
} | |
function getInvocationsPacketHash (Invocations memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
invocationsTypehash, | |
getInvocationArrayPacketHash(_input.batch), | |
getReplayprotectionPacketHash(_input.replayProtection) | |
); | |
return keccak256(encoded); | |
} | |
function getTransactionPacketHash (Transaction memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
transactionTypehash, | |
_input.to, | |
_input.gasLimit, | |
keccak256(_input.data) | |
); | |
return keccak256(encoded); | |
} | |
function getReplayprotectionPacketHash (ReplayProtection memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
replayprotectionTypehash, | |
_input.nonce, | |
_input.queue | |
); | |
return keccak256(encoded); | |
} | |
function getDelegationPacketHash (Delegation memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
delegationTypehash, | |
_input.delegate, | |
_input.authority, | |
getCaveatArrayPacketHash(_input.caveats) | |
); | |
return keccak256(encoded); | |
} | |
function getCaveatArrayPacketHash (Caveat[] memory _input) public pure returns (bytes32) { | |
bytes memory encoded; | |
// HELLO | |
for (uint i = 0; i < _input.length; i++) { | |
encoded = abi.encodePacked(encoded, getCaveatPacketHash(_input[i])); | |
} | |
return keccak256(encoded); | |
} | |
function getCaveatPacketHash (Caveat memory _input) public pure returns (bytes32) { | |
bytes memory encoded = abi.encode( | |
caveatTypehash, | |
_input.enforcer, | |
keccak256(_input.terms) | |
); | |
return keccak256(encoded); | |
} | |
function verifySignedReplayProtection(SignedReplayProtection memory _input) public view returns (address) { | |
bytes32 packetHash = getReplayprotectionPacketHash(_input.message); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
getDomainHash(), | |
packetHash | |
) | |
); | |
if (_input.signer == 0x0000000000000000000000000000000000000000) { | |
address recoveredSigner = recover( | |
digest, | |
_input.signature | |
); | |
return recoveredSigner; | |
} else { | |
// EIP-1271 signature verification | |
bytes4 result = ERC1271Contract(_input.signer).isValidSignature(digest, _input.signature); | |
require(result == 0x1626ba7e, "INVALID_SIGNATURE"); | |
return _input.signer; | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment