The Randomness Pallet¶
Introduction¶
Moonbeam utilizes verifiable random functions (VRF) to generate randomness that can be verified on-chain. A VRF is a cryptographic function that takes some input and produces random values, along with a proof of authenticity that these random values were generated by the submitter. The proof can be verified by anyone to ensure the random values generated were calculated correctly. For more information on Moonbeam's on-chain randomness, such as an overview on the randomness sources, the request and fulfill cycle, and more, please refer to the Randomness on Moonbeam overview page.
The randomness pallet enables you to check on randomness requests that have not been fulfilled or purged, randomness results, and more. To actually request and fulfill randomness, you can use the randomness precompile and randomness consumer contracts. The precompile is a Solidity interface that enables you to request randomness, check on the status of requests, fulfill requests, and more through the Ethereum API. For more information on how to use both of these contracts, please refer to the Randomness Precompile guide.
This page will provide an overview of the storage methods and getters for the pallet constants available in the randomness pallet.
Randomness Pallet Interface¶
Storage Methods¶
The randomness pallet includes the following read-only storage methods to obtain chain state data:
localVrfOutput() - returns the current local per-block VRF randomness
None
H256
- A 32-byte (256-bit) hex value, starting with "0x"`
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the local VRF output from randomness pallet
const localVrf = await api.query.randomness.localVrfOutput();
console.log('Local VRF Output:', localVrf.toString());
process.exit(0);
} catch (error) {
console.error('Error querying local VRF output:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
palletVersion() - returns the current pallet version
None
u16
- The pallet version
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the pallet version from randomness pallet
const version = await api.query.randomness.palletVersion();
console.log('Randomness Pallet Version:', version.toString());
process.exit(0);
} catch (error) {
console.error('Error querying randomness pallet version:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
randomnessResults(PalletRandomnessRequestType) - snapshot of randomness to fulfill all requests that are for the same raw randomness
PalletRandomnessRequestType
- You can optionally provide the type of randomness you'd like, e.g.Local
orBabeEpoch
Randomness. If you omit this, you'll receive all types of randomness.
The query returns mappings of request types to their randomness outcomes, where:
-
Key: Identifies the source and timing of the randomness request. e.g.
{ Local: '4,619,640' }
indicates this was a Local randomness request from block number 4,619,640. The Local type uses block numbers as identifiers, while BabeEpoch uses epoch numbers. -
Value: Contains two pieces of information, including
randomness
: A 32-byte hex string (0x15b5f6...c816) representing the random value generated andrequestCount
: The number of requests that used this same random value (e.g. '1')
Multiple requests for randomness at the same block/epoch would share the same random value, which is why there's a requestCount field.
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Query Babe Epoch randomness results
const babeResults = await api.query.randomness.randomnessResults({
BabeEpoch: 0,
});
console.log('\nBabe Epoch Randomness Results:');
console.log(babeResults.toHuman());
// Query Local randomness results
const localResults = await api.query.randomness.randomnessResults({
Local: 0,
});
console.log('\nLocal Randomness Results:');
console.log(localResults.toHuman());
// Get the available keys/entries
console.log('\nAll Available Randomness Results:');
const entries = await api.query.randomness.randomnessResults.entries();
entries.forEach(([key, value]) => {
console.log(
'Key:',
key.args.map((k) => k.toHuman())
);
console.log('Value:', value.toHuman());
console.log('---');
});
process.exit(0);
} catch (error) {
console.error('Error querying randomness results:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
relayEpoch() - returns the relay epoch
None
u64
- the relay epoch
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the relay epoch
const relayEpoch = await api.query.randomness.relayEpoch();
console.log('Current Relay Epoch:', relayEpoch.toString());
process.exit(0);
} catch (error) {
console.error('Error querying relay epoch:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
requestCount() - returns the number of randomness requests made so far, and is used to generate the next request's uid
None
u64
- the request count
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the request count
const requestCount = await api.query.randomness.requestCount();
console.log('Total Randomness Requests:', requestCount.toString());
console.log(
'Next Request UID will be:',
(Number(requestCount) + 1).toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying request count:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
requests(u64) - returns a given randomness request or all of the randomness requests that have not been fulfilled nor purged yet
u64
- The request ID number (optional)
Returns an Option containing the request information if it exists and hasn't been fulfilled/purged, including:
- The request type (Local or Babe)
- When it can be fulfilled
- Number of random words requested
- The requester's information
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// First get the current request count
const requestCount = await api.query.randomness.requestCount();
console.log('Total Request Count:', requestCount.toString());
// Query most recent request as an example
if (requestCount > 0) {
const latestRequestId = requestCount - 1;
const specificRequest =
await api.query.randomness.requests(latestRequestId);
console.log('\nLatest Request (ID:', latestRequestId.toString(), '):');
if (specificRequest.isSome) {
console.log(specificRequest.unwrap().toHuman());
} else {
console.log('Request has been fulfilled or purged');
}
}
// Query all available requests
console.log('\nAll Pending Requests:');
const allRequests = await api.query.randomness.requests.entries();
if (allRequests.length === 0) {
console.log('No pending requests found');
} else {
allRequests.forEach(([key, value]) => {
const requestId = key.args[0].toString();
console.log('\nRequest ID:', requestId);
if (value.isSome) {
const request = value.unwrap();
console.log('Request Details:', request.toHuman());
}
});
// Show some statistics
console.log('\nRequest Statistics:');
console.log('Total Pending Requests:', allRequests.length);
}
process.exit(0);
} catch (error) {
console.error('Error querying randomness requests:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
Pallet Constants¶
The randomness pallet includes the following read-only functions to obtain pallet constants:
blockExpirationDelay() - the number of blocks that must pass before a local VRF request expires and can be purged
None
u32
- the number of blocks that must pass before a local VRF request expires and can be purged
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the block expiration delay constant
const blockExpirationDelay =
await api.consts.randomness.blockExpirationDelay;
console.log(
'Block Expiration Delay:',
blockExpirationDelay.toString(),
'blocks'
);
process.exit(0);
} catch (error) {
console.error('Error querying block expiration delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
deposit() - the amount that should be taken as a security deposit when requesting random words. There is one deposit per request
None
u128
- the amount that should be taken as a security deposit when requesting random words
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the deposit constant
const deposit = await api.consts.randomness.deposit;
console.log('Randomness Request Deposit:', deposit.toString(), 'Wei');
console.log(
'Deposit in DEV:',
(BigInt(deposit) / BigInt(10 ** 18)).toString()
);
process.exit(0);
} catch (error) {
console.error('Error querying randomness deposit:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
epochExpirationDelay() - the number of epochs that must pass before a BABE request expires and can be purged
None
u64
- the number of epochs that must pass before a BABE request expires and can be purged
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the epoch expiration delay constant
const epochExpirationDelay =
await api.consts.randomness.epochExpirationDelay;
console.log(
'Epoch Expiration Delay:',
epochExpirationDelay.toString(),
'epochs'
);
process.exit(0);
} catch (error) {
console.error('Error querying epoch expiration delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
maxBlockDelay() - the maximum number of blocks (after the block in which the request was made) that can pass before a local VRF request is fulfilled
None
u32
- the maximum number of blocks that can pass before a local VRF request is fulfilled
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maximum block delay constant
const maxBlockDelay = await api.consts.randomness.maxBlockDelay;
console.log('Maximum Block Delay:', maxBlockDelay.toString(), 'blocks');
process.exit(0);
} catch (error) {
console.error('Error querying max block delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
maxRandomWords() - the maximum number of random words that can be requested
None
u8
- the maximum number of random words that can be requested
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the maximum random words constant
const maxRandomWords = await api.consts.randomness.maxRandomWords;
console.log('Maximum Random Words:', maxRandomWords.toString(), 'words');
process.exit(0);
} catch (error) {
console.error('Error querying max random words:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
minBlockDelay() - the minimum number of blocks (after the block in which the request was made) that must pass before a local VRF request can be fulfilled
None
u32
- the minimum number of blocks (after the block in which the request was made) that must pass before a local VRF request can be fulfilled
import { ApiPromise, WsProvider } from '@polkadot/api';
const main = async () => {
// Initialize the API
const api = await ApiPromise.create({
provider: new WsProvider('wss://moonbase-alpha.public.blastapi.io'),
});
try {
// Get the minimum block delay constant
const minBlockDelay = await api.consts.randomness.minBlockDelay;
console.log('Minimum Block Delay:', minBlockDelay.toString(), 'blocks');
process.exit(0);
} catch (error) {
console.error('Error querying min block delay:', error);
process.exit(1);
}
};
// Execute the script
main().catch((error) => {
console.error('Script error:', error);
process.exit(1);
});
| Created: August 12, 2022