Skip to content

Commit

Permalink
ERC721 tests pass
Browse files Browse the repository at this point in the history
  • Loading branch information
GWSzeto committed Sep 25, 2024
1 parent 643675a commit 82b8c59
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 8 deletions.
2 changes: 1 addition & 1 deletion dependecies/immutable/test/allowlist/OperatorAllowlist.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
pragma solidity ^0.8.24;

// Access Control

import {Role} from "../../../../src/Role.sol";
import {OwnableRoles} from "@solady/auth/OwnableRoles.sol";

Expand Down Expand Up @@ -58,6 +57,7 @@ contract OperatorAllowlist is ERC165, OwnableRoles, IOperatorAllowlist {
* @param admin the address to grant `Role._MANAGER_ROLE` to
*/
constructor(address admin) {
_initializeOwner(admin);
_grantRoles(admin, Role._MANAGER_ROLE);
}

Expand Down
167 changes: 160 additions & 7 deletions test/module/immutable/ImmutableAllowlistERC721.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,36 @@ contract Core is ERC721Core {

}

contract TransferableERC721Test is Test {
contract DummyContract {

ERC721Core public immutable erc721Core;

constructor(address payable _erc721Core) {
erc721Core = ERC721Core(_erc721Core);
}

function approve(address _to, uint256 _tokenId) external {
erc721Core.approve(_to, _tokenId);
}

function setApprovalForAll(address _operator) external {
erc721Core.setApprovalForAll(_operator, true);
}

function transfer(address _to, uint256 _tokenId) external {
erc721Core.transferFrom(address(this), _to, _tokenId);
}

}

contract ImmutableAllowlistERC721Test is Test {

Core public core;

ImmutableAllowlistERC721 public immutableAllowlistModule;
OperatorAllowlist public operatorAllowlist;
DummyContract public dummyContract1;
DummyContract public dummyContract2;

address public owner = address(0x1);
address public actorOne = address(0x2);
Expand All @@ -55,6 +79,8 @@ contract TransferableERC721Test is Test {

core = new Core("test", "TEST", "", owner, modules, moduleData);
immutableAllowlistModule = new ImmutableAllowlistERC721();

vm.prank(owner);
operatorAllowlist = new OperatorAllowlist(owner);

// install module
Expand All @@ -64,6 +90,14 @@ contract TransferableERC721Test is Test {
core.installModule(address(immutableAllowlistModule), encodedOperatorAllowlist);
vm.stopPrank();

// set registrar role for owner
vm.prank(owner);
operatorAllowlist.grantRegistrarRole(owner);

// deploy dummy contract
dummyContract1 = new DummyContract(payable(address(core)));
dummyContract2 = new DummyContract(payable(address(core)));

// mint tokens
core.mint(actorOne, 1, string(""), ""); // tokenId 0
core.mint(actorTwo, 1, string(""), ""); // tokenId 1
Expand All @@ -73,6 +107,13 @@ contract TransferableERC721Test is Test {
core.grantRoles(owner, Role._MANAGER_ROLE);
}

function allowlist(address _target) internal {
address[] memory allowlist = new address[](1);
allowlist[0] = _target;
vm.prank(owner);
operatorAllowlist.addAddressToAllowlist(allowlist);
}

/*///////////////////////////////////////////////////////////////
Unit tests: `setOperatorAllowlistRegistry`
//////////////////////////////////////////////////////////////*/
Expand All @@ -97,14 +138,126 @@ contract TransferableERC721Test is Test {
}

/*///////////////////////////////////////////////////////////////
Unit tests: `setTransferable`
Unit tests: `beforeApproveERC721`
//////////////////////////////////////////////////////////////*/

/// @notice Callback function for ERC721.approve
function beforeApproveERC721(address _from, address _to, uint256 _tokenId, bool _approve)
external
returns (bytes memory)
{}
function test_state_beforeApproveERC721() public {
// passes when msg.sender is an EOA and targetApproval is an EOA
vm.prank(actorOne);
core.approve(actorTwo, 0);

// set allowlist for dummy contract
address[] memory allowlist = new address[](3);
allowlist[0] = address(dummyContract1);
allowlist[1] = address(dummyContract2);
allowlist[2] = address(actorThree);
vm.prank(owner);
operatorAllowlist.addAddressToAllowlist(allowlist);

vm.startPrank(actorThree);
core.mint(actorThree, 2, string(""), ""); // tokenId 3
core.transferFrom(actorThree, address(dummyContract1), 3);
vm.stopPrank();

// passes when msg.sender is a contract and is allowlisted
// and when targetApproval is a contract and is allowlisted
dummyContract1.approve(address(dummyContract2), 3);
}

function test_revert_beforeApproveERC721() public {
vm.prank(actorOne);
vm.expectRevert(
abi.encodeWithSelector(
OperatorAllowlistEnforcementErrors.ApproveTargetNotInAllowlist.selector, address(dummyContract1)
)
);
core.approve(address(dummyContract1), 0);
}

/*///////////////////////////////////////////////////////////////
Unit tests: `beforeApproveForAll`
//////////////////////////////////////////////////////////////*/

function test_state_beforeApproveForAllERC721() public {
// passes when msg.sender is an EOA and targetApproval is an EOA
vm.prank(actorOne);
core.setApprovalForAll(actorTwo, true);

// set allowlist for dummy contract
address[] memory allowlist = new address[](3);
allowlist[0] = address(dummyContract1);
allowlist[1] = address(dummyContract2);
allowlist[2] = address(actorThree);
vm.prank(owner);
operatorAllowlist.addAddressToAllowlist(allowlist);

vm.startPrank(actorThree);
core.mint(actorThree, 1, string(""), ""); // tokenId 3
core.transferFrom(actorThree, address(dummyContract1), 3);
vm.stopPrank();

// passes when msg.sender is a contract and is allowlisted
// and when targetApproval is a contract and is allowlisted
dummyContract1.setApprovalForAll(address(dummyContract2));
}

function test_revert_beforeApproveForAllERC721() public {
vm.prank(actorOne);
vm.expectRevert(
abi.encodeWithSelector(
OperatorAllowlistEnforcementErrors.ApproveTargetNotInAllowlist.selector, address(dummyContract1)
)
);
core.setApprovalForAll(address(dummyContract1), true);
}

/*///////////////////////////////////////////////////////////////
Unit tests: `beforeTransferERC721`
//////////////////////////////////////////////////////////////*/

function test_state_beforeTransferERC721() public {
// set allowlist
address[] memory allowlist = new address[](5);
allowlist[0] = address(dummyContract1);
allowlist[1] = address(dummyContract2);
allowlist[2] = address(actorOne);
allowlist[3] = address(actorTwo);
allowlist[4] = address(actorThree);
vm.prank(owner);
operatorAllowlist.addAddressToAllowlist(allowlist);

vm.prank(actorOne);
core.transferFrom(actorOne, actorTwo, 0);

// passes when msg.sender is an EOA and targetApproval is a contract and is allowlisted
core.mint(actorThree, 1, string(""), ""); // tokenId 3
vm.startPrank(actorThree);
core.transferFrom(actorThree, address(dummyContract1), 3);
vm.stopPrank();

// passes when msg.sender is a contract and is allowlisted
// and when targetApproval is a contract and is allowlisted
dummyContract1.transfer(address(dummyContract2), 3);
}

function test_revert_beforeTransferERC721() public {
// fails when msg.sender is not allowlisted
vm.prank(actorOne);
vm.expectRevert(
abi.encodeWithSelector(OperatorAllowlistEnforcementErrors.CallerNotInAllowlist.selector, actorOne)
);
core.transferFrom(actorOne, actorTwo, 0);

// fails when target is not allowlisted
allowlist(actorOne);
vm.prank(actorOne);
vm.expectRevert(
abi.encodeWithSelector(
OperatorAllowlistEnforcementErrors.TransferToNotInAllowlist.selector, address(dummyContract1)
)
);
core.transferFrom(actorOne, address(dummyContract1), 0);
}

/// @notice Callback function for ERC721.setApprovalForAll
function beforeApproveForAll(address _from, address _to, bool _approved) external returns (bytes memory) {}
Expand Down

0 comments on commit 82b8c59

Please sign in to comment.