Skip to content

Commit

Permalink
Optimise permit hashing (#260)
Browse files Browse the repository at this point in the history
* permit hash in assembly

* fuzz test
  • Loading branch information
hensha256 authored Aug 4, 2024
1 parent 86b5ea3 commit d65f158
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_permit.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
79585
79486
Original file line number Diff line number Diff line change
@@ -1 +1 @@
62497
62398
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_permit_twice.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
45397
45298
17 changes: 15 additions & 2 deletions src/libraries/ERC721PermitHash.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,20 @@ library ERC721PermitHashLibrary {
/// @dev Value is equal to keccak256("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)");
bytes32 constant PERMIT_TYPEHASH = 0x49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad;

function hash(address spender, uint256 tokenId, uint256 nonce, uint256 deadline) internal pure returns (bytes32) {
return keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, nonce, deadline));
function hash(address spender, uint256 tokenId, uint256 nonce, uint256 deadline)
internal
pure
returns (bytes32 digest)
{
// equivalent to: keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, nonce, deadline));
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(fmp, PERMIT_TYPEHASH)
mstore(add(fmp, 0x20), spender)
mstore(add(fmp, 0x40), tokenId)
mstore(add(fmp, 0x60), nonce)
mstore(add(fmp, 0x80), deadline)
digest := keccak256(fmp, 0xa0)
}
}
}
6 changes: 6 additions & 0 deletions test/ERC721Permit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ contract ERC721PermitTest is Test {
);
}

function test_fuzz_permitHash(address spender, uint256 tokenId, uint256 nonce, uint256 deadline) public view {
bytes32 expectedHash =
keccak256(abi.encode(ERC721PermitHashLibrary.PERMIT_TYPEHASH, spender, tokenId, nonce, deadline));
assertEq(expectedHash, ERC721PermitHashLibrary.hash(spender, tokenId, nonce, deadline));
}

function test_domainSeparator() public view {
assertEq(
IERC721Permit(address(erc721Permit)).DOMAIN_SEPARATOR(),
Expand Down

0 comments on commit d65f158

Please sign in to comment.