Skip to content

Commit

Permalink
more coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanio committed Nov 15, 2023
1 parent a98fb8c commit 2a4e69d
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 6 deletions.
104 changes: 98 additions & 6 deletions test/ERC7498-SimpleRedeem.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,59 @@ contract ERC7498_SimpleRedeem is BaseRedeemablesTest {
tokenId = 2;
}

function testSendErc721OrErc1155RedeemErc721() public {
for (uint256 i; i < erc7498Tokens.length; i++) {
testRedeemable(
this.sendErc721OrErc1155RedeemErc721, RedeemablesContext({erc7498Token: IERC7498(erc7498Tokens[i])})
);
}
}

function sendErc721OrErc1155RedeemErc721(RedeemablesContext memory context) external {
_mintToken(address(context.erc7498Token), tokenId);
ConsiderationItem[] memory consideration = new ConsiderationItem[](1);
consideration[0] = _getCampaignConsiderationItem(address(context.erc7498Token));
// Set consideration recipient to greg.
address greg = makeAddr("greg");
consideration[0].recipient = payable(greg);
CampaignRequirements[] memory requirements = new CampaignRequirements[](
1
);
requirements[0] = CampaignRequirements({
offer: defaultCampaignOffer,
consideration: consideration,
traitRedemptions: defaultTraitRedemptions
});
CampaignParams memory params = CampaignParams({
startTime: uint32(block.timestamp),
endTime: uint32(block.timestamp + 1000),
maxCampaignRedemptions: 1,
manager: address(this),
signer: address(0)
});
Campaign memory campaign = Campaign({params: params, requirements: requirements});
context.erc7498Token.createCampaign(campaign, "");

// Grant approval to the erc7498Token.
IERC721(address(context.erc7498Token)).setApprovalForAll(address(context.erc7498Token), true);

bytes memory extraData = abi.encode(
1, // campaignId
0, // requirementsIndex
bytes32(0), // redemptionHash
defaultTraitRedemptionTokenIds,
uint256(0), // salt
bytes("") // signature
);
uint256[] memory considerationTokenIds = Solarray.uint256s(tokenId);
vm.expectEmit(true, true, true, true);
emit Redemption(1, 0, bytes32(0), considerationTokenIds, defaultTraitRedemptionTokenIds, address(this));
context.erc7498Token.redeem(considerationTokenIds, address(0), extraData);

_checkTokenIsOwnedBy(address(context.erc7498Token), tokenId, greg);
assertEq(receiveToken721.ownerOf(1), address(this));
}

function testBurnErc721RedeemErc721WithSecondRequirementsIndex() public {
for (uint256 i; i < erc7498Tokens.length; i++) {
testRedeemable(
Expand Down Expand Up @@ -180,12 +233,6 @@ contract ERC7498_SimpleRedeem is BaseRedeemablesTest {
}

function testBurnErc20RedeemErc721() public {
for (uint256 i; i < erc7498Tokens.length; i++) {
testRedeemable(this.burnErc20RedeemErc721, RedeemablesContext({erc7498Token: IERC7498(erc7498Tokens[i])}));
}
}

function burnErc20RedeemErc721(RedeemablesContext memory /* context */ ) public {
erc20s[0].mint(address(this), 0.5 ether);
CampaignRequirements[] memory requirements = new CampaignRequirements[](
1
Expand Down Expand Up @@ -228,6 +275,51 @@ contract ERC7498_SimpleRedeem is BaseRedeemablesTest {
assertEq(receiveToken721.ownerOf(1), address(this));
}

function testSendErc20RedeemErc721() public {
erc20s[0].mint(address(this), 0.5 ether);
CampaignRequirements[] memory requirements = new CampaignRequirements[](
1
);
ConsiderationItem[] memory consideration = new ConsiderationItem[](1);
consideration[0] = defaultCampaignConsideration[0].withToken(address(erc20s[0])).withItemType(ItemType.ERC20)
.withStartAmount(0.5 ether).withEndAmount(0.5 ether);
// Set consideration recipient to greg.
address greg = makeAddr("greg");
consideration[0].recipient = payable(greg);
requirements[0] = CampaignRequirements({
offer: defaultCampaignOffer,
consideration: consideration,
traitRedemptions: defaultTraitRedemptions
});
CampaignParams memory params = CampaignParams({
startTime: uint32(block.timestamp),
endTime: uint32(block.timestamp + 1000),
maxCampaignRedemptions: 5,
manager: address(this),
signer: address(0)
});
Campaign memory campaign = Campaign({params: params, requirements: requirements});
IERC7498(erc7498Tokens[0]).createCampaign(campaign, "");

bytes memory extraData = abi.encode(
1, // campaignId
0, // requirementsIndex
bytes32(0), // redemptionHash
defaultTraitRedemptionTokenIds,
uint256(0), // salt
bytes("") // signature
);

uint256[] memory considerationTokenIds = Solarray.uint256s(0);

vm.expectEmit(true, true, true, true);
emit Redemption(1, 0, bytes32(0), considerationTokenIds, defaultTraitRedemptionTokenIds, address(this));
IERC7498(erc7498Tokens[0]).redeem(considerationTokenIds, address(this), extraData);

_checkTokenIsOwnedBy(address(erc20s[0]), tokenId, greg);
assertEq(receiveToken721.ownerOf(1), address(this));
}

function testBurnErc721RedeemErc1155() public {
_mintToken(address(erc7498Tokens[0]), tokenId);
CampaignRequirements[] memory requirements = new CampaignRequirements[](
Expand Down
8 changes: 8 additions & 0 deletions test/ERC7498-TraitRedemption.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,13 @@ contract ERC7498_TraitRedemption is BaseRedeemablesTest {
bytes32 actualTraitValue = redeemToken.getTraitValue(tokenId, traitKey);
assertEq(bytes32(uint256(1)), actualTraitValue);
assertEq(receiveToken721.ownerOf(1), address(this));

// Redeeming one more time should fail with InvalidRequiredTraitValue since it is already 1.
vm.expectRevert(
abi.encodeWithSelector(
InvalidRequiredTraitValue.selector, redeemToken, tokenId, traitKey, bytes32(uint256(1)), bytes32(0)
)
);
context.erc7498Token.redeem(considerationTokenIds, address(this), extraData);
}
}
16 changes: 16 additions & 0 deletions test/utils/BaseRedeemablesTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.19;
import {Solarray} from "solarray/Solarray.sol";
import {ERC721} from "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
import {ERC1155} from "openzeppelin-contracts/contracts/token/ERC1155/ERC1155.sol";
import {IERC20} from "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import {IERC165} from "openzeppelin-contracts/contracts/interfaces/IERC165.sol";
import {IERC721A} from "seadrop/lib/ERC721A/contracts/IERC721A.sol";
import {IERC721} from "openzeppelin-contracts/contracts/interfaces/IERC721.sol";
Expand Down Expand Up @@ -197,6 +198,17 @@ contract BaseRedeemablesTest is RedeemablesErrors, BaseOrderTest {
}
}

function _checkTokenIsOwnedBy(address token, uint256 tokenId, address owner) internal {
if (_isERC721(token)) {
assertEq(IERC721(address(token)).ownerOf(tokenId), owner);
} else if (_isERC20(token)) {
assertGt(IERC20(address(token)).balanceOf(owner), 0);
} else {
// token is ERC1155
assertGt(IERC1155(address(token)).balanceOf(owner, tokenId), 0);
}
}

function _mintToken(address token, uint256 tokenId) internal {
if (_isERC721(token)) {
ERC721ShipyardRedeemableOwnerMintable(address(token)).mint(address(this), tokenId);
Expand All @@ -218,4 +230,8 @@ contract BaseRedeemablesTest is RedeemablesErrors, BaseOrderTest {
function _isERC721(address token) internal view returns (bool isERC721) {
isERC721 = IERC165(token).supportsInterface(type(IERC721).interfaceId);
}

function _isERC20(address token) internal view returns (bool isERC20) {
isERC20 = IERC165(token).supportsInterface(type(IERC20).interfaceId);
}
}
6 changes: 6 additions & 0 deletions test/utils/mocks/TestERC20.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.19;

import {IERC165} from "openzeppelin-contracts/contracts/interfaces/IERC165.sol";
import {IERC20} from "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import {ERC20} from "solady/src/tokens/ERC20.sol";

// Used for minting test ERC20s in our tests
Expand Down Expand Up @@ -56,4 +58,8 @@ contract TestERC20 is ERC20 {
function symbol() public view virtual override returns (string memory) {
return "TST20";
}

function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC20).interfaceId;
}
}

0 comments on commit 2a4e69d

Please sign in to comment.