diff --git a/lib/solmate b/lib/solmate new file mode 160000 index 0000000..a9e3ea2 --- /dev/null +++ b/lib/solmate @@ -0,0 +1 @@ +Subproject commit a9e3ea26a2dc73bfa87f0cb189687d029028e0c5 diff --git a/src/HookERC721MultiVaultImplV1.sol b/src/HookERC721MultiVaultImplV1.sol index 02a6041..da0ae7f 100644 --- a/src/HookERC721MultiVaultImplV1.sol +++ b/src/HookERC721MultiVaultImplV1.sol @@ -281,7 +281,7 @@ contract HookERC721MultiVaultImplV1 is /// @dev returns the underlying token ID for a given asset. In this case /// the tokenId == the assetId - function assetTokenId(uint256 assetId) external view returns (uint256) { + function assetTokenId(uint256 assetId) external pure returns (uint256) { return assetId; } diff --git a/src/test/HookCoveredCallBiddingRevertTests.sol b/src/test/HookCoveredCallBiddingRevertTests.t.sol similarity index 99% rename from src/test/HookCoveredCallBiddingRevertTests.sol rename to src/test/HookCoveredCallBiddingRevertTests.t.sol index 716b9dd..8bf3207 100644 --- a/src/test/HookCoveredCallBiddingRevertTests.sol +++ b/src/test/HookCoveredCallBiddingRevertTests.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.10; -import "./utils/base.sol"; +import "./utils/base.t.sol"; import "./utils/mocks/MaliciousBidder.sol"; // @dev these tests try cases where a bidder maliciously reverts on save. diff --git a/src/test/HookCoveredCallIntegrationTest.sol b/src/test/HookCoveredCallIntegrationTest.t.sol similarity index 99% rename from src/test/HookCoveredCallIntegrationTest.sol rename to src/test/HookCoveredCallIntegrationTest.t.sol index 8d418e5..0a1bbef 100644 --- a/src/test/HookCoveredCallIntegrationTest.sol +++ b/src/test/HookCoveredCallIntegrationTest.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.10; -import "./utils/base.sol"; +import "./utils/base.t.sol"; contract HookCoveredCallIntegrationTest is HookProtocolTest { function setUp() public { diff --git a/src/test/HookCoveredCallTests.sol b/src/test/HookCoveredCallTests.t.sol similarity index 95% rename from src/test/HookCoveredCallTests.sol rename to src/test/HookCoveredCallTests.t.sol index ba818e5..30fd810 100644 --- a/src/test/HookCoveredCallTests.sol +++ b/src/test/HookCoveredCallTests.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.10; import "ds-test/test.sol"; import "forge-std/Test.sol"; -import "./utils/base.sol"; +import "./utils/base.t.sol"; /// Mint /// contract HookCoveredCallMintTests is HookProtocolTest { @@ -120,13 +120,7 @@ contract HookCoveredCallMintTests is HookProtocolTest { vm.expectRevert( "_mintOptionWithVault -- expirationTime must be more than one day in the future time" ); - uint256 optionId = calls.mintWithVault( - address(vault), - 0, - 1000, - expiration, - sig - ); + calls.mintWithVault(address(vault), 0, 1000, expiration, sig); } function test_MintOptionWithVaultFailsEmptyVault() public { @@ -148,13 +142,7 @@ contract HookCoveredCallMintTests is HookProtocolTest { ); vm.expectRevert("mintWithVault-- asset must be in vault"); - uint256 optionId = calls.mintWithVault( - address(vault), - 0, - 1000, - expiration, - sig - ); + calls.mintWithVault(address(vault), 0, 1000, expiration, sig); } function test_MintOptionWithVaultFailsUnsupportedCollection() public { @@ -176,13 +164,7 @@ contract HookCoveredCallMintTests is HookProtocolTest { ); vm.expectRevert("mintWithVault -- token must be on the project allowlist"); - uint256 optionId = calls.mintWithVault( - address(vault), - 0, - 1000, - expiration, - sig - ); + calls.mintWithVault(address(vault), 0, 1000, expiration, sig); } function testMintMultipleOptions() public { @@ -193,11 +175,6 @@ contract HookCoveredCallMintTests is HookProtocolTest { uint256 expiration = block.timestamp + 3 days; - Signatures.Signature memory sig = makeSignature( - underlyingTokenId, - expiration, - writer - ); vm.expectEmit(true, true, true, false); emit CallCreated( address(writer), @@ -320,11 +297,6 @@ contract HookCoveredCallMintTests is HookProtocolTest { token.setApprovalForAll(address(calls), true); uint256 expiration = block.timestamp + 1 hours; - Signatures.Signature memory sig = makeSignature( - underlyingTokenId, - expiration, - writer - ); vm.expectRevert( "_mintOptionWithVault -- expirationTime must be more than one day in the future time" ); @@ -340,11 +312,7 @@ contract HookCoveredCallMintTests is HookProtocolTest { token.setApprovalForAll(address(calls), true); uint256 expiration = block.timestamp + 1 hours; - Signatures.Signature memory sig = makeSignature( - underlyingTokenId, - expiration, - writer - ); + vm.expectRevert( "_mintOptionWithVault -- expirationTime must be more than one day in the future time" ); @@ -360,12 +328,6 @@ contract HookCoveredCallMintTests is HookProtocolTest { token.setApprovalForAll(address(calls), true); uint256 expiration = block.timestamp + 5 hours; - Signatures.Signature memory sig = makeSignature( - underlyingTokenId, - expiration, - writer - ); - calls.mintWithErc721(address(token), underlyingTokenId, 1000, expiration); } @@ -374,11 +336,6 @@ contract HookCoveredCallMintTests is HookProtocolTest { protocol.pause(); uint256 expiration = block.timestamp + 3 days; - Signatures.Signature memory sig = makeSignature( - underlyingTokenId, - expiration, - writer - ); vm.expectRevert("Pausable: paused"); calls.mintWithErc721(address(token), underlyingTokenId, 1000, expiration); @@ -389,11 +346,6 @@ contract HookCoveredCallMintTests is HookProtocolTest { callInternal.setMarketPaused(true); uint256 expiration = block.timestamp + 3 days; - Signatures.Signature memory sig = makeSignature( - underlyingTokenId, - expiration, - writer - ); vm.expectRevert("whenNotPaused -- market is paused"); calls.mintWithErc721(address(token), underlyingTokenId, 1000, expiration); @@ -476,11 +428,6 @@ contract HookCoveredCallMintTests is HookProtocolTest { ); calls.mintWithErc721(address(token), underlyingTokenId, 1000, expiration); - Signatures.Signature memory sig = makeSignature( - underlyingTokenId, - expiration, - writer - ); // Vault is now owner of the underlying token so this fails. vm.expectRevert("mintWithErc721 -- caller must be token owner or operator"); calls.mintWithErc721(address(token), underlyingTokenId, 1000, expiration); @@ -512,11 +459,6 @@ contract HookCoveredCallMintTests is HookProtocolTest { vm.stopPrank(); vm.startPrank(operator); - Signatures.Signature memory sig = makeSignature( - underlyingTokenId, - expiration, - writer - ); // Vault is now owner of the underlying token so this fails. vm.expectRevert("mintWithErc721 -- caller must be token owner or operator"); calls.mintWithErc721(address(token), underlyingTokenId, 1000, expiration); @@ -546,11 +488,6 @@ contract HookCoveredCallMintTests is HookProtocolTest { expiration ); - Signatures.Signature memory sig = makeSignature( - optionId, - expiration, - writer - ); // Minting should only work for TestERC721 vm.expectRevert("mintWithErc721 -- token must be on the project allowlist"); calls.mintWithErc721(address(calls), optionId, 1000, expiration); @@ -815,7 +752,6 @@ contract HookCoveredCallBidTests is HookProtocolTest { vm.deal(writer, 1 ether); uint256 firstBidderStartBalance = firstBidder.balance; - uint256 writerStartBalance = writer.balance; vm.warp(block.timestamp + 2.1 days); @@ -853,7 +789,6 @@ contract HookCoveredCallBidTests is HookProtocolTest { vm.deal(writer, 1 ether); uint256 firstBidderStartBalance = firstBidder.balance; - uint256 writerStartBalance = writer.balance; vm.warp(block.timestamp + 2.1 days); @@ -1304,9 +1239,6 @@ contract HookCoveredCallReclaimTests is HookProtocolTest { vm.deal(writer, 1 ether); vm.deal(firstBidder, 1 ether); - uint256 buyerStartBalance = buyer.balance; - uint256 writerStartBalance = writer.balance; - // Writer approve operator and covered call token.setApprovalForAll(address(calls), true); @@ -1355,9 +1287,6 @@ contract HookCoveredCallReclaimTests is HookProtocolTest { vm.deal(writer, 1 ether); vm.deal(firstBidder, 1 ether); - uint256 buyerStartBalance = buyer.balance; - uint256 writerStartBalance = writer.balance; - // Writer approve operator and covered call token.setApprovalForAll(address(calls), true); @@ -1407,9 +1336,6 @@ contract HookCoveredCallReclaimTests is HookProtocolTest { vm.deal(writer, 1 ether); vm.deal(firstBidder, 1 ether); - uint256 buyerStartBalance = buyer.balance; - uint256 writerStartBalance = writer.balance; - // Writer approve operator and covered call token.setApprovalForAll(address(calls), true); diff --git a/src/test/HookMultiVaultTests.sol b/src/test/HookMultiVaultTests.t.sol similarity index 97% rename from src/test/HookMultiVaultTests.sol rename to src/test/HookMultiVaultTests.t.sol index 8553f3d..082fb9e 100644 --- a/src/test/HookMultiVaultTests.sol +++ b/src/test/HookMultiVaultTests.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.10; import "ds-test/test.sol"; import "forge-std/Test.sol"; -import "./utils/base.sol"; +import "./utils/base.t.sol"; import "../interfaces/IHookERC721VaultFactory.sol"; import "../lib/Entitlements.sol"; @@ -32,9 +32,7 @@ contract HookMultiVaultTests is HookProtocolTest { tokenId = tokenStartIndex; token.mint(address(writer), tokenId); vault.makeMultiVault(address(token)); - address vaultAddress = address( - vault.findOrCreateVault(address(token), tokenId) - ); + vaultAddress = address(vault.findOrCreateVault(address(token), tokenId)); vm.stopPrank(); return (vaultAddress, tokenId); } @@ -54,7 +52,7 @@ contract HookMultiVaultTests is HookProtocolTest { { address ownerAdd = vm.addr(writerpkey); - Entitlements.Entitlement memory entitlement = Entitlements.Entitlement({ + entitlement = Entitlements.Entitlement({ beneficialOwner: ownerAdd, operator: operator, vaultAddress: vaultAddress, @@ -568,9 +566,7 @@ contract HookMultiVaultTests is HookProtocolTest { vm.prank(mockContract); vaultImpl.clearEntitlement(tokenId); - (bool active, address operator) = vaultImpl.getCurrentEntitlementOperator( - tokenId - ); + (bool active, ) = vaultImpl.getCurrentEntitlementOperator(tokenId); assertTrue(!active, "there should not be an active entitlement"); // check that the owner can actually withdrawl @@ -723,9 +719,7 @@ contract HookMultiVaultTests is HookProtocolTest { IHookERC721Vault vaultImpl = IHookERC721Vault(vaultAddress); address mockContract2 = address(35553445); - (bool active, address operator) = vaultImpl.getCurrentEntitlementOperator( - tokenId - ); + (bool active, ) = vaultImpl.getCurrentEntitlementOperator(tokenId); assertTrue(active, "there should be an active entitlement"); uint256 expiration2 = block.timestamp + 3 days; @@ -776,9 +770,7 @@ contract HookMultiVaultTests is HookProtocolTest { ); IHookERC721Vault vaultImpl = IHookERC721Vault(vaultAddress); - (bool active, address operator) = vaultImpl.getCurrentEntitlementOperator( - tokenId - ); + (bool active, ) = vaultImpl.getCurrentEntitlementOperator(tokenId); assertTrue(active, "there should be an active entitlement"); vm.prank(writer); @@ -834,7 +826,7 @@ contract HookMultiVaultTests is HookProtocolTest { } function testAirdropsCanBeDisbled() public { - (address vaultAddress, uint256 tokenId) = createVaultandAsset(); + (address vaultAddress, ) = createVaultandAsset(); vm.prank(admin); protocol.setCollectionConfig( @@ -851,7 +843,7 @@ contract HookMultiVaultTests is HookProtocolTest { } function testAirdropsAllowedWhenEnabled() public { - (address vaultAddress, uint256 tokenId) = createVaultandAsset(); + (address vaultAddress, ) = createVaultandAsset(); vm.prank(admin); protocol.setCollectionConfig( diff --git a/src/test/HookVaultTests.sol b/src/test/HookVaultTests.t.sol similarity index 97% rename from src/test/HookVaultTests.sol rename to src/test/HookVaultTests.t.sol index 4384a9e..e20d108 100644 --- a/src/test/HookVaultTests.sol +++ b/src/test/HookVaultTests.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.10; import "ds-test/test.sol"; import "forge-std/Test.sol"; -import "./utils/base.sol"; +import "./utils/base.t.sol"; import "../interfaces/IHookERC721VaultFactory.sol"; import "../lib/Entitlements.sol"; @@ -13,7 +13,7 @@ import "../mixin/EIP712.sol"; import "./utils/mocks/FlashLoan.sol"; -contract HookVaultTests is HookProtocolTest { +contract HookVaultTestsBase is HookProtocolTest { IHookERC721VaultFactory vault; uint256 tokenStartIndex = 300; @@ -31,12 +31,9 @@ contract HookVaultTests is HookProtocolTest { tokenStartIndex += 1; tokenId = tokenStartIndex; token.mint(address(writer), tokenId); - IHookERC721Vault vaultAddress = vault.findOrCreateVault( - address(token), - tokenId - ); + vaultAddress = address(vault.findOrCreateVault(address(token), tokenId)); vm.stopPrank(); - return (address(vaultAddress), tokenId); + return (vaultAddress, tokenId); } function makeEntitlementAndSignature( @@ -53,7 +50,7 @@ contract HookVaultTests is HookProtocolTest { { address ownerAdd = vm.addr(writerpkey); - Entitlements.Entitlement memory entitlement = Entitlements.Entitlement({ + entitlement = Entitlements.Entitlement({ beneficialOwner: ownerAdd, operator: operator, vaultAddress: vaultAddress, @@ -76,47 +73,9 @@ contract HookVaultTests is HookProtocolTest { }); return (entitlement, sig); } +} - function testImposeEntitlmentOnTransferIn() public { - (address vaultAddress, uint256 tokenId) = createVaultandAsset(); - - address mockContract = address(69); - uint256 expiration = block.timestamp + 1 days; - - ( - Entitlements.Entitlement memory entitlement, - Signatures.Signature memory sig - ) = makeEntitlementAndSignature( - writerpkey, - mockContract, - vaultAddress, - expiration - ); - - vm.prank(writer); - - token.safeTransferFrom( - writer, - vaultAddress, - tokenId, - abi.encode(entitlement, sig) - ); - - HookERC721VaultImplV1 vaultImpl = HookERC721VaultImplV1(vaultAddress); - assertTrue( - vaultImpl.getHoldsAsset(0), - "the token should be owned by the vault" - ); - assertTrue( - vaultImpl.getBeneficialOwner(0) == writer, - "writer should be the beneficial owner" - ); - assertTrue( - vaultImpl.hasActiveEntitlement(), - "there should be an active entitlement" - ); - } - +contract HookVaultTestFlash is HookVaultTestsBase { function testBasicFlashLoan() public { (address vaultAddress, uint256 tokenId) = createVaultandAsset(); @@ -419,6 +378,48 @@ contract HookVaultTests is HookProtocolTest { "good flashloan should work" ); } +} + +contract HookVaultTestEntitlement is HookVaultTestsBase { + function testImposeEntitlmentOnTransferIn() public { + (address vaultAddress, uint256 tokenId) = createVaultandAsset(); + + address mockContract = address(69); + uint256 expiration = block.timestamp + 1 days; + + ( + Entitlements.Entitlement memory entitlement, + Signatures.Signature memory sig + ) = makeEntitlementAndSignature( + writerpkey, + mockContract, + vaultAddress, + expiration + ); + + vm.prank(writer); + + token.safeTransferFrom( + writer, + vaultAddress, + tokenId, + abi.encode(entitlement, sig) + ); + + HookERC721VaultImplV1 vaultImpl = HookERC721VaultImplV1(vaultAddress); + assertTrue( + vaultImpl.getHoldsAsset(0), + "the token should be owned by the vault" + ); + assertTrue( + vaultImpl.getBeneficialOwner(0) == writer, + "writer should be the beneficial owner" + ); + assertTrue( + vaultImpl.hasActiveEntitlement(), + "there should be an active entitlement" + ); + } function testImposeEntitlementAfterInitialTransfer() public { (address vaultAddress, uint256 tokenId) = createVaultandAsset(); @@ -773,7 +774,9 @@ contract HookVaultTests is HookProtocolTest { ); vaultImpl.clearEntitlement(0); } +} +contract HookVaultTestsDistribution is HookVaultTestsBase { function testClearAndDistributeReturnsNFT() public { (address vaultAddress, uint256 tokenId) = createVaultandAsset(); @@ -814,7 +817,7 @@ contract HookVaultTests is HookProtocolTest { } function testAirdropsCanBeDisbled() public { - (address vaultAddress, uint256 tokenId) = createVaultandAsset(); + (address vaultAddress, ) = createVaultandAsset(); vm.prank(admin); protocol.setCollectionConfig( @@ -831,7 +834,7 @@ contract HookVaultTests is HookProtocolTest { } function testAirdropsAllowedWhenEnabled() public { - (address vaultAddress, uint256 tokenId) = createVaultandAsset(); + (address vaultAddress, ) = createVaultandAsset(); vm.prank(admin); protocol.setCollectionConfig( diff --git a/src/test/utils/base.sol b/src/test/utils/base.t.sol similarity index 100% rename from src/test/utils/base.sol rename to src/test/utils/base.t.sol diff --git a/src/test/utils/mocks/FlashLoan.sol b/src/test/utils/mocks/FlashLoan.sol index bfb73f8..6d2f0a1 100644 --- a/src/test/utils/mocks/FlashLoan.sol +++ b/src/test/utils/mocks/FlashLoan.sol @@ -35,9 +35,9 @@ contract FlashLoanDoesNotApprove is IERC721FlashLoanReceiver { address nftContract, uint256 tokenId, address, - address vault, + address, bytes calldata - ) external returns (bool) { + ) external view returns (bool) { // skip this: // IERC721(nftContract).approve(vault, tokenId); return IERC721(nftContract).ownerOf(tokenId) == address(this); @@ -131,7 +131,7 @@ contract FlashLoanVerifyCalldata is IERC721FlashLoanReceiver { function executeOperation( address nftContract, - uint256 tokenId, + uint256, address, address vault, bytes calldata params