address sourceNetworkCollectionAddress,
) external payable whenNotPaused {
// check input parameters
if (releasedDeposits[depositChainId][depositNumber]) revert AlreadyUsed();
!multiSignatureOracle.signaturesCheckERC721(
sourceNetworkCollectionAddress,
// get collection address in release network
address collectionAddress = sourceNetworkCollectionAddress;
if (outsidePeggedCollections[collectionAddress] != address(0)) {
collectionAddress = outsidePeggedCollections[collectionAddress];
// calculate bridging fee
uint256 nftBridgingFee = defaultBridgeFee;
if (bridgeFees[collectionAddress] > 0) {
nftBridgingFee = bridgeFees[collectionAddress];
// check if transaction contains enough native tokens to pay the bridging fee
if (msg.value < nftBridgingFee) revert InvalidMessageValue(msg.value, nftBridgingFee);
// check if to-be-released token is part of the official collection (whitelisted)
if (officialCollectionWhitelist[collectionAddress] == true) {
ERC721Upgradeable(collectionAddress).safeTransferFrom(address(this), receiverAddress, tokenId);
MintableERC721(collectionAddress).mint(receiverAddress, tokenId);
mintedDeposits[collectionAddress][tokenId] = true;
// update records to track released deposits
releasedDeposits[depositChainId][depositNumber] = true;
// release successful, deposit event
emit TokenReleased(collectionAddress, tokenId, receiverAddress, depositChainId, depositNumber);