As long as no units of a mosaic exist on the network, its creator can still change its definition properties
(flags, divisibility, and duration) by sending a second definition transaction with the same identifier.
For example, adding a flag that was not set initially, changing its divisibility, or extending its duration before
distribution.
Zero supply requirement
A mosaic definition can only be modified when its total supply is 0.
No units of the mosaic can exist anywhere on the network, otherwise the transaction fails with
Failure_Mosaic_Modification_Disallowed.
This tutorial shows how to modify an existing mosaic's flags.
To change the mosaic's supply instead of its definition, see Changing Mosaic Supply.
Consider creating a new mosaic instead
Creating a new mosaic is easier than modifying an existing one.
Understanding how modification works is still important to know when a mosaic's definition can no longer be edited.
The snippet reads the signer's private key from the SIGNER_PRIVATE_KEY environment variable, which defaults to a
test key if not set.
The signer's address is derived from the public key.
This account must be the original creator of the mosaic.
# Fetch current network timetime_path='/node/time'print(f'Fetching current network time from {time_path}')withurllib.request.urlopen(f'{NODE_URL}{time_path}')asresponse:response_json=json.loads(response.read().decode())receive_timestamp=(response_json['communicationTimestamps']['receiveTimestamp'])timestamp=NetworkTimestamp(int(receive_timestamp))print(f' Network time: {timestamp.timestamp} ms since nemesis')# Fetch recommended feesfee_path='/network/fees/transaction'print(f'Fetching recommended fees from {fee_path}')withurllib.request.urlopen(f'{NODE_URL}{fee_path}')asresponse:response_json=json.loads(response.read().decode())median_mult=response_json['medianFeeMultiplier']minimum_mult=response_json['minFeeMultiplier']fee_mult=max(median_mult,minimum_mult)print(f' Fee multiplier: {fee_mult}')
Modifying a mosaic definition requires knowing its current values (flags, divisibility, and duration),
because the network combines them with the values in the transaction rather than replacing them.
The mosaic can be retrieved using the /mosaics/{mosaicId}GET endpoint or looked up in the
Symbol Explorer.
In this tutorial, the current values are already known because the mosaic was just
created and retrieved in the previous tutorial.
// Build the modification transactionconstMOSAIC_NONCE=parseInt(process.env.MOSAIC_NONCE||'0',10);console.log('Mosaic nonce:',MOSAIC_NONCE);constmosaicId=generateMosaicId(signerAddress,MOSAIC_NONCE);console.log(`Mosaic ID: ${mosaicId} (0x${mosaicId.toString(16)})`);constmodifyTx=facade.transactionFactory.create({type:'mosaic_definition_transaction_v1',signerPublicKey:signerKeyPair.publicKey.toString(),deadline:timestamp.addHours(2).timestamp,duration:0n,divisibility:0,nonce:MOSAIC_NONCE,flags:'revokable'});modifyTx.fee=newmodels.Amount(feeMult*modifyTx.size);
The MOSAIC_NONCE environment variable specifies the nonce of the mosaic to modify.
The nonce must match the one used when creating the mosaic to target the same mosaic.
The modification transaction uses the same mosaic_definition_transaction_v1 type as the original creation.
The key difference is that the nonce targets an existing mosaic instead of creating a new one.
When processing the transaction, each property is combined with the mosaic's current value using the following rules:
Flags are XOR'd with the current flags.
Setting a flag that is already active removes it; setting a flag that is not active adds it.
For a description of each available flag, see
Building the Mosaic Definition Transaction.
Divisibility is XOR'd with the current divisibility.
The resulting value must be between 0 and 6.
Duration is added to the current remaining duration.
Duration can only be extended, not reduced, because the field is unsigned.
A value of 0 leaves the duration unchanged.
Eternal mosaics (duration 0) cannot have their duration modified.
The resulting duration cannot exceed 10,512,000 blocks (approximately 10 years).
In this example, the existing mosaic has flags transferable restrictable
(numeric value6).
The modification sets flags: 'revokable' (numeric value 8).
XOR produces 6 ⊕ 8 = 14, which corresponds to transferable restrictable revokable.
The following table illustrates how XOR affects individual flags:
Flag
Current
Modification
Result (XOR)
transferable
on
off
on
restrictable
on
off
on
revokable
off
on
on
Setting divisibility to 0 results in 2 ⊕ 0 = 2 (no change), and duration: 0 adds nothing to the current
duration.
Lease fee
Each mosaic definition transaction incurs the full lease fee paid in
XYM, whether creating or modifying a mosaic.
This is the same fee every time, in addition to the standard transaction fee.
The lease fee amount can be queried from the /network/fees/rentalGET endpoint
(effectiveMosaicRentalFee property).
// Retrieve the mosaicconstmosaicIdHex=mosaicId.toString(16);constmosaicPath=`/mosaics/${mosaicIdHex}`;console.log('Fetching mosaic information from',mosaicPath);constmosaicResponse=awaitfetch(`${NODE_URL}${mosaicPath}`);constmosaicJSON=awaitmosaicResponse.json();constmosaicInfo=mosaicJSON.mosaic;console.log('Mosaic information:');console.log(' Mosaic ID:',mosaicInfo.id);console.log(' Supply:',mosaicInfo.supply);console.log(' Divisibility:',mosaicInfo.divisibility);console.log(' Flags:',mosaicInfo.flags);console.log(' Duration:',mosaicInfo.duration);
To verify the modification was applied, the code retrieves the mosaic from the network using the
/mosaics/{mosaicId}GET endpoint and displays its updated properties.
A successful response confirms the mosaic now has the expected flags value.
Using node https://reference.symboltest.net:3001
Signer address: TCHBDENCLKEBILBPWP3JPB2XNY64OE7PYHHE32I
Fetching current network time from /node/time
Network time: 103748303591 ms since nemesis
Fetching recommended fees from /network/fees/transaction
Fee multiplier: 100
Mosaic nonce: 1770998662
Mosaic ID: 6619508144549180335 (0x5bdd3795f7a8b3af)
Built mosaic modification transaction:
{
"signature": "729A40BAD69DA8B3CE38D442CFCD1258CA41B7933CF80EFE24A7A354773E0B08D7E2796DED2D93A5F1C16A5EB3298A2113601348A436A4340BFFC38BD7EEBF07",
"signer_public_key": "3B6A27BCCEB6A42D62A3A8D02A6F0D73653215771DE243A63AC048A18B59DA29",
"version": 1,
"network": 152,
"type": 16717,
"fee": "15000",
"deadline": "103755503591",
"id": "6619508144549180335",
"duration": "0",
"nonce": 1770998662,
"flags": 8,
"divisibility": 0
}
Transaction hash: 110D3B362D76020EBCD96A5A2E7C621ADE53D98BFACEEE273DA224D8E8B07225
Announcing mosaic modification to /transactions
Response: {"message":"packet 9 was pushed to the network via /transactions"}
Waiting for mosaic modification confirmation...
Transaction status: unconfirmed
Transaction status: unconfirmed
Transaction status: confirmed
Mosaic modification confirmed in 11 seconds
Fetching mosaic information from /mosaics/5bdd3795f7a8b3af
Mosaic information:
Mosaic ID: 5BDD3795F7A8B3AF
Supply: 0
Divisibility: 2
Flags: 14
Duration: 0
Some highlights from the output:
Mosaic nonce (line 7): The nonce 1770998662 matches the nonce used when the mosaic was created, targeting
the same mosaic for modification.
Mosaic ID (line 8): The mosaic ID 0x5bdd3795f7a8b3af is derived from the nonce and signer address, confirming
the correct mosaic is being modified.
Transaction properties (lines 19, 21-22): The modification sets duration to 0 (no change),
flags to 8 (revokable), and divisibility to 0 (no change).
Updated properties (lines 36-38): The mosaic's divisibility remains 2 (unchanged by XOR with 0).
The flags are now 14, which corresponds to transferable (2) + restrictable (4) + revokable (8).
The duration remains 0 (eternal, unchanged).
The transaction hash printed in the output can be used to search for the transaction in the
Symbol Testnet Explorer.