function createCubegon(bytes32 _ch, bytes32 _cmt, bytes32 _tmt, uint _energyLimit, uint _expiryTime, uint8 _v, bytes32 _r, bytes32 _s) isActive payable external {
        if (verifyAddress == address(0)) revert();
        if (_expiryTime < block.timestamp) revert();
        if (getVerifyAddress(msg.sender, _ch, _cmt, _tmt, _energyLimit, _expiryTime, _v, _r, _s) != verifyAddress) revert();
        uint payAmount = energyPrices[_energyLimit];
        if (payAmount == 0 || payAmount > msg.value) revert();
        
        CubegonMaterial memory cm;
        (cm.mId1, cm.amount1, cm.mId2, cm.amount2, cm.mId3, cm.amount3, cm.mId4, cm.amount4) = extractMaterialToken(_tmt);
        payAmount += cubegoCore.buyMaterials(msg.sender, cm.mId1, cm.amount1, cm.mId2, cm.amount2, cm.mId3, cm.amount3, cm.mId4, cm.amount4);
        if (payAmount > msg.value) revert();

        (cm.mId1, cm.amount1, cm.mId2, cm.amount2, cm.mId3, cm.amount3, cm.mId4, cm.amount4) = extractMaterialToken(_cmt);
        cubegoCore.removeMaterials(msg.sender, cm.mId1, cm.amount1, cm.mId2, cm.amount2, cm.mId3, cm.amount3, cm.mId4, cm.amount4);
        
        
        if (msg.value > payAmount) {
            msg.sender.transfer((msg.value - payAmount));
        }
        
        cm.energyLimit = _energyLimit;
        cubegonNFT.mineCubegon(msg.sender, _ch, cm.mId1, cm.amount1, cm.mId2, cm.amount2, cm.mId3, cm.amount3, cm.mId4, cm.amount4, cm.energyLimit);
    }