Developers Forum for XinFin XDC Network

Cover image for [Informative] How NFTs can be batched, creating new markets for batched assets
Quincy Jones
Quincy Jones

Posted on • Updated on

[Informative] How NFTs can be batched, creating new markets for batched assets

The concept of batched assets plays a pivotal role in contemporary asset management, serving as a cornerstone for optimizing processes, cost reduction, and the streamlining of diverse financial and operational activities.

In the context of smart contracts, an illustrative example involves the creation of a smart contract capable of consolidating tokens from multiple contracts, even encompassing multiple tokens within a singular contract. These aggregated tokens are then batched into a single token, offering possessors the ability to redeem the underlying tokens encapsulated within the smart contract. Such a tool finds valuable application in the realm of financial investments, particularly in the tokenization of collective assets managed as a unified entity.

One compelling instance of batched assets emerges within the sphere of investment portfolios. Here, the grouping of akin financial instruments, spanning stocks, bonds, and real estate, enables investors to effectively oversee and manage their portfolios, informed by comprehensive performance data.

Furthermore, in supply chain management, this concept underpins efficient inventory control, while in the tech sector, batched assets manifest in software updates. Software developers routinely bundle multiple patches and enhancements into a cohesive batch, facilitating seamless updates and bolstering system stability and security.

In manufacturing, batched assets are integral to production lines, where products with congruous specifications or production requisites are produced in clusters. This approach curtails setup and transition times, driving heightened efficiency and cost-effectiveness, particularly within the realm of collecting accounting in the form of NFTs.

The tokenization of diverse assets and objects using NFTs, alongside their integration into a contract governed by an NFT, offers a sophisticated mechanism for the management of multiple assets.

As the DeFi (Decentralized Finance) landscape matures, the sheer volume of tokens in circulation is poised to expand significantly, rendering batch processing an essential strategy to minimize operational overhead and complexity when grappling with these novel forms of tokenized assets.

//SPDX-License-Identifier: MIT

pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

/// @title Multi Asset Batch Contract
/// @author Quincy J
/// @notice This contract is meant to allow a multitude of different assets from different contracts to be referenced by a single token
/// @dev This contract is built to allow for more complex contracts to only have to manage  a single token rather than a complex multitude of different tokens

contract MultiAssetBatch is ERC1155{
    uint public handlerToken;
    string public batchName;
    uint public tokenIDNumber = 0;
    uint public maxBatchSize; //50-100 recomended

    constructor(uint _totalHandlers,string memory _URI,string memory _batchName,uint _maxBatchSize) ERC1155(_URI) {
        handlerToken = uint(keccak256(abi.encodePacked(_URI)));
        _mint(msg.sender,handlerToken,_totalHandlers, "");
        batchName = _batchName;
        maxBatchSize = _maxBatchSize; 
    }

    mapping(uint => Assets) assetID;
    mapping(address => Assets) assetContract;
    struct Assets{
        address assetContract;
        string assetName;
        uint[] amount;
        uint[] assetID;
        uint count;
        bool exist;
    }

    modifier handler{
        require(balanceOf(msg.sender,handlerToken) >= 1, "user does not hold handler token");
        _;
    }

    function addAssets(address _contract,string memory _assetName,uint[] memory _id,uint[] memory _amount)public handler returns(string memory,bool){
        require(tokenIDNumber <= maxBatchSize,"Contract has hit Max Batch limit");
        require(_id.length ==_amount.length ,"both the token id and the ammount arrays must have the same length");

        ERC1155 tokenContract = ERC1155(_contract);

        if(assetContract[_contract].exist == false){
            assetContract[_contract] = Assets(_contract,_assetName,_amount,_id,tokenIDNumber,true);
            assetID[tokenIDNumber] = Assets(_contract,_assetName,_amount,_id,tokenIDNumber,true);
            tokenIDNumber++;

            for(uint i =0;i<= _id.length;i++){
                require(tokenContract.balanceOf(msg.sender,_id[i]) >= 1,"user is missing a token");
            }

            tokenContract.safeBatchTransferFrom(msg.sender, address(this), _id, _amount, "");
            return ("new asset added",true);

        }else if(assetContract[_contract].exist == true && _id.length != 0 && _amount.length != 0 && _amount.length == _id.length){
            for(uint256 i = 0; i < _id.length; i++){
                assetContract[_contract].assetID.push(_id[i]);
                assetContract[_contract].amount.push(_amount[i]);

                assetID[assetContract[_contract].count].assetID.push(_id[i]);
                assetID[assetContract[_contract].count].amount.push(_amount[i]);
            }
            tokenContract.safeBatchTransferFrom(msg.sender, address(this), _id, _amount, "");

            return ("Assets Added",true);
        } else {
            return ("asset already exist",false);
        }
    }

    function redeemAssets()public handler returns(bool){
        for(uint i; i <= tokenIDNumber;i++){
            ERC1155 tokenContract = ERC1155(assetID[i].assetContract);
            tokenContract.safeBatchTransferFrom(address(this),msg.sender, assetID[i].assetID, assetID[i].amount, "");
        }
        return true;
    }

    function viewAssets(uint _tokenIDNumber)public  view returns(address,string memory,uint[] memory,uint[] memory,uint,bool){
        return (assetID[_tokenIDNumber].assetContract,assetID[_tokenIDNumber].assetName,assetID[_tokenIDNumber].amount,assetID[_tokenIDNumber].assetID,assetID[_tokenIDNumber].count,assetID[_tokenIDNumber].exist);
    }

    //ERC1155Received fuctions
    function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual returns (bytes4) {
        return this.onERC1155Received.selector;
    }
    function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory) public virtual returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
    function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
        return this.onERC721Received.selector;
    }

    fallback() external payable {}
    receive() external payable {} 
}
Enter fullscreen mode Exit fullscreen mode

Github: https://github.com/CoinClubQuincy/XDC-BrokerageDapp/blob/main/contracts/BrokerageTools/MultiAssetBatch.sol

Discussion (1)

Collapse
akhekade profile image
Atul Khekade

always a good read!