Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized committed Jan 31, 2025
1 parent fbd9b55 commit c360dee
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 80 deletions.
56 changes: 30 additions & 26 deletions src/utils/EIP712.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ abstract contract EIP712 {
0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

/// @dev `keccak256("EIP712Domain(string name,string version,address verifyingContract)")`.
/// This is only used in `_hashTypedDataWithoutChainId`.
bytes32 internal constant _DOMAIN_TYPEHASH_WITHOUT_CHAINID =
0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766;

Expand Down Expand Up @@ -54,20 +55,15 @@ abstract contract EIP712 {

bytes32 separator;
if (!_domainNameAndVersionMayChange()) {
bool z = _domainSeparatorWithoutChainId();
/// @solidity memory-safe-assembly
assembly {
z := iszero(z)
let m := mload(0x40) // Load the free memory pointer.
// forgefmt: disable-next-item
mstore(m,
xor(_DOMAIN_TYPEHASH_WITHOUT_CHAINID,
mul(z, xor(_DOMAIN_TYPEHASH, _DOMAIN_TYPEHASH_WITHOUT_CHAINID))))
mstore(m, _DOMAIN_TYPEHASH)
mstore(add(m, 0x20), nameHash)
mstore(add(m, 0x40), versionHash)
mstore(add(m, 0x60), chainid())
mstore(add(m, add(0x60, shl(5, z))), address())
separator := keccak256(m, add(0x80, shl(5, z)))
mstore(add(m, 0x80), address())
separator := keccak256(m, 0xa0)
}
}
_cachedDomainSeparator = separator;
Expand Down Expand Up @@ -103,10 +99,6 @@ abstract contract EIP712 {
/// Default: false.
function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}

/// @dev Returns if `_domainSeparator()` without chain Id.
/// Default: false.
function _domainSeparatorWithoutChainId() internal pure virtual returns (bool result) {}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
Expand Down Expand Up @@ -154,6 +146,27 @@ abstract contract EIP712 {
}
}

/// @dev Variant that excludes the chain ID.
/// Optimized for smaller bytecode size over runtime gas, as it is intended to be used sparingly.
function _hashTypedDataWithoutChainId(bytes32 structHash) internal view virtual returns (bytes32 digest) {
(string memory name, string memory version) = _domainNameAndVersion();
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Load the free memory pointer.
mstore(0x00, _DOMAIN_TYPEHASH_WITHOUT_CHAINID)
mstore(0x20, keccak256(add(name, 0x20), mload(name)))
mstore(0x40, keccak256(add(version, 0x20), mload(version)))
mstore(0x60, address())
// Compute the digest.
mstore(0x20, keccak256(0x00, 0x80)) // Store the domain separator.
mstore(0x00, 0x1901) // Store "\x19\x01".
mstore(0x40, structHash) // Store the struct hash.
digest := keccak256(0x1e, 0x42)
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero pointer.
}
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EIP-5267 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
Expand All @@ -174,7 +187,6 @@ abstract contract EIP712 {
)
{
fields = hex"0f"; // `0b01111`.
if (_domainSeparatorWithoutChainId()) fields = hex"0b"; // `0b01011`.
(name, version) = _domainNameAndVersion();
chainId = block.chainid;
verifyingContract = address(this);
Expand All @@ -198,33 +210,25 @@ abstract contract EIP712 {
separator = _cachedNameHash;
versionHash = _cachedVersionHash;
}
bool z = _domainSeparatorWithoutChainId();
/// @solidity memory-safe-assembly
assembly {
z := iszero(z)
let m := mload(0x40) // Load the free memory pointer.
// forgefmt: disable-next-item
mstore(m,
xor(_DOMAIN_TYPEHASH_WITHOUT_CHAINID,
mul(z, xor(_DOMAIN_TYPEHASH, _DOMAIN_TYPEHASH_WITHOUT_CHAINID))))
mstore(add(m, 0x20), separator)
mstore(m, _DOMAIN_TYPEHASH)
mstore(add(m, 0x20), separator) // Name hash.
mstore(add(m, 0x40), versionHash)
mstore(add(m, 0x60), chainid())
mstore(add(m, add(0x60, shl(5, z))), address())
separator := keccak256(m, add(0x80, shl(5, z)))
mstore(add(m, 0x80), address())
separator := keccak256(m, 0xa0)
}
}

/// @dev Returns if the cached domain separator has been invalidated.
function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
uint256 cachedChainId = _cachedChainId;
uint256 cachedThis = _cachedThis;
bool z = _domainSeparatorWithoutChainId();
/// @solidity memory-safe-assembly
assembly {
// forgefmt: disable-next-item
result := iszero(and(or(iszero(iszero(z)), eq(chainid(), cachedChainId)),
eq(address(), cachedThis)))
result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
}
}
}
8 changes: 1 addition & 7 deletions test/EIP712.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ pragma solidity ^0.8.4;
import "./utils/SoladyTest.sol";
import {MockEIP712} from "./utils/mocks/MockEIP712.sol";
import {MockEIP712Dynamic} from "./utils/mocks/MockEIP712Dynamic.sol";
import {MockEIP712DyanmicWithoutChainId} from "./utils/mocks/MockEIP712DyanmicWithoutChainId.sol";
import {LibClone} from "../src/utils/LibClone.sol";

contract EIP712Test is SoladyTest {
MockEIP712 mock;
MockEIP712 mockClone;
MockEIP712DyanmicWithoutChainId mockWithoutChainId;
MockEIP712DyanmicWithoutChainId mockWithoutChainIdClone;
MockEIP712Dynamic mockDynamic;
MockEIP712Dynamic mockDynamicClone;

Expand All @@ -20,9 +17,6 @@ contract EIP712Test is SoladyTest {
mockClone = MockEIP712(LibClone.clone(address(mock)));
mockDynamic = new MockEIP712Dynamic("Milady", "1");
mockDynamicClone = MockEIP712Dynamic(LibClone.clone(address(mockDynamic)));
mockWithoutChainId = new MockEIP712DyanmicWithoutChainId("Milady", "1");
mockWithoutChainIdClone =
MockEIP712DyanmicWithoutChainId(LibClone.clone(address(mockWithoutChainId)));
}

function testHashTypedData() public {
Expand All @@ -41,7 +35,7 @@ contract EIP712Test is SoladyTest {
_testHashTypedDataOnClone(MockEIP712(address(mockDynamicClone)));
}

function testHashTypedDataOnDynamicWithOutChainId() public {
function testHashTypedDataWithOutChainId() public {
_testHashTypedDataOnClone(MockEIP712(address(mockWithoutChainId)));
}

Expand Down
47 changes: 0 additions & 47 deletions test/utils/mocks/MockEIP712DyanmicWithoutChainId.sol

This file was deleted.

0 comments on commit c360dee

Please sign in to comment.