Skip to content

Instantly share code, notes, and snippets.

@xinbenlv
Created October 5, 2023 18:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xinbenlv/55fe92093f53964233891bc19067a21e to your computer and use it in GitHub Desktop.
Save xinbenlv/55fe92093f53964233891bc19067a21e to your computer and use it in GitHub Desktop.
Demonstrate Old and New Output from eip712-codegen
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;
}
}
}
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