Chromia
Start Building

09 / 15Module 2: Model NFTs in RellAdvanced

Make card attributes random

True randomness is hard to achieve on a blockchain. Every node must be able to replay each operation and reach the same outcome, so every transaction and function call has to return identical results everywhere. That determinism is the opposite of genuine unpredictability.

You can still approximate randomness by deriving values from transaction data; the code below uses the transaction RID. The result is not truly random, but it works for simple cases. This lesson is optional. To stay focused on the marketplace, skip it and give your cards fixed attributes.

Add random functions

To give the buy_mystery_card operation random strength and health values, start with a function that produces a pseudo-random number:

src/rell_marketplace/nft.rell
// Generate a random integer within a specified rangefunction random(high: integer, seed: integer): integer {    // Ensure high is not zero to avoid division by zero    if (high == 0) return 0;    // Calculate the random value using the provided seed    return (op_context.last_block_time - op_context.block_height - op_context.op_index + seed) % high;}

The transaction RID serves as the seed source. You take a substring of it for each random number you need, and those substrings become the seeds for health and strength.

src/rell_marketplace/nft.rell
function extract_seeds() {    // Extract seeds for randomness from the transaction RID    val seeds = op_context.transaction.tx_rid.to_hex();    val health_seed: integer = integer.from_hex(seeds.sub(0, 4));    val strength_seed: integer = integer.from_hex(seeds.sub(4, 8));    return (health_seed, strength_seed);}

Next, add one function per attribute. generate_health and generate_strength each take their extracted seed and return a random value for health or strength.

src/rell_marketplace/nft.rell
// Generate random health within a specified rangefunction generate_health(seed: integer): integer {    val rand = random(30, seed) + 1; // Generate a random value between 1 and 30    val baseline = 30; // Consistent baseline for all cards    return baseline + rand;}// Generate random strength within a specified rangefunction generate_strength(seed: integer): integer {    val rand = random(30, seed) + 1; // Generate a random value between 1 and 30    val baseline = 50; // Consistent baseline for all cards    return baseline + rand * 2; // Adjust range to 50-110}

Finally, mint_card uses these generated values to create a new NFT card with random strength and health.

src/rell_marketplace/nft.rell
// Mint a new card with random attributesfunction mint_card(account) {    // Create a new NFT for the specified account    val nft = create nft(account);    // Extract seeds for randomness    val (health_seed, strength_seed) = extract_seeds();    // Generate random health and strength based on the provided seeds    val health = generate_health(health_seed);    val strength = generate_strength(strength_seed);    // Create the NFT card with the generated attributes    create nft_card(        .nft = nft,        .strength = strength,        .health = health    );}
Written for this site from Chromia’s public course. Code samples are the course’s own.