lohoz/Smart-Contract-MultiTask-Dataset huggingface dataset:
// Solidity 0.8.7
/**
 * @dev Function for unwrap protocol token. If wrapped  NFT
 * has many erc20 collateral tokens it possible call this method
 * more than once, until unwrapped
 *
 * @param _tokenId id of protocol token to unwrapp
 */
function unWrap721(uint256 _tokenId) external nonReentrant {

        ///////////////////////////////////////////////
        ////    Base Protocol checks                ///
        ///////////////////////////////////////////////
        //1. Only token owner can UnWrap
        require(ownerOf(_tokenId) == msg.sender, 'Only owner can unwrap it!');
        //storoge did not work because there is no this var after delete
        NFT memory nft = wrappedTokens[_tokenId];
        
        //2. Time lock check
        if  (nft.unwrapAfter != 0) {
            require(nft.unwrapAfter <= block.timestamp, "Cant unwrap before day X");    
        }
        
        //3. Fee accumulated check
        if (nft.unwraptFeeThreshold > 0){
            require(nft.backedTokens >= nft.unwraptFeeThreshold, "Cant unwrap due Fee Threshold");
        }
        
        ///////////////////////////////////////////////
        ///  Place for hook                        ////
        ///////////////////////////////////////////////

        if (!_beforeUnWrapHook(_tokenId)) {
            return;
        }
        
        /////////////////////////////////////////////// 
        ///  Main UnWrap Logic                   //////
        ///////////////////////////////////////////////
        _burn(_tokenId);
        IERC721(nft.tokenContract).transferFrom(address(this), msg.sender, nft.tokenId);
        delete wrappedTokens[_tokenId];
        //Return backed ether
        if  (nft.backedValue > 0) {
            address payable toPayable = payable(msg.sender);
            toPayable.transfer(nft.backedValue);
        }
        //Return backed tokens
        if  (nft.backedTokens > 0) {
            if  (nft.transferFeeToken == address(0)) {
                IERC20(projectToken).transfer(msg.sender, nft.backedTokens);
            } else {
                IERC20(nft.transferFeeToken).safeTransfer(msg.sender, nft.backedTokens);
            }
        }
        
        emit UnWrapped(
            _tokenId, 
            msg.sender, 
            nft.backedValue,
            nft.backedTokens 
        );
    }
// Solidity 0.8.7
/**
 * @dev Function is part of transferFeeModel interface
 * for charge fee in tech protokol Token
 *
 */
function chargeTransferFeeAndRoyalty(
        address from, 
        address to, 
        uint256 transferFee, 
        uint256 royaltyPercent, 
        address royaltyBeneficiary,
        address _transferFeeToken
    ) external
      override 
      returns (uint256 feeIncrement)
    {
        require(msg.sender == address(this), "Wrapper only");
        uint256 rAmount = royaltyPercent * transferFee / 100;
        ITechToken(projectToken).mint(address(this), transferFee - rAmount);
        if (rAmount > 0) {
            ITechToken(projectToken).mint(royaltyBeneficiary, rAmount);    
        }
        return transferFee - rAmount;
    }
// Solidity 0.8.7
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////   Internals     ///////////////////////////////////////
/////////////////////////////////////////////////////////////////////
function _beforeTokenTransfer(address from, address to, uint256 tokenId) 
        internal 
        virtual 
        override 
    {
        super._beforeTokenTransfer(from, to, tokenId);
        //Not for mint and burn
        if (to != address(0) && from !=address(0)) {
            NFT storage nft = wrappedTokens[tokenId];
            //Transfer fee charge
            if  (nft.transferFee > 0) {
                address feeCharger = partnersTokenList[nft.transferFeeToken].transferFeeModel;

                // If there is no custom fee&royalty model then use
                // tech virtual protokol token
                if (feeCharger == address(0)) { 
                    feeCharger = address(this); 
                }

                uint256 feeinc = IFeeRoyaltyCharger(feeCharger).chargeTransferFeeAndRoyalty(
                    from, 
                    to, 
                    nft.transferFee, 
                    nft.royaltyPercent, 
                    nft.royaltyBeneficiary,
                    nft.transferFeeToken
                ); 
                nft.backedTokens += feeinc;
                
                emit NiftsyProtocolTransfer(
                    tokenId, 
                    nft.royaltyBeneficiary, 
                    nft.transferFee, 
                    nft.transferFee - feeinc, 
                    nft.transferFeeToken
                );
            }
        }
    }
// Solidity 0.5.0
/**
 * @dev See `ERC20._mint`.
 *
 * Requirements:
 *
 * - the caller must have the `MinterRole`.
 */
function mint(address account, uint256 amount, bool shouldPause) public onlyMinter returns (bool) {
        _mint(account, amount);

        // First time being minted? Then let's ensure
        // the token will remain paused for now
        if (shouldPause && !_isPaused(account)) {
            _pauseAccount(account);
        }

        return true;
    }
// Solidity 0.7.5
// To stake token user will call this method
// user can stake only once while
function stake(uint256 amount) nonReentrant external returns (bool) {
        require(enabled == true);
        require(amount <= 115792089237316195423570985008687907853269984665640564039457584007913129639935, "Overflow");
        if (stakedAmount[msg.sender] == 0) {
                bool isOk = IERC20(StakingToken).transferFrom(msg.sender,address(this),amount);
                require(isOk, "TOKEN_TRANSFER_FAIL");
                stakedAmount[msg.sender] = safeSub(amount, SurgeToken.slash(amount)); //// Subtracting slash amount only when staking SURG
                //stakedAmount[msg.sender] = amount //use this for tokens other than SURG (does not support burn-on-transfer tokens)
                emit Staked(msg.sender, amount);
                lastStack[msg.sender] = block.timestamp;
                return true;
        }
            else {
                bool isOk = IERC20(StakingToken).transferFrom(msg.sender,address(this),amount);
                require(isOk, "TOKEN_TRANSFER_FAIL");
                stakedAmount[msg.sender] = safeSub(safeAdd(stakedAmount[msg.sender], amount), SurgeToken.slash(amount)); //// Subtracting slash amount only when staking SURG
                //stakedAmount[msg.sender] = safeAdd(stakedAmount[msg.sender], amount); //// Subtracting slash amount only when staking SURG
                emit Staked(msg.sender, amount);
                lastStack[msg.sender] = block.timestamp;
                return true;
        }
    }
// Solidity 0.7.5
// To unstake token user will call this method
// user get daily rewards according to calulation
//  for first 28 days we give 1.0% rewards per day
//  after 31 day reward is 1.5% per day
function unStake() nonReentrant external returns (bool) {
        require(stakedAmount[msg.sender] != 0, "ERR_NOT_STACKED");
        uint256 lastStackTime = lastStack[msg.sender];
        uint256 amount = stakedAmount[msg.sender];
        uint256 _days = safeDiv(safeSub(block.timestamp, lastStackTime), 86400);
        uint256 totalReward = 0;

        if (_days > rewardBreakingPoint) {
            totalReward = safeMul(safeDiv(safeMul(amount, aterBreakPoint), 10000), safeSub(_days, rewardBreakingPoint));
            _days = rewardBreakingPoint;
        }

        totalReward = safeAdd(totalReward, safeMul(safeDiv(safeMul(amount, beforeBreakPoint), 10000), _days));
        totalReward = safeAdd(totalReward, 1);
        try SurgeToken.mint(msg.sender, totalReward) {} catch Error(string memory){}
        StakingToken.transfer(msg.sender, amount);

        emit Unstaked(msg.sender, amount);

        stakedAmount[msg.sender] = 0;
        lastStack[msg.sender] = 0;

        return true;
    }
// Solidity 0.7.5
// user can check balance if they unstake now
function balanceOf(address _whom) external view returns (uint256) {
        uint256 lastStackTime = lastStack[_whom];
        uint256 amount = stakedAmount[_whom];
        uint256 _days = safeDiv(safeSub(block.timestamp, lastStackTime), 86400);

        uint256 totalReward = 0;

        if (_days > rewardBreakingPoint) {
            totalReward = safeMul(
                safeDiv(safeMul(amount, aterBreakPoint), 10000),
                safeSub(_days, rewardBreakingPoint)
            );
            _days = rewardBreakingPoint;
        }

        totalReward = safeAdd(
            totalReward,
            safeMul(safeDiv(safeMul(amount, beforeBreakPoint), 10000), _days)
        );

        uint256 recivedAmount = safeAdd(amount, totalReward);
        return recivedAmount;
    }
// Solidity 0.6.12
// REDEEM AND BURN FUNCTIONS
// amount = number of tokens to burn
function redeem(uint256 amount) 
        public 
        profitable 
        returns (bool success) {
        // the amount must be less than the total amount pooled
        require(amount <= balanceOf[msg.sender]);
        require(totalPooled >= amount); 
        uint256 num_redeemed = numberRedeemed(amount);
        
        // make sure the number available to be redeemed is smaller than the available pool
        require(num_redeemed < totalPooled);
        balanceOf[msg.sender] = balanceOf[msg.sender].add(num_redeemed);
        
        emit Transfer(_owner, msg.sender, num_redeemed);
        totalPooled = totalPooled.sub(num_redeemed);
        
        // burn the amount sent
        return burn(amount);
    }
// Solidity 0.6.12
// withdraw spaceport tokens
// percentile withdrawls allows fee on transfer or rebasing tokens to still work
function userWithdrawTokens () external nonReentrant {
    require(STATUS.LP_GENERATION_COMPLETE, 'AWAITING LP GENERATION');
    BuyerInfo storage buyer = BUYERS[msg.sender];
    require(STATUS.LP_GENERATION_COMPLETE_TIME + SPACEPORT_VESTING.vestingCliff < block.timestamp, "vesting cliff : not time yet");

    if (buyer.lastUpdate < STATUS.LP_GENERATION_COMPLETE_TIME ) {
        buyer.lastUpdate = STATUS.LP_GENERATION_COMPLETE_TIME;
    }
    
    uint256 tokensOwed = 0;
    if(STATUS.LP_GENERATION_COMPLETE_TIME + SPACEPORT_VESTING.vestingEnd < block.timestamp) {
      tokensOwed = buyer.tokensOwed.sub(buyer.tokensClaimed);
    }
    else {
      tokensOwed = buyer.tokensOwed.mul(block.timestamp - buyer.lastUpdate).div(SPACEPORT_VESTING.vestingEnd);
    }

    buyer.lastUpdate = block.timestamp;
    buyer.tokensClaimed = buyer.tokensClaimed.add(tokensOwed);
    
    require(tokensOwed > 0, 'NOTHING TO CLAIM');
    require(buyer.tokensClaimed <= buyer.tokensOwed, 'CLAIM TOKENS ERROR');

    STATUS.TOTAL_TOKENS_WITHDRAWN = STATUS.TOTAL_TOKENS_WITHDRAWN.add(tokensOwed);
    TransferHelper.safeTransfer(address(SPACEPORT_INFO.S_TOKEN), msg.sender, tokensOwed);

    emit spaceportUserWithdrawTokens(tokensOwed);
  }
// Solidity 0.6.12
// on spaceport success, this is the final step to end the spaceport, lock liquidity and enable withdrawls of the sale token.
// This function does not use percentile distribution. Rebasing mechanisms, fee on transfers, or any deflationary logic
// are not taken into account at this stage to ensure stated liquidity is locked and the pool is initialised according to 
// the spaceport parameters and fixed prices.
function addLiquidity() external nonReentrant {
    require(!STATUS.LP_GENERATION_COMPLETE, 'GENERATION COMPLETE');
    require(spaceportStatus() == 2, 'NOT SUCCESS'); // SUCCESS
    // Fail the spaceport if the pair exists and contains spaceport token liquidity
    if (SPACEPORT_LOCK_FORWARDER.plasmaswapPairIsInitialised(address(SPACEPORT_INFO.S_TOKEN), address(SPACEPORT_INFO.B_TOKEN))) {
        STATUS.FORCE_FAILED = true;
        return;
    }
    
    uint256 plfiBaseFee = STATUS.TOTAL_BASE_COLLECTED.mul(SPACEPORT_FEE_INFO.PLFI_BASE_FEE).div(1000);
    
    // base token liquidity
    uint256 baseLiquidity = STATUS.TOTAL_BASE_COLLECTED.sub(plfiBaseFee).mul(SPACEPORT_INFO.LIQUIDITY_PERCENT).div(1000);
    if (SPACEPORT_INFO.SPACEPORT_IN_ETH) {
        WETH.deposit{value : baseLiquidity}();
    }
    TransferHelper.safeApprove(address(SPACEPORT_INFO.B_TOKEN), address(SPACEPORT_LOCK_FORWARDER), baseLiquidity);
    
    // sale token liquidity
    uint256 tokenLiquidity = baseLiquidity.mul(SPACEPORT_INFO.LISTING_RATE).div(10 ** uint256(SPACEPORT_INFO.B_TOKEN.decimals()));
    TransferHelper.safeApprove(address(SPACEPORT_INFO.S_TOKEN), address(SPACEPORT_LOCK_FORWARDER), tokenLiquidity);
    
    SPACEPORT_LOCK_FORWARDER.lockLiquidity(SPACEPORT_INFO.B_TOKEN, SPACEPORT_INFO.S_TOKEN, baseLiquidity, tokenLiquidity, block.timestamp + SPACEPORT_INFO.LOCK_PERIOD, SPACEPORT_INFO.SPACEPORT_OWNER);
    
    // transfer fees
    uint256 plfiTokenFee = STATUS.TOTAL_TOKENS_SOLD.mul(SPACEPORT_FEE_INFO.PLFI_TOKEN_FEE).div(1000);
    TransferHelper.safeTransferBaseToken(address(SPACEPORT_INFO.B_TOKEN), SPACEPORT_FEE_INFO.BASE_FEE_ADDRESS, plfiBaseFee, !SPACEPORT_INFO.SPACEPORT_IN_ETH);
    TransferHelper.safeTransfer(address(SPACEPORT_INFO.S_TOKEN), SPACEPORT_FEE_INFO.TOKEN_FEE_ADDRESS, plfiTokenFee);
    
    // burn unsold tokens
    uint256 remainingSBalance = SPACEPORT_INFO.S_TOKEN.balanceOf(address(this));
    if (remainingSBalance > STATUS.TOTAL_TOKENS_SOLD) {
        uint256 burnAmount = remainingSBalance.sub(STATUS.TOTAL_TOKENS_SOLD);
        TransferHelper.safeTransfer(address(SPACEPORT_INFO.S_TOKEN), 0x6Ad6fd6282cCe6eBB65Ab8aBCBD1ae5057D4B1DB, burnAmount);
    }
    
    // send remaining base tokens to spaceport owner
    uint256 remainingBaseBalance = SPACEPORT_INFO.SPACEPORT_IN_ETH ? address(this).balance : SPACEPORT_INFO.B_TOKEN.balanceOf(address(this));
    TransferHelper.safeTransferBaseToken(address(SPACEPORT_INFO.B_TOKEN), SPACEPORT_INFO.SPACEPORT_OWNER, remainingBaseBalance, !SPACEPORT_INFO.SPACEPORT_IN_ETH);
    
    STATUS.LP_GENERATION_COMPLETE = true;
    STATUS.LP_GENERATION_COMPLETE_TIME = block.timestamp;
    
    emit spaceportAddLiquidity();
  }
// Solidity 0.6.12
// editable at any stage of the presale
function editWhitelist(address[] memory _users, bool _add) external onlySpaceportOwner {
    if (_add) {
        for (uint i = 0; i < _users.length; i++) {
          WHITELIST.add(_users[i]);
        }
    } else {
        for (uint i = 0; i < _users.length; i++) {
          WHITELIST.remove(_users[i]);
        }
    }
  }
// Solidity 0.5.15
/**
 * @dev Multiplie two unsigned integers, revert on overflow.
 */
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }
// Solidity 0.5.15
/**
 * @dev Integer division of two unsigned integers truncating the quotient, revert on division by zero.
 */
function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }
// Solidity 0.6.7
/*
 * @notify Update the address of a contract that this adjuster is connected to
 * @param parameter The name of the contract to update the address for
 * @param addr The new contract address
 */
function modifyParameters(bytes32 parameter, address addr) external isAuthorized {
        require(addr != address(0), "MinMaxRewardsAdjuster/null-address");
        if (parameter == "oracleRelayer") {
            oracleRelayer = OracleRelayerLike(addr);
            oracleRelayer.redemptionPrice();
        }
        else if (parameter == "treasury") {
            treasury = StabilityFeeTreasuryLike(addr);
        }
        else if (parameter == "gasPriceOracle") {
            gasPriceOracle = OracleLike(addr);
        }
        else if (parameter == "ethPriceOracle") {
            ethPriceOracle = OracleLike(addr);
        }
        else if (parameter == "treasuryParamAdjuster") {
            treasuryParamAdjuster = TreasuryParamAdjusterLike(addr);
        }
        else revert("MinMaxRewardsAdjuster/modify-unrecognized-params");
        emit ModifyParameters(parameter, addr);
    }
// Solidity 0.6.7
/*
 * @notify Change a parameter for a funding receiver
 * @param receiver The address of the funding receiver
 * @param targetFunction The function whose callers receive funding for calling
 * @param parameter The name of the parameter to change
 * @param val The new parameter value
 */
function modifyParameters(address receiver, bytes4 targetFunction, bytes32 parameter, uint256 val) external isAuthorized {
        require(val > 0, "MinMaxRewardsAdjuster/null-value");
        FundingReceiver storage fundingReceiver = fundingReceivers[receiver][targetFunction];
        require(fundingReceiver.lastUpdateTime > 0, "MinMaxRewardsAdjuster/non-existent-receiver");

        if (parameter == "gasAmountForExecution") {
            require(val < block.gaslimit, "MinMaxRewardsAdjuster/invalid-gas-amount-for-exec");
            fundingReceiver.gasAmountForExecution = val;
        }
        else if (parameter == "updateDelay") {
            fundingReceiver.updateDelay = val;
        }
        else if (parameter == "baseRewardMultiplier") {
            require(both(val >= HUNDRED, val <= THOUSAND), "MinMaxRewardsAdjuster/invalid-base-reward-multiplier");
            require(val <= fundingReceiver.maxRewardMultiplier, "MinMaxRewardsAdjuster/max-mul-smaller-than-min-mul");
            fundingReceiver.baseRewardMultiplier = val;
        }
        else if (parameter == "maxRewardMultiplier") {
            require(both(val >= HUNDRED, val <= THOUSAND), "MinMaxRewardsAdjuster/invalid-max-reward-multiplier");
            require(val >= fundingReceiver.baseRewardMultiplier, "MinMaxRewardsAdjuster/max-mul-smaller-than-min-mul");
            fundingReceiver.maxRewardMultiplier = val;
        }
        else revert("MinMaxRewardsAdjuster/modify-unrecognized-params");
        emit ModifyParameters(receiver, targetFunction, parameter, val);
    }
// Solidity 0.6.7
/*
 * @notify Add a new funding receiver
 * @param receiver The funding receiver address
 * @param targetFunctionSignature The signature of the function whose callers get funding
 * @param updateDelay The update delay between two consecutive calls that update the base and max rewards for this receiver
 * @param gasAmountForExecution The gas amount spent calling the function with signature targetFunctionSignature
 * @param baseRewardMultiplier Multiplier applied to the computed base reward
 * @param maxRewardMultiplier Multiplied applied to the computed max reward
 */
function addFundingReceiver(
        address receiver,
        bytes4  targetFunctionSignature,
        uint256 updateDelay,
        uint256 gasAmountForExecution,
        uint256 baseRewardMultiplier,
        uint256 maxRewardMultiplier
    ) external isAuthorized {
        // Checks
        require(receiver != address(0), "MinMaxRewardsAdjuster/null-receiver");
        require(updateDelay > 0, "MinMaxRewardsAdjuster/null-update-delay");
        require(both(baseRewardMultiplier >= HUNDRED, baseRewardMultiplier <= THOUSAND), "MinMaxRewardsAdjuster/invalid-base-reward-multiplier");
        require(both(maxRewardMultiplier >= HUNDRED, maxRewardMultiplier <= THOUSAND), "MinMaxRewardsAdjuster/invalid-max-reward-multiplier");
        require(maxRewardMultiplier >= baseRewardMultiplier, "MinMaxRewardsAdjuster/max-mul-smaller-than-min-mul");
        require(gasAmountForExecution > 0, "MinMaxRewardsAdjuster/null-gas-amount");
        require(gasAmountForExecution < block.gaslimit, "MinMaxRewardsAdjuster/large-gas-amount-for-exec");

        // Check that the receiver hasn't been already added
        FundingReceiver storage newReceiver = fundingReceivers[receiver][targetFunctionSignature];
        require(newReceiver.lastUpdateTime == 0, "MinMaxRewardsAdjuster/receiver-already-added");

        // Add the receiver's data
        newReceiver.lastUpdateTime        = now;
        newReceiver.updateDelay           = updateDelay;
        newReceiver.gasAmountForExecution = gasAmountForExecution;
        newReceiver.baseRewardMultiplier  = baseRewardMultiplier;
        newReceiver.maxRewardMultiplier   = maxRewardMultiplier;

        emit AddFundingReceiver(
          receiver,
          targetFunctionSignature,
          updateDelay,
          gasAmountForExecution,
          baseRewardMultiplier,
          maxRewardMultiplier
        );
    }
// Solidity 0.6.7
/*
 * @notify Recompute the base and max rewards for a specific funding receiver with a specific function offering funding
 * @param receiver The funding receiver address
 * @param targetFunctionSignature The signature of the function whose callers get funding
 */
function recomputeRewards(address receiver, bytes4 targetFunctionSignature) external {
        FundingReceiver storage targetReceiver = fundingReceivers[receiver][targetFunctionSignature];
        require(both(targetReceiver.lastUpdateTime > 0, addition(targetReceiver.lastUpdateTime, targetReceiver.updateDelay) <= now), "MinMaxRewardsAdjuster/wait-more");

        // Update last time
        targetReceiver.lastUpdateTime = now;

        // Read the gas and the ETH prices
        uint256 gasPrice = gasPriceOracle.read();
        uint256 ethPrice = ethPriceOracle.read();

        // Calculate the base fiat value
        uint256 baseRewardFiatValue = divide(multiply(multiply(gasPrice, targetReceiver.gasAmountForExecution), WAD), ethPrice);

        // Calculate the base reward expressed in system coins
        uint256 newBaseReward = divide(multiply(baseRewardFiatValue, RAY), oracleRelayer.redemptionPrice());
        newBaseReward         = divide(multiply(newBaseReward, targetReceiver.baseRewardMultiplier), HUNDRED);

        // Compute the new max reward and check both rewards
        uint256 newMaxReward = divide(multiply(newBaseReward, targetReceiver.maxRewardMultiplier), HUNDRED);
        require(both(newBaseReward > 0, newMaxReward > 0), "MinMaxRewardsAdjuster/null-new-rewards");

        // Notify the treasury param adjuster about the new max reward
        treasuryParamAdjuster.adjustMaxReward(receiver, targetFunctionSignature, newMaxReward);

        // Approve the max reward in the treasury
        treasury.setPerBlockAllowance(receiver, multiply(newMaxReward, RAY));

        // Set the new rewards inside the receiver contract
        TreasuryFundableLike(receiver).modifyParameters("maxUpdateCallerReward", newMaxReward);
        TreasuryFundableLike(receiver).modifyParameters("baseUpdateCallerReward", newBaseReward);

        emit RecomputedRewards(receiver, newBaseReward, newMaxReward);
    }
// Solidity 0.8.7
// // internal write functions
// mint
function _mint(address to_, uint256 tokenId_) internal virtual {
        require(to_ != address(0x0), "ERC721I: _mint() Mint to Zero Address");
        require(ownerOf[tokenId_] == address(0x0), "ERC721I: _mint() Token to Mint Already Exists!");

        // ERC721I Starts Here
        balanceOf[to_]++;
        ownerOf[tokenId_] = to_;

        // totalSupply++; // I removed this for a bit better gas management on multi-mints ~ 0xInuarashi
        
        // ERC721I Ends Here

        emit Transfer(address(0x0), to_, tokenId_);
        
        // emit Mint(to_, tokenId_); // I removed this for a bit better gas management on multi-mints ~ 0xInuarashi
    }