Skip to content

Commit

Permalink
rebase and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
snreynolds committed Jan 31, 2023
1 parent a377753 commit 195c179
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 88 deletions.
File renamed without changes.
2 changes: 2 additions & 0 deletions src/ERC721/interfaces/IAllowanceTransferERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,12 @@ interface IAllowanceTransferERC721 {
/// @notice A mapping from owner address to token address to tokenId to PackedAllowance struct, which contains details and conditions of the approval.
/// @notice The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][tokenId]
/// @dev The packed slot holds the allowed spender, expiration at which the permissions on the tokenId is no longer valid, and current nonce thats updated on any signature based approvals.
/// @dev Setting the expiration to 0, sets the expiration to block.timestamp so the approval only lasts for the duration of the block.
function allowance(address, address, uint256) external view returns (address, uint48, uint48);

/// @notice A mapping from owner address to token address to spender address to a PackedOperatorAllowance struct, which contains the expiration of the operator approval.
/// @notice The mapping is indexed in the above order see: operator[ownerAddress][tokenAddress][spenderAddress]
/// @dev Unlike the allowance mappings, setting the expiration to 0 just invalidates the operator allowance. It does NOT set the allowance to block.timestamp.
function operators(address, address, address) external view returns (uint48, uint48);

/// @notice Approves the spender to transfer the tokenId of the specified token up until the expiration
Expand Down
30 changes: 23 additions & 7 deletions test/mocks/IMockPermit2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,35 @@ import {ISignatureTransfer} from "../../src/ERC20/interfaces/ISignatureTransfer.
import {Allowance} from "../../src/ERC20/libraries/Allowance.sol";

abstract contract IMockPermit2 {
function doStore(address from, address token, address spender, uint256 word) public virtual {}
// note that some parameters are unused in the erc20 and erc721 case but with this interface they can share some base tests

function getStore(address from, address token, address spender) public view virtual returns (uint256 word) {}
function doStore(address from, address token, address spender, uint256 tokenId, uint256 word) public virtual {}

function mockUpdateSome(address from, address token, address spender, uint160 data, uint48 expiration)
function getStore(address from, address token, address spender, uint256 tokenId)
public
view
virtual
returns (uint256 word)
{}

function mockUpdateAll(address from, address token, address spender, uint160 data, uint48 expiration, uint48 nonce)
public
virtual
{}
function mockUpdateSome(
address from,
address token,
address spender,
uint160 updateData,
uint256 tokenId,
uint48 expiration
) public virtual {}

function mockUpdateAll(
address from,
address token,
address spender,
uint160 updateData,
uint256 tokenId,
uint48 expiration,
uint48 nonce
) public virtual {}

function useUnorderedNonce(address from, uint256 nonce) public virtual {}
}
39 changes: 27 additions & 12 deletions test/mocks/MockPermit2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,49 @@ import {Allowance} from "../../src/ERC20/libraries/Allowance.sol";
import {IMockPermit2} from "../mocks/IMockPermit2.sol";

contract MockPermit2 is IMockPermit2, Permit2 {
function doStore(address from, address token, address spender, uint256 word) public override {
function doStore(address from, address token, address spender, uint256 tokenId, uint256 word) public override {
IAllowanceTransfer.PackedAllowance storage allowed = allowance[from][token][spender];
assembly {
sstore(allowed.slot, word)
}
}

function getStore(address from, address token, address spender) public view override returns (uint256 word) {
function getStore(address from, address token, address spender, uint256 tokenId)
public
view
override
returns (uint256 word)
{
IAllowanceTransfer.PackedAllowance storage allowed = allowance[from][token][spender];
assembly {
word := sload(allowed.slot)
}
}

function mockUpdateSome(address from, address token, address spender, uint160 data, uint48 expiration)
public
override
{
function mockUpdateSome(
address from,
address token,
address spender,
uint160 updateData,
uint256 tokenId,
uint48 expiration
) public override {
// uint256 tokenId unused
IAllowanceTransfer.PackedAllowance storage allowed = allowance[from][token][spender];
Allowance.updateAmountAndExpiration(allowed, data, expiration);
Allowance.updateAmountAndExpiration(allowed, updateData, expiration);
}

function mockUpdateAll(address from, address token, address spender, uint160 data, uint48 expiration, uint48 nonce)
public
override
{
function mockUpdateAll(
address from,
address token,
address spender,
uint160 updateData,
uint256 tokenId,
uint48 expiration,
uint48 nonce
) public override {
IAllowanceTransfer.PackedAllowance storage allowed = allowance[from][token][spender];
Allowance.updateAll(allowed, data, expiration, nonce);
Allowance.updateAll(allowed, updateData, expiration, nonce);
}

function useUnorderedNonce(address from, uint256 nonce) public override {
Expand Down
59 changes: 59 additions & 0 deletions test/mocks/MockPermit2ERC721.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {Permit2ERC721} from "../../src/ERC721/Permit2ERC721.sol";
import {IAllowanceTransferERC721} from "../../src/ERC721/interfaces/IAllowanceTransferERC721.sol";
import {SignatureTransferERC721} from "../../src/ERC721/SignatureTransferERC721.sol";
import {AllowanceERC721} from "../../src/ERC721/libraries/AllowanceERC721.sol";
import {IMockPermit2} from "../mocks/IMockPermit2.sol";

contract MockPermit2ERC721 is IMockPermit2, Permit2ERC721 {
function doStore(address from, address token, address spender, uint256 tokenId, uint256 word) public override {
IAllowanceTransferERC721.PackedAllowance storage allowed = allowance[from][token][tokenId];
assembly {
sstore(allowed.slot, word)
}
}

function getStore(address from, address token, address spender, uint256 tokenId)
public
view
override
returns (uint256 word)
{
IAllowanceTransferERC721.PackedAllowance storage allowed = allowance[from][token][tokenId];
assembly {
word := sload(allowed.slot)
}
}

function mockUpdateSome(
address from,
address token,
address spender,
uint160 updateData,
uint256 tokenId,
uint48 expiration
) public override {
// spender input unused in 721 case
IAllowanceTransferERC721.PackedAllowance storage allowed = allowance[from][token][tokenId];
AllowanceERC721.updateSpenderAndExpiration(allowed, address(updateData), expiration);
}

function mockUpdateAll(
address from,
address token,
address spender,
uint160 updateData,
uint256 tokenId,
uint48 expiration,
uint48 nonce
) public override {
IAllowanceTransferERC721.PackedAllowance storage allowed = allowance[from][token][tokenId];
AllowanceERC721.updateAll(allowed, address(updateData), expiration, nonce);
}

function useUnorderedNonce(address from, uint256 nonce) public override {
_useUnorderedNonce(from, nonce);
}
}
44 changes: 0 additions & 44 deletions test/mocks/MockPermit2_ERC721.sol

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import "forge-std/Test.sol";
import "../mocks/MockPermit2.sol";
import {BaseAllowanceUnitTest} from "./BaseAllowanceUnitTest.sol";
import {TokenProvider} from "../utils/TokenProvider.sol";
import {Allowance} from "../../src/ERC20/libraries/Allowance.sol";

contract AllowanceUnitTest_ERC20 is BaseAllowanceUnitTest {
contract AllowanceUnitTestERC20 is BaseAllowanceUnitTest {
function setUp() public override {
permit2 = new MockPermit2();
initializeERC20Tokens();
}

function allowance(address from, address token, address spender)
function allowance(address from, address token, address spender, uint256 tokenId)
public
view
override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
// SPDX-License-Identifier: MIT
// // SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "forge-std/Test.sol";
import "../mocks/MockPermit2_ERC721.sol";
import "../mocks/MockPermit2ERC721.sol";
import {BaseAllowanceUnitTest} from "./BaseAllowanceUnitTest.sol";
import {TokenProvider} from "../utils/TokenProvider.sol";

contract AllowanceUnitTest_ERC721 is BaseAllowanceUnitTest {
contract AllowanceUnitTestERC721 is BaseAllowanceUnitTest {
function setUp() public override {
permit2 = new MockPermit2_ERC721();
permit2 = new MockPermit2ERC721();
initializeNFTTokens();
}

function allowance(address from, address token, address spender)
function allowance(address from, address token, address spender, uint256 tokenId)
public
view
override
returns (uint160, uint48, uint48)
{
return MockPermit2_ERC721(address(permit2)).allowance(from, token, spender);
(address spender1, uint48 expiration1, uint48 nonce1) =
MockPermit2ERC721(address(permit2)).allowance(from, token, tokenId);
return (uint160(spender1), expiration1, nonce1);
}

function token() public view override returns (address) {
Expand Down
31 changes: 19 additions & 12 deletions test/shared/BaseAllowanceUnitTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,28 @@ abstract contract BaseAllowanceUnitTest is Test, TokenProvider {

address from = address(0xBEEE);
address spender = address(0xBBBB);
uint256 tokenId = 0;

function setUp() public virtual {}

function allowance(address from, address token, address spender) public virtual returns (uint160, uint48, uint48);
function allowance(address from, address token, address spender, uint256 tokenId)
public
virtual
returns (uint160, uint48, uint48);

function token() public virtual returns (address);

function testUpdateAmountExpirationRandomly(uint160 amount, uint48 expiration) public {
function testUpdateSomeRandomly(uint160 amount, uint48 expiration) public {
address token = token();

(,, uint48 nonce) = allowance(from, token, spender);
(,, uint48 nonce) = allowance(from, token, spender, tokenId);

permit2.mockUpdateSome(from, token, spender, amount, expiration);
// erc721s will update the spender field to the amount and will not use the spender input
permit2.mockUpdateSome(from, token, spender, amount, tokenId, expiration);

uint48 timestampAfterUpdate = expiration == 0 ? uint48(block.timestamp) : expiration;

(uint160 amount1, uint48 expiration1, uint48 nonce1) = allowance(from, token, spender);
(uint160 amount1, uint48 expiration1, uint48 nonce1) = allowance(from, token, spender, tokenId);
assertEq(amount, amount1);
assertEq(timestampAfterUpdate, expiration1);
/// nonce shouldnt change
Expand All @@ -40,12 +45,12 @@ abstract contract BaseAllowanceUnitTest is Test, TokenProvider {

address token = token();

permit2.mockUpdateAll(from, token, spender, amount, expiration, nonce);
permit2.mockUpdateAll(from, token, spender, amount, tokenId, expiration, nonce);

uint48 nonceAfterUpdate = nonce + 1;
uint48 timestampAfterUpdate = expiration == 0 ? uint48(block.timestamp) : expiration;

(uint160 amount1, uint48 expiration1, uint48 nonce1) = allowance(from, token, spender);
(uint160 amount1, uint48 expiration1, uint48 nonce1) = allowance(from, token, spender, tokenId);

assertEq(amount, amount1);
assertEq(timestampAfterUpdate, expiration1);
Expand All @@ -54,19 +59,21 @@ abstract contract BaseAllowanceUnitTest is Test, TokenProvider {

function testPackAndUnpack(uint160 amount, uint48 expiration, uint48 nonce) public {
// pack some numbers
uint256 word = Allowance.pack(amount, expiration, nonce);
address token = token();
uint256 word = Allowance.pack(amount, expiration, nonce);

// store the raw word
permit2.doStore(from, token, spender, word);
permit2.doStore(from, token, spender, tokenId, word);
uint256 word1 = permit2.getStore(from, token, spender, tokenId);

// load it as a packed allowance
(uint160 amount1, uint48 expiration1, uint48 nonce1) = allowance(from, token, spender);
(uint160 amount1, uint48 expiration1, uint48 nonce1) = allowance(from, token, spender, tokenId);
assertEq(amount, amount1);
assertEq(expiration, expiration1);
assertEq(nonce, nonce1);

// get the stored word
uint256 word1 = permit2.getStore(from, token, spender);
assertEq(word, word1);
uint256 word2 = permit2.getStore(from, token, spender, tokenId);
assertEq(word, word2);
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ pragma solidity ^0.8.17;

import "forge-std/Test.sol";
import {BaseNonceBitmapTest} from "./BaseNonceBitmapTest.t.sol";
import {MockPermit2_ERC721} from "../mocks/MockPermit2_ERC721.sol";
import {MockPermit2ERC721} from "../mocks/MockPermit2ERC721.sol";

contract NonceBitmapTest_ERC721 is BaseNonceBitmapTest {
contract NonceBitmapTestERC721 is BaseNonceBitmapTest {
function setUp() public override {
permit2 = new MockPermit2_ERC721();
permit2 = new MockPermit2ERC721();
}

function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) public override {
MockPermit2_ERC721(address(permit2)).invalidateUnorderedNonces(wordPos, mask);
MockPermit2ERC721(address(permit2)).invalidateUnorderedNonces(wordPos, mask);
}

function nonceBitmap(address addr, uint256 wordPos) public override returns (uint256) {
return MockPermit2_ERC721(address(permit2)).nonceBitmap(addr, wordPos);
return MockPermit2ERC721(address(permit2)).nonceBitmap(addr, wordPos);
}
}

0 comments on commit 195c179

Please sign in to comment.