Skip to content

Commit

Permalink
Add mint function to pass data to onERC721Received
Browse files Browse the repository at this point in the history
  • Loading branch information
matejos committed Apr 11, 2024
1 parent a72abb9 commit e64944d
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,18 @@ interface IInverseAppProjectedNft is IInverseProjectedNft {
/// Emits the `Minted` event.
/// @param _to where to send the NFT to
/// @param _verificationData any additional data to verify the validity of the mint
/// @param _data any additional data to pass to the receiver contract
/// @return id of the minted token
function mint(
address _to,
bytes memory _verificationData,
bytes memory _data
) external returns (uint256);

/// @dev Shorthand function that calls the `mint` function with empty `_data`.
function mint(address _to, bytes memory _verificationData) external returns (uint256);

/// @dev This works identically to the other function with an extra data parameter,
/// except this function just sets data to "".
/// @dev Shorthand function that calls the `mint` function with empty `_verificationData` and empty `_data`.
function mint(address _to) external returns (uint256);

/// @notice Returns the last nonce used (or 0 if the user has never minted)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,16 @@ interface IInverseBaseProjectedNft is IInverseProjectedNft {
/// Increases the `totalSupply` and `currentTokenId`.
/// Reverts if `_to` is a zero address or if it refers to smart contract but does not implement IERC721Receiver-onERC721Received.
/// Emits the `Minted` event.
/// @param _to where to send the NFT to
/// @param initialData data that is emitted in the `Minted` event
/// @param data any additional data to pass to the receiver contract
/// @return id of the minted token
function mint(
address _to,
string calldata initialData,
bytes memory data
) external returns (uint256);

/// @dev Shorthand function that calls the `mint` function with empty `data`.
function mint(address _to, string calldata initialData) external returns (uint256);
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,27 @@ contract InverseAppProjectedNft is IInverseAppProjectedNft, ERC721, Ownable {
return true;
}

/// @dev Mints a new token to address `_to`.
/// @dev Mints a new token to address `_to`
/// Increases the `totalSupply` and `currentTokenId`.
/// Reverts if `_to` is a zero address or if it refers to smart contract but does not implement IERC721Receiver-onERC721Received.
/// Emits the `Minted` event.
function mint(address _to, bytes memory _verificationData) public virtual returns (uint256) {
/// @param _to where to send the NFT to
/// @param _verificationData any additional data to verify the validity of the mint
/// @param _data any additional data to pass to the receiver contract
/// @return id of the minted token
function mint(
address _to,
bytes memory _verificationData,
bytes memory _data
) public virtual returns (uint256) {
require(_to != address(0), "InverseAppProjectedNft: zero receiver address");
require(
validateMint(_to, _verificationData),
"InverseAppProjectedNft: invalid verification data"
);

uint256 tokenId = currentTokenId;
_safeMint(_to, tokenId);
_safeMint(_to, tokenId, _data);
mintCount[_to] += 1;
uint256 userTokenId = mintCount[_to];
tokenToMint[tokenId] = MintEntry(_to, userTokenId);
Expand All @@ -95,8 +103,14 @@ contract InverseAppProjectedNft is IInverseAppProjectedNft, ERC721, Ownable {
return tokenId;
}

/// @dev Shorthand function that calls the `mint` function with empty `_data`.
function mint(address _to, bytes memory _verificationData) public virtual returns (uint256) {
return mint(_to, _verificationData, bytes(""));
}

/// @dev Shorthand function that calls the `mint` function with empty `_verificationData` and empty `_data`.
function mint(address _to) public returns (uint256) {
return mint(_to, bytes(""));
return mint(_to, bytes(""), bytes(""));
}

/// @dev Burns token of ID `_tokenId`. Callable only by the owner of the specified token.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,19 @@ contract InverseBaseProjectedNft is IInverseBaseProjectedNft, ERC721, Ownable {
/// Increases the `totalSupply` and `currentTokenId`.
/// Reverts if `_to` is a zero address or if it refers to smart contract but does not implement IERC721Receiver-onERC721Received.
/// Emits the `Minted` event.
function mint(address _to, string calldata initialData) public virtual returns (uint256) {
/// @param _to where to send the NFT to
/// @param initialData data that is emitted in the `Minted` event
/// @param data any additional data to pass to the receiver contract
/// @return id of the minted token
function mint(
address _to,
string calldata initialData,
bytes memory data
) public virtual returns (uint256) {
require(_to != address(0), "InverseBaseProjectedNft: zero receiver address");

uint256 tokenId = currentTokenId;
_safeMint(_to, tokenId);
_safeMint(_to, tokenId, data);

totalSupply++;
currentTokenId++;
Expand All @@ -69,6 +77,11 @@ contract InverseBaseProjectedNft is IInverseBaseProjectedNft, ERC721, Ownable {
return tokenId;
}

/// @dev Shorthand function that calls the `mint` function with empty `data`.
function mint(address _to, string calldata initialData) public virtual returns (uint256) {
return mint(_to, initialData, bytes(""));
}

/// @dev Burns token of ID `_tokenId`. Callable only by the owner of the specified token.
/// Reverts if `_tokenId` does not exist.
function burn(uint256 _tokenId) public virtual onlyTokenOwner(_tokenId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ contract MockTokenUri is ITokenUri {
}
}

contract MockDataReceiver {
bytes public dataReceived;
function onERC721Received(
address,
address,
uint256,
bytes calldata data
) public returns (bytes4) {
dataReceived = data;
return this.onERC721Received.selector;
}
}

contract InverseAppProjectedNftTest is CTest, ERC721Holder {
using Strings for uint256;

Expand All @@ -42,19 +55,33 @@ contract InverseAppProjectedNftTest is CTest, ERC721Holder {
}

function test_CanMint() public {
vm.prank(alice);
vm.expectEmit(true, true, true, true);
emit IInverseAppProjectedNft.Minted(2, address(this), 2);
nft.mint(address(this), bytes(""), bytes(""));
}

function test_CanMintNoData() public {
vm.prank(alice);
vm.expectEmit(true, true, true, true);
emit IInverseAppProjectedNft.Minted(2, address(this), 2);
nft.mint(address(this), bytes(""));
}

function test_CanMintNoVerificationData() public {
function test_CanMintNoDataNoVerificationData() public {
vm.prank(alice);
vm.expectEmit(true, true, true, true);
emit IInverseAppProjectedNft.Minted(2, address(this), 2);
nft.mint(address(this));
}

function test_MintPassesDataToReceiver() public {
MockDataReceiver receiver = new MockDataReceiver();
bytes memory data = bytes("data");
nft.mint(address(receiver), "", data);
assertEq(keccak256(receiver.dataReceived()), keccak256(data));
}

function test_CanTransfer() public {
nft.transferFrom(address(this), alice, ownedTokenId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ contract MockTokenUri is ITokenUri {
}
}

contract MockDataReceiver {
bytes public dataReceived;
function onERC721Received(
address,
address,
uint256,
bytes calldata data
) public returns (bytes4) {
dataReceived = data;
return this.onERC721Received.selector;
}
}

contract InverseBaseProjectedNftTest is CTest, ERC721Holder {
using Strings for uint256;

Expand All @@ -42,12 +55,26 @@ contract InverseBaseProjectedNftTest is CTest, ERC721Holder {
}

function test_CanMint() public {
vm.prank(alice);
vm.expectEmit(true, true, true, true);
emit IInverseBaseProjectedNft.Minted(2, "abcd");
nft.mint(address(this), "abcd", bytes(""));
}

function test_CanMintNoData() public {
vm.prank(alice);
vm.expectEmit(true, true, true, true);
emit IInverseBaseProjectedNft.Minted(2, "abcd");
nft.mint(address(this), "abcd");
}

function test_MintPassesDataToReceiver() public {
MockDataReceiver receiver = new MockDataReceiver();
bytes memory data = bytes("data");
nft.mint(address(receiver), "", data);
assertEq(keccak256(receiver.dataReceived()), keccak256(data));
}

function test_CanTransfer() public {
nft.transferFrom(address(this), alice, ownedTokenId);
}
Expand Down

0 comments on commit e64944d

Please sign in to comment.