From d65f1581f0224d1f6caf69de271153766a23ca32 Mon Sep 17 00:00:00 2001 From: Alice <34962750+hensha256@users.noreply.github.com> Date: Sun, 4 Aug 2024 16:38:15 +0100 Subject: [PATCH] Optimise permit hashing (#260) * permit hash in assembly * fuzz test --- .forge-snapshots/PositionManager_permit.snap | 2 +- .../PositionManager_permit_secondPosition.snap | 2 +- .../PositionManager_permit_twice.snap | 2 +- src/libraries/ERC721PermitHash.sol | 17 +++++++++++++++-- test/ERC721Permit.t.sol | 6 ++++++ 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/.forge-snapshots/PositionManager_permit.snap b/.forge-snapshots/PositionManager_permit.snap index b2faa7cc..dfab40b6 100644 --- a/.forge-snapshots/PositionManager_permit.snap +++ b/.forge-snapshots/PositionManager_permit.snap @@ -1 +1 @@ -79585 \ No newline at end of file +79486 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_permit_secondPosition.snap b/.forge-snapshots/PositionManager_permit_secondPosition.snap index 60f10b03..19350c74 100644 --- a/.forge-snapshots/PositionManager_permit_secondPosition.snap +++ b/.forge-snapshots/PositionManager_permit_secondPosition.snap @@ -1 +1 @@ -62497 \ No newline at end of file +62398 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_permit_twice.snap b/.forge-snapshots/PositionManager_permit_twice.snap index 3df69310..ecadddb0 100644 --- a/.forge-snapshots/PositionManager_permit_twice.snap +++ b/.forge-snapshots/PositionManager_permit_twice.snap @@ -1 +1 @@ -45397 \ No newline at end of file +45298 \ No newline at end of file diff --git a/src/libraries/ERC721PermitHash.sol b/src/libraries/ERC721PermitHash.sol index cf4c74f0..9a36d6de 100644 --- a/src/libraries/ERC721PermitHash.sol +++ b/src/libraries/ERC721PermitHash.sol @@ -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) + } } } diff --git a/test/ERC721Permit.t.sol b/test/ERC721Permit.t.sol index d7126223..16f4f39f 100644 --- a/test/ERC721Permit.t.sol +++ b/test/ERC721Permit.t.sol @@ -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(),