Skip to content

Commit

Permalink
Add test coverage for NFT functions
Browse files Browse the repository at this point in the history
  • Loading branch information
brayansdt committed Feb 15, 2024
1 parent 2741beb commit 9936741
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 5 deletions.
56 changes: 51 additions & 5 deletions test/bridge/x/v4/MockCoreV4.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
pragma solidity ^0.8.19;

import {CoreV4} from "../../../../contracts/bridge/x/v4/CoreV4.sol";
import {Asset} from "../../../../contracts/token/erc721/x/Asset.sol";
import {Minting} from "../../../../contracts/token/erc721/x/utils/Minting.sol";

contract MockCoreV4 is CoreV4 {
address internal ZERO_ADDRESS = address(0);
Expand All @@ -16,6 +18,10 @@ contract MockCoreV4 is CoreV4 {

uint256 internal constant MASK_ADDRESS = (1 << 160) - 1;

// Pending withdrawals.
// A map asset type => contract address.
mapping(uint256 => address) internal tokenContracts;

fallback() external payable {
revert();
}
Expand Down Expand Up @@ -250,7 +256,7 @@ contract MockCoreV4 is CoreV4 {
}

function onERC721Received(address, address, uint256, bytes memory) external pure override returns (bytes4) {
revert("Not implemented");
return this.onERC721Received.selector;
}

function orderRegistryAddress() external pure override returns (address) {
Expand Down Expand Up @@ -300,6 +306,10 @@ contract MockCoreV4 is CoreV4 {
revert("Not implemented");
}

function addTokenContract(uint256 assetType, address tokenContract) external {
tokenContracts[assetType] = tokenContract;
}

function registerToken(uint256 assetType, bytes memory assetInfo, uint256 quantum) external pure override {
revert("Not implemented");
}
Expand All @@ -325,12 +335,48 @@ contract MockCoreV4 is CoreV4 {
emit LogWithdrawalPerformed(ownerKey, assetType, amount, amount, recipient);
}

function withdrawAndMint(uint256 ownerKey, uint256 assetType, bytes memory mintingBlob) external pure override {
revert("Not implemented");
function withdrawAndMint(uint256 ownerKey, uint256 assetType, bytes calldata mintingBlob) external override {
address payable recipient = payable(getEthKey(ownerKey));
require(recipient != ZERO_ADDRESS, "USER_UNREGISTERED");

(uint256 tokenId, bytes memory blueprint) = Minting.split(mintingBlob);
uint256 assetId = assetType + tokenId;
uint256 amount = pendingWithdrawals[ownerKey][assetId];
pendingWithdrawals[ownerKey][assetId] = 0;
require(amount == 1, "INVALID_AMOUNT");

// Make sure we don't accidentally burn funds.
require(recipient != address(0x0), "INVALID_RECIPIENT");
address tokenAddress = tokenContracts[assetType];
require(tokenAddress != address(0x0), "INVALID_CONTRACT");

Asset(tokenAddress).mintFor(address(recipient), amount, mintingBlob);
}

function withdrawNft(uint256 ownerKey, uint256 assetType, uint256 tokenId) external pure override {
revert("Not implemented");
function withdrawNft(uint256 ownerKey, uint256 assetType, uint256 tokenId) external override {
uint256 assetId = assetType + tokenId;

address payable recipient = payable(getEthKey(ownerKey));
require(recipient != ZERO_ADDRESS, "USER_UNREGISTERED");

uint256 amount = pendingWithdrawals[ownerKey][assetId];
pendingWithdrawals[ownerKey][assetId] = 0;

require(amount == 1, "INVALID_AMOUNT");

// Transfer funds.
transferOutNft(recipient, assetType, tokenId);

emit LogNftWithdrawalPerformed(ownerKey, assetType, tokenId, assetId, recipient);
}

function transferOutNft(address recipient, uint256 assetType, uint256 tokenId) internal {
// Make sure we don't accidentally burn funds.
require(recipient != address(0x0), "INVALID_RECIPIENT");
address tokenAddress = tokenContracts[assetType];
require(tokenAddress != address(0x0), "INVALID_CONTRACT");

Asset(tokenAddress).safeTransferFrom(address(this), recipient, tokenId);
}

function STARKEX_MAX_DEFAULT_VAULT_LOCK() external pure override returns (uint256) {
Expand Down
75 changes: 75 additions & 0 deletions test/bridge/x/v4/RegistrationV4.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {RegistrationV4} from "../../../../contracts/bridge/x/v4/RegistrationV4.s
import {Test} from "forge-std/Test.sol";
import {DeployRegistrationV4Dev} from "../../../../script/DeployRegistrationV4Dev.s.sol";
import {MockCoreV4} from "./MockCoreV4.sol";
import {Asset} from "../../../../contracts/token/erc721/x/Asset.sol";
import {console} from "forge-std/console.sol";

contract RegistrationV4Test is Test {
MockCoreV4 public mockCore;
Expand Down Expand Up @@ -184,4 +186,77 @@ contract RegistrationV4Test is Test {
assertTrue(registration.isRegistered(starkKey));
assertEq(ethAdd, registration.imx().getEthKey(starkKey));
}

function testCompleteWithdrawalNFT_WhenUserIsNotRegistered() public {
address ethAdd = 0xac3cc5a41D9e8c94Fe64138C1343A07B2fF5ff76;
uint256 ethKey = 983301674259619813482344086789227297671214399350;
// 0x7a88d4e1a357d33d6168058ac6b08fa54c07b72313f78af594d4d44e8268a6c
uint256 starkKey = 3463995498836494504631329032145085468217956335318243415256427132985150966380;

// arrange
bytes memory regSig = abi.encodePacked(
uint256(0x06f56e3e7392318ae672ff7d68d1b6c54a6f402019bd121dee9b8d8aa9658ab5), // r
uint256(0x06c1b98af915c6c1f88ea15f22f2d4f4a7a20c5416cafca0538bf227469dc14a), // s
uint256(0x02ec99c3c1d90d78dd77676a2505bbeba3cf9ecd1003d72c14949817d84625a4) // starkY
);

// 0x31e2a7a568737baacd430d7750c9bf07dba85ba60d13b6b6fe8d47e8d13aa21
uint256 assetType = 1410237129265691706741215969248966526395742991743406915223458527859231140385;
uint256 quantity = 1;
uint256 tokenId = 6;

// arrange nft contract
Asset nftContract = new Asset(address(this), "name", "symbol", address(registration.imx()));
mockCore.addTokenContract(assetType, address(nftContract));
mockCore.addWithdrawalBalance(starkKey, assetType + tokenId, 1);
nftContract.mintFor(address(mockCore), quantity, abi.encodePacked("{6}:{onchain-metadata}"));

// pre-checks
assertFalse(registration.isRegistered(starkKey));
assertEq(0, nftContract.balanceOf(ethAdd));

// act
registration.registerAndWithdrawNft(ethAdd, starkKey, regSig, assetType, tokenId);

// assert
assertTrue(registration.isRegistered(starkKey));
assertEq(quantity, nftContract.balanceOf(ethAdd));
}

function testCompleteWithdrawalAndMintNFT_WhenUserIsNotRegistered() public {
address ethAdd = 0xac3cc5a41D9e8c94Fe64138C1343A07B2fF5ff76;
uint256 ethKey = 983301674259619813482344086789227297671214399350;
// 0x7a88d4e1a357d33d6168058ac6b08fa54c07b72313f78af594d4d44e8268a6c
uint256 starkKey = 3463995498836494504631329032145085468217956335318243415256427132985150966380;

// arrange
bytes memory regSig = abi.encodePacked(
uint256(0x06f56e3e7392318ae672ff7d68d1b6c54a6f402019bd121dee9b8d8aa9658ab5), // r
uint256(0x06c1b98af915c6c1f88ea15f22f2d4f4a7a20c5416cafca0538bf227469dc14a), // s
uint256(0x02ec99c3c1d90d78dd77676a2505bbeba3cf9ecd1003d72c14949817d84625a4) // starkY
);

// 0x31e2a7a568737baacd430d7750c9bf07dba85ba60d13b6b6fe8d47e8d13aa21
uint256 assetType = 1410237129265691706741215969248966526395742991743406915223458527859231140385;
uint256 quantity = 1;
uint256 tokenId = 7;

// arrange nft contract
Asset nftContract = new Asset(address(this), "name", "symbol", address(registration.imx()));
mockCore.addTokenContract(assetType, address(nftContract));
mockCore.addWithdrawalBalance(starkKey, assetType + tokenId, 1);

// pre-checks
assertFalse(registration.isRegistered(starkKey));
assertEq(0, nftContract.balanceOf(ethAdd));

// act
registration.registerWithdrawAndMint(
ethAdd, starkKey, regSig, assetType, abi.encodePacked("{7}:{onchain-metadata}")
);

// assert
assertTrue(registration.isRegistered(starkKey));
assertEq(quantity, nftContract.balanceOf(ethAdd));
}
}

0 comments on commit 9936741

Please sign in to comment.