Skip to content

Commit 0517b93

Browse files
authored
Yash/pack review (#195)
* receive function update * tests for valid token inputs * check for TokenType * update tests * run prettier * fix/add forge dir * add forge url
1 parent de8dd20 commit 0517b93

File tree

7 files changed

+105
-6
lines changed

7 files changed

+105
-6
lines changed

contracts/extension/TokenBundle.sol

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
pragma solidity ^0.8.0;
33

44
import "./interface/ITokenBundle.sol";
5+
import "../lib/CurrencyTransferLib.sol";
6+
7+
interface IERC165 {
8+
function supportsInterface(bytes4 interfaceId) external view returns (bool);
9+
}
510

611
abstract contract TokenBundle is ITokenBundle {
712
/// @dev Mapping from bundle UID => bundle info.
@@ -30,6 +35,7 @@ abstract contract TokenBundle is ITokenBundle {
3035
require(bundle[_bundleId].count == 0, "TokenBundle: existent at bundleId");
3136

3237
for (uint256 i = 0; i < targetCount; i += 1) {
38+
_checkTokenType(_tokensToBind[i]);
3339
bundle[_bundleId].tokens[i] = _tokensToBind[i];
3440
}
3541

@@ -46,6 +52,7 @@ abstract contract TokenBundle is ITokenBundle {
4652

4753
for (uint256 i = 0; i < check; i += 1) {
4854
if (i < targetCount) {
55+
_checkTokenType(_tokensToBind[i]);
4956
bundle[_bundleId].tokens[i] = _tokensToBind[i];
5057
} else if (i < currentCount) {
5158
delete bundle[_bundleId].tokens[i];
@@ -57,6 +64,7 @@ abstract contract TokenBundle is ITokenBundle {
5764

5865
/// @dev Lets the calling contract add a token to a bundle for a unique bundle id and index.
5966
function _addTokenInBundle(Token memory _tokenToBind, uint256 _bundleId) internal {
67+
_checkTokenType(_tokenToBind);
6068
uint256 id = bundle[_bundleId].count;
6169

6270
bundle[_bundleId].tokens[id] = _tokenToBind;
@@ -70,9 +78,38 @@ abstract contract TokenBundle is ITokenBundle {
7078
uint256 _index
7179
) internal {
7280
require(_index < bundle[_bundleId].count, "TokenBundle: index DNE.");
81+
_checkTokenType(_tokenToBind);
7382
bundle[_bundleId].tokens[_index] = _tokenToBind;
7483
}
7584

85+
/// @dev Checks if the type of asset-contract is same as the TokenType specified.
86+
function _checkTokenType(Token memory _token) internal view {
87+
if (_token.tokenType == TokenType.ERC721) {
88+
try IERC165(_token.assetContract).supportsInterface(0x80ac58cd) returns (bool supported721) {
89+
require(supported721, "Asset doesn't match TokenType");
90+
} catch {
91+
revert("Asset doesn't match TokenType");
92+
}
93+
} else if (_token.tokenType == TokenType.ERC1155) {
94+
try IERC165(_token.assetContract).supportsInterface(0xd9b67a26) returns (bool supported1155) {
95+
require(supported1155, "Asset doesn't match TokenType");
96+
} catch {
97+
revert("Asset doesn't match TokenType");
98+
}
99+
} else if (_token.tokenType == TokenType.ERC20) {
100+
if (_token.assetContract != CurrencyTransferLib.NATIVE_TOKEN) {
101+
// 0x36372b07
102+
try IERC165(_token.assetContract).supportsInterface(0x80ac58cd) returns (bool supported721) {
103+
require(!supported721, "Asset doesn't match TokenType");
104+
105+
try IERC165(_token.assetContract).supportsInterface(0xd9b67a26) returns (bool supported1155) {
106+
require(!supported1155, "Asset doesn't match TokenType");
107+
} catch Error(string memory) {} catch {}
108+
} catch Error(string memory) {} catch {}
109+
}
110+
}
111+
}
112+
76113
/// @dev Lets the calling contract set/update the uri of a particular bundle.
77114
function _setUriOfBundle(string calldata _uri, uint256 _bundleId) internal {
78115
bundle[_bundleId].uri = _uri;

contracts/extension/TokenStore.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
1111

1212
// ========== Internal imports ==========
1313

14-
import "./TokenBundle.sol";
14+
import { TokenBundle, ITokenBundle } from "./TokenBundle.sol";
1515
import "../lib/CurrencyTransferLib.sol";
1616

1717
contract TokenStore is TokenBundle, ERC721Holder, ERC1155Holder {

contracts/pack/Pack.sol

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ contract Pack is
109109
}
110110

111111
receive() external payable {
112-
require(_msgSender() == nativeTokenWrapper, "Caller is not native token wrapper.");
112+
require(msg.sender == nativeTokenWrapper, "Caller is not native token wrapper.");
113113
}
114114

115115
/*///////////////////////////////////////////////////////////////
@@ -215,11 +215,11 @@ contract Pack is
215215
{
216216
address opener = _msgSender();
217217

218-
require(opener == tx.origin, "opener must be eoa");
218+
require(isTrustedForwarder(opener) || opener == tx.origin, "opener must be eoa");
219219
require(balanceOf(opener, _packId) >= _amountToOpen, "opening more than owned");
220220

221221
PackInfo memory pack = packInfo[_packId];
222-
require(pack.openStartTimestamp < block.timestamp, "cannot open yet");
222+
require(pack.openStartTimestamp <= block.timestamp, "cannot open yet");
223223

224224
Token[] memory rewardUnits = getRewardUnits(_packId, _amountToOpen, pack.amountDistributedPerOpen, pack);
225225

@@ -232,6 +232,7 @@ contract Pack is
232232
return rewardUnits;
233233
}
234234

235+
/// @dev Stores assets within the contract.
235236
function escrowPackContents(
236237
Token[] calldata _contents,
237238
uint256[] calldata _numOfRewardUnits,
@@ -242,6 +243,7 @@ contract Pack is
242243
uint256 totalRewardUnits;
243244

244245
for (uint256 i = 0; i < _contents.length; i += 1) {
246+
require(_contents[i].totalAmount != 0, "amount can't be zero");
245247
require(_contents[i].totalAmount % _numOfRewardUnits[i] == 0, "invalid reward units");
246248
require(
247249
_contents[i].tokenType != TokenType.ERC721 || _contents[i].totalAmount == 1,

lib/forge-std

src/test/Pack.t.sol

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ contract PackTest is BaseTest {
159159
Unit tests: `createPack`
160160
//////////////////////////////////////////////////////////////*/
161161

162+
function test_interface() public {
163+
console2.logBytes4(type(IERC20).interfaceId);
164+
console2.logBytes4(type(IERC721).interfaceId);
165+
console2.logBytes4(type(IERC1155).interfaceId);
166+
}
167+
162168
/**
163169
* note: Testing state changes; token owner calls `createPack` to pack owned tokens.
164170
*/
@@ -383,7 +389,7 @@ contract PackTest is BaseTest {
383389
totalAmount: 20 ether
384390
})
385391
);
386-
numOfRewardUnits.push(1 ether);
392+
numOfRewardUnits.push(1);
387393

388394
vm.prank(address(tokenOwner));
389395
vm.expectRevert("msg.value != amount");
@@ -468,6 +474,52 @@ contract PackTest is BaseTest {
468474
pack.createPack(packContents, numOfRewardUnits, packUri, 0, 1, recipient);
469475
}
470476

477+
/**
478+
* note: Testing revert condition; token owner calls `createPack` with invalid token-type.
479+
*/
480+
function test_revert_createPack_invalidTokenType() public {
481+
ITokenBundle.Token[] memory invalidContent = new ITokenBundle.Token[](1);
482+
uint256[] memory rewardUnits = new uint256[](1);
483+
484+
invalidContent[0] = ITokenBundle.Token({
485+
assetContract: address(erc721),
486+
tokenType: ITokenBundle.TokenType.ERC20,
487+
tokenId: 0,
488+
totalAmount: 1
489+
});
490+
rewardUnits[0] = 1;
491+
492+
address recipient = address(0x123);
493+
494+
vm.startPrank(address(tokenOwner));
495+
vm.expectRevert("Asset doesn't match TokenType");
496+
pack.createPack(invalidContent, rewardUnits, packUri, 0, 1, recipient);
497+
}
498+
499+
/**
500+
* note: Testing revert condition; token owner calls `createPack` with total-amount as 0.
501+
*/
502+
function test_revert_createPack_zeroTotalAmount() public {
503+
ITokenBundle.Token[] memory invalidContent = new ITokenBundle.Token[](1);
504+
uint256[] memory rewardUnits = new uint256[](1);
505+
506+
invalidContent[0] = ITokenBundle.Token({
507+
assetContract: address(erc20),
508+
tokenType: ITokenBundle.TokenType.ERC20,
509+
tokenId: 0,
510+
totalAmount: 0
511+
});
512+
rewardUnits[0] = 10;
513+
514+
address recipient = address(0x123);
515+
516+
vm.startPrank(address(tokenOwner));
517+
vm.expectRevert("amount can't be zero");
518+
(, uint256 totalSupply) = pack.createPack(invalidContent, rewardUnits, packUri, 0, 1, recipient);
519+
520+
// assertEq(totalSupply, 10);
521+
}
522+
471523
/**
472524
* note: Testing revert condition; token owner calls `createPack` with no tokens to pack.
473525
*/

src/test/mocks/MockERC1155.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,8 @@ contract MockERC1155 is ERC1155PresetMinterPauser {
2727

2828
_mintBatch(to, ids, amounts, "");
2929
}
30+
31+
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
32+
return super.supportsInterface(interfaceId);
33+
}
3034
}

src/test/mocks/MockERC721.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,8 @@ contract MockERC721 is ERC721Burnable {
1717
tokenId += 1;
1818
}
1919
}
20+
21+
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
22+
return super.supportsInterface(interfaceId);
23+
}
2024
}

0 commit comments

Comments
 (0)