Skip to content

Commit

Permalink
[Part 2 - option 1] feat: refactor v4 to infinity (#78)
Browse files Browse the repository at this point in the history
* feat: rename _v4 to without _v4

* Update src/interfaces/external/IV3NonfungiblePositionManager.sol

Co-authored-by: Chef Omelette <[email protected]>

---------

Co-authored-by: Chef Omelette <[email protected]>
  • Loading branch information
ChefMist and chef-omelette authored Feb 5, 2025
1 parent 85c5433 commit 6d8ec06
Show file tree
Hide file tree
Showing 16 changed files with 88 additions and 88 deletions.
2 changes: 1 addition & 1 deletion src/base/SelfPermitERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity ^0.8.0;

import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC721Permit} from "../pool-cl/interfaces/IERC721Permit.sol";
import {IERC721Permit} from "../interfaces/IERC721Permit.sol";
import {ISelfPermitERC721} from "../interfaces/ISelfPermitERC721.sol";

/// @title Self Permit For ERC721
Expand Down
27 changes: 27 additions & 0 deletions src/interfaces/IERC721Permit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

/// @title ERC721 with permit
/// @notice Extension to ERC721 that includes a permit function for signature based approvals
interface IERC721Permit is IERC721 {
/// @notice The permit typehash used in the permit signature
/// @return The typehash for the permit
function PERMIT_TYPEHASH() external pure returns (bytes32);

/// @notice The domain separator used in the permit signature
/// @return The domain seperator used in encoding of permit signature
function DOMAIN_SEPARATOR() external view returns (bytes32);

/// @notice Approve of a specific token ID for spending by spender via signature
/// @param spender The account that is being approved
/// @param tokenId The ID of the token that is being approved for spending
/// @param deadline The deadline timestamp by which the call must be mined for the approve to work
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external
payable;
}
2 changes: 1 addition & 1 deletion src/interfaces/external/IV3NonfungiblePositionManager.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import {IERC721Permit} from "../../pool-cl/interfaces/IERC721Permit.sol";
import {IERC721Permit} from "../IERC721Permit.sol";

/// @title IV3NonfungiblePositionManager
/// @notice Wraps PancakeSwap V3 positions in a non-fungible token interface which allows for them to be transferred
Expand Down
8 changes: 4 additions & 4 deletions src/pool-cl/CLPositionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {ICLPositionManager} from "./interfaces/ICLPositionManager.sol";
import {CalldataDecoder} from "../libraries/CalldataDecoder.sol";
import {CLCalldataDecoder} from "./libraries/CLCalldataDecoder.sol";
import {Actions} from "../libraries/Actions.sol";
import {ERC721Permit_v4} from "./base/ERC721Permit_v4.sol";
import {ERC721Permit} from "./base/ERC721Permit.sol";
import {SlippageCheck} from "../libraries/SlippageCheck.sol";
import {Multicall} from "../base/Multicall.sol";
import {CLNotifier} from "./base/CLNotifier.sol";
Expand All @@ -37,7 +37,7 @@ import {TickMath} from "infinity-core/src/pool-cl/libraries/TickMath.sol";
/// @notice Contract for modifying liquidity for PCS Infinity CL pools
contract CLPositionManager is
ICLPositionManager,
ERC721Permit_v4,
ERC721Permit,
Multicall,
DeltaResolver,
ReentrancyLock,
Expand Down Expand Up @@ -73,7 +73,7 @@ contract CLPositionManager is
)
BaseActionsRouter(_vault)
Permit2Forwarder(_permit2)
ERC721Permit_v4("Pancakeswap Infinity Positions NFT", "PCS-INFINITY-POSM")
ERC721Permit("Pancakeswap Infinity Positions NFT", "PCS-INFINITY-POSM")
CLNotifier(_unsubscribeGasLimit)
NativeWrapper(_weth9)
{
Expand Down Expand Up @@ -357,7 +357,7 @@ contract CLPositionManager is
_mint(poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, owner, hookData);
}

/// @dev this is overloaded with ERC721Permit_v4._burn
/// @dev this is overloaded with ERC721Permit._burn
function _burn(uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData)
internal
onlyIfApproved(msgSender(), tokenId)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IEIP712_v4} from "../interfaces/IEIP712_v4.sol";
import {IEIP712} from "../interfaces/IEIP712.sol";

/// @notice Generic EIP712 implementation
/// @dev Maintains cross-chain replay protection in the event of a fork
/// @dev Should not be delegatecall'd because DOMAIN_SEPARATOR returns the cached hash and does not recompute with the delegatecallers address
/// @dev Reference: https://github.com/pancakeswap/permit2/blob/main/src/EIP712.sol
/// @dev Reference: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol
contract EIP712_v4 is IEIP712_v4 {
contract EIP712 is IEIP712 {
// Cache the domain separator as an immutable value, but also store the chain id that it
// corresponds to, in order to invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
Expand All @@ -25,7 +25,7 @@ contract EIP712_v4 is IEIP712_v4 {
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator();
}

/// @inheritdoc IEIP712_v4
/// @inheritdoc IEIP712
function DOMAIN_SEPARATOR() public view override returns (bytes32) {
// uses cached version if chainid is unchanged from construction
return block.chainid == _CACHED_CHAIN_ID ? _CACHED_DOMAIN_SEPARATOR : _buildDomainSeparator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,25 @@ import {ERC721} from "solmate/src/tokens/ERC721.sol";
import {ERC721PermitHash} from "../libraries/ERC721PermitHash.sol";
import {SignatureVerification} from "permit2/src/libraries/SignatureVerification.sol";

import {EIP712_v4} from "./EIP712_v4.sol";
import {IERC721Permit_v4} from "../interfaces/IERC721Permit_v4.sol";
import {EIP712} from "./EIP712.sol";
import {IERC721Permit} from "../interfaces/IERC721Permit.sol";
import {UnorderedNonce} from "./UnorderedNonce.sol";

/// @title ERC721 with permit
/// @notice Nonfungible tokens that support an approve via signature, i.e. permit
abstract contract ERC721Permit_v4 is ERC721, IERC721Permit_v4, EIP712_v4, UnorderedNonce {
abstract contract ERC721Permit is ERC721, IERC721Permit, EIP712, UnorderedNonce {
using SignatureVerification for bytes;

/// @notice Computes the nameHash and versionHash
constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) EIP712_v4(name_) {}
constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) EIP712(name_) {}

/// @notice Checks if the block's timestamp is before a signature's deadline
modifier checkSignatureDeadline(uint256 deadline) {
if (block.timestamp > deadline) revert SignatureDeadlineExpired();
_;
}

/// @inheritdoc IERC721Permit_v4
/// @inheritdoc IERC721Permit
function permit(address spender, uint256 tokenId, uint256 deadline, uint256 nonce, bytes calldata signature)
external
payable
Expand All @@ -40,7 +40,7 @@ abstract contract ERC721Permit_v4 is ERC721, IERC721Permit_v4, EIP712_v4, Unorde
_approve(owner, spender, tokenId);
}

/// @inheritdoc IERC721Permit_v4
/// @inheritdoc IERC721Permit
function permitForAll(
address owner,
address operator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.0;

/// @notice This interface is used for an EIP712 implementation
interface IEIP712_v4 {
interface IEIP712 {
/// @notice Returns the domain separator for the current chain.
/// @dev Uses cached version if chainid is unchanged from construction.
function DOMAIN_SEPARATOR() external view returns (bytes32);
Expand Down
39 changes: 25 additions & 14 deletions src/pool-cl/interfaces/IERC721Permit.sol
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

/// @title ERC721 with permit
/// @notice Extension to ERC721 that includes a permit function for signature based approvals
interface IERC721Permit is IERC721 {
/// @notice The permit typehash used in the permit signature
/// @return The typehash for the permit
function PERMIT_TYPEHASH() external pure returns (bytes32);

/// @notice The domain separator used in the permit signature
/// @return The domain seperator used in encoding of permit signature
function DOMAIN_SEPARATOR() external view returns (bytes32);
interface IERC721Permit {
error SignatureDeadlineExpired();
error NoSelfPermit();
error Unauthorized();

/// @notice Approve of a specific token ID for spending by spender via signature
/// @param spender The account that is being approved
/// @param tokenId The ID of the token that is being approved for spending
/// @param deadline The deadline timestamp by which the call must be mined for the approve to work
/// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`
/// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`
/// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`
function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
/// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word
/// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v)
/// @dev payable so it can be multicalled with NATIVE related actions
function permit(address spender, uint256 tokenId, uint256 deadline, uint256 nonce, bytes calldata signature)
external
payable;

/// @notice Set an operator with full permission to an owner's tokens via signature
/// @param owner The address that is setting the operator
/// @param operator The address that will be set as an operator for the owner
/// @param approved The permission to set on the operator
/// @param deadline The deadline timestamp by which the call must be mined for the approve to work
/// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word
/// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v)
/// @dev payable so it can be multicalled with NATIVE related actions
function permitForAll(
address owner,
address operator,
bool approved,
uint256 deadline,
uint256 nonce,
bytes calldata signature
) external payable;
}
38 changes: 0 additions & 38 deletions src/pool-cl/interfaces/IERC721Permit_v4.sol

This file was deleted.

4 changes: 2 additions & 2 deletions src/pool-cl/libraries/ERC721PermitHash.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ library ERC721PermitHash {
/// @dev Value is equal to keccak256("PermitForAll(address operator,bool approved,uint256 nonce,uint256 deadline)");
bytes32 constant PERMIT_FOR_ALL_TYPEHASH = 0x6673cb397ee2a50b6b8401653d3638b4ac8b3db9c28aa6870ffceb7574ec2f76;

/// @notice Hashes the data that will be signed for IERC721Permit_v4.permit()
/// @notice Hashes the data that will be signed for IERC721Permit.permit()
/// @param spender The address which may spend the tokenId
/// @param tokenId The tokenId of the owner, which may be spent by spender
/// @param nonce A unique non-ordered value for each signature to prevent replay attacks
Expand Down Expand Up @@ -39,7 +39,7 @@ library ERC721PermitHash {
}
}

/// @notice Hashes the data that will be signed for IERC721Permit_v4.permit()
/// @notice Hashes the data that will be signed for IERC721Permit.permit()
/// @param operator The address which may spend any of the owner's tokenIds
/// @param approved true if the operator is to have full permission over the owner's tokenIds; false otherwise
/// @param nonce A unique non-ordered value for each signature to prevent replay attacks
Expand Down
6 changes: 3 additions & 3 deletions test/pool-cl/EIP712.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ pragma solidity ^0.8.20;

import "forge-std/Test.sol";

import {EIP712_v4} from "../../src/pool-cl/base/EIP712_v4.sol";
import {EIP712} from "../../src/pool-cl/base/EIP712.sol";

contract EIP712Test is EIP712_v4, Test {
constructor() EIP712_v4("EIP712Test") {}
contract EIP712Test is EIP712, Test {
constructor() EIP712("EIP712Test") {}

function setUp() public {}

Expand Down
8 changes: 4 additions & 4 deletions test/pool-cl/erc721Permit/ERC721Permit.permit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {SignatureVerification} from "permit2/src/libraries/SignatureVerification

import {ERC721PermitHash} from "../../../src/pool-cl/libraries/ERC721PermitHash.sol";
import {MockERC721Permit} from "../mocks/MockERC721Permit.sol";
import {IERC721Permit_v4} from "../../../src/pool-cl/interfaces/IERC721Permit_v4.sol";
import {IERC721Permit} from "../../../src/pool-cl/interfaces/IERC721Permit.sol";
import {IERC721} from "forge-std/interfaces/IERC721.sol";
import {UnorderedNonce} from "../../../src/pool-cl/base/UnorderedNonce.sol";

Expand All @@ -17,7 +17,7 @@ contract ERC721PermitTest is Test {
address bob;
uint256 bobPK;

string constant name = "Mock ERC721Permit_v4";
string constant name = "Mock ERC721Permit";
string constant symbol = "MOCK721";

function setUp() public {
Expand Down Expand Up @@ -54,7 +54,7 @@ contract ERC721PermitTest is Test {
function test_fuzz_approve_unauthorizedRevert(address caller) public {
uint256 tokenId = erc721Permit.mint();
vm.prank(caller);
if (caller != address(this)) vm.expectRevert(IERC721Permit_v4.Unauthorized.selector);
if (caller != address(this)) vm.expectRevert(IERC721Permit.Unauthorized.selector);
erc721Permit.approve(address(this), tokenId);
}

Expand Down Expand Up @@ -254,7 +254,7 @@ contract ERC721PermitTest is Test {

// -- Permit but deadline expired -- //
vm.startPrank(spender);
vm.expectRevert(IERC721Permit_v4.SignatureDeadlineExpired.selector);
vm.expectRevert(IERC721Permit.SignatureDeadlineExpired.selector);
erc721Permit.permit(spender, tokenId, deadline, nonce, signature);
vm.stopPrank();

Expand Down
6 changes: 3 additions & 3 deletions test/pool-cl/erc721Permit/ERC721Permit.permitForAll.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {SignatureVerification} from "permit2/src/libraries/SignatureVerification

import {ERC721PermitHash} from "../../../src/pool-cl/libraries/ERC721PermitHash.sol";
import {MockERC721Permit} from "../mocks/MockERC721Permit.sol";
import {IERC721Permit_v4} from "../../../src/pool-cl/interfaces/IERC721Permit_v4.sol";
import {IERC721Permit} from "../../../src/pool-cl/interfaces/IERC721Permit.sol";
import {IERC721} from "forge-std/interfaces/IERC721.sol";
import {UnorderedNonce} from "../../../src/pool-cl/base/UnorderedNonce.sol";

Expand All @@ -17,7 +17,7 @@ contract ERC721PermitForAllTest is Test {
address bob;
uint256 bobPK;

string constant name = "Mock ERC721Permit_v4";
string constant name = "Mock ERC721Permit";
string constant symbol = "MOCK721";

function setUp() public {
Expand Down Expand Up @@ -193,7 +193,7 @@ contract ERC721PermitForAllTest is Test {

// -- PermitForAll but deadline expired -- //
vm.startPrank(operator);
vm.expectRevert(IERC721Permit_v4.SignatureDeadlineExpired.selector);
vm.expectRevert(IERC721Permit.SignatureDeadlineExpired.selector);
erc721Permit.permitForAll(alice, operator, true, deadline, nonce, signature);
vm.stopPrank();

Expand Down
6 changes: 3 additions & 3 deletions test/pool-cl/mocks/MockERC721Permit.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.20;

import {ERC721Permit_v4} from "../../../src/pool-cl/base/ERC721Permit_v4.sol";
import {ERC721Permit} from "../../../src/pool-cl/base/ERC721Permit.sol";

contract MockERC721Permit is ERC721Permit_v4 {
contract MockERC721Permit is ERC721Permit {
uint256 public lastTokenId;

constructor(string memory name, string memory symbol) ERC721Permit_v4(name, symbol) {}
constructor(string memory name, string memory symbol) ERC721Permit(name, symbol) {}

function mint() external returns (uint256 tokenId) {
tokenId = ++lastTokenId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {CLPoolParametersHelper} from "infinity-core/src/pool-cl/libraries/CLPool

import {IERC20} from "forge-std/interfaces/IERC20.sol";

import {IERC721Permit_v4} from "../../../src/pool-cl/base/ERC721Permit_v4.sol";
import {IERC721Permit} from "../../../src/pool-cl/base/ERC721Permit.sol";
import {IMulticall} from "../../../src/interfaces/IMulticall.sol";
import {CLPositionManager} from "../../../src/pool-cl/CLPositionManager.sol";
import {IPositionManager} from "../../../src/interfaces/IPositionManager.sol";
Expand Down Expand Up @@ -250,7 +250,7 @@ contract CLPositionManagerMulticallTest is Test, Permit2SignatureHelpers, PosmTe
// bob gives himself permission and decreases liquidity
bytes[] memory calls = new bytes[](2);
calls[0] = abi.encodeWithSelector(
IERC721Permit_v4(lpm).permit.selector, bob, tokenId, block.timestamp + 1, nonce, signature
IERC721Permit(lpm).permit.selector, bob, tokenId, block.timestamp + 1, nonce, signature
);
uint256 liquidityToRemove = 0.4444e18;
bytes memory actions = getDecreaseEncoded(tokenId, liquidityToRemove, ZERO_BYTES);
Expand Down
6 changes: 3 additions & 3 deletions test/pool-cl/position-managers/Permit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {SignatureVerification} from "permit2/src/libraries/SignatureVerification
import {IVault} from "infinity-core/src/interfaces/IVault.sol";

import {IERC20} from "forge-std/interfaces/IERC20.sol";
import {IERC721Permit_v4} from "../../../src/pool-cl/interfaces/IERC721Permit_v4.sol";
import {ERC721Permit_v4} from "../../../src/pool-cl/base/ERC721Permit_v4.sol";
import {IERC721Permit} from "../../../src/pool-cl/interfaces/IERC721Permit.sol";
import {ERC721Permit} from "../../../src/pool-cl/base/ERC721Permit.sol";
import {UnorderedNonce} from "../../../src/pool-cl/base/UnorderedNonce.sol";

import {ICLPositionManager} from "../../../src/pool-cl/interfaces/ICLPositionManager.sol";
Expand Down Expand Up @@ -60,7 +60,7 @@ contract PermitTest is Test, PosmTestSetup {

function test_domainSeparator() public view {
assertEq(
ERC721Permit_v4(address(lpm)).DOMAIN_SEPARATOR(),
ERC721Permit(address(lpm)).DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"),
Expand Down

0 comments on commit 6d8ec06

Please sign in to comment.