diff --git a/docs/build/isc/v1.0.0-rc.6/docs/how-tos/get-randomness-on-l2.md b/docs/build/isc/v1.0.0-rc.6/docs/how-tos/get-randomness-on-l2.md new file mode 100644 index 00000000000..c41f75a9315 --- /dev/null +++ b/docs/build/isc/v1.0.0-rc.6/docs/how-tos/get-randomness-on-l2.md @@ -0,0 +1,126 @@ +--- +description: The ISC Magic Contract allows EVM contracts to access ISC functionality. +image: /img/logo/WASP_logo_dark.png +tags: + - configure + - using + - EVM + - magic + - Ethereum + - Solidity + - metamask + - JSON + - RPC +--- + +# Get Randomness on L2 + +In the ISC protocol, each validator proposes a batch of smart contract requests they would like to process next. They commit to their proposals with a signature, after which a common subset of requests is found and a combined signature is produced. This combined signature is unpredictable, and not only serves as protection against MEV by pseudo-randomly ordering requests, but also provides a source of verifiable entropy for randomness on L2. + +This guide will show ways you can use this entropy to generate random values in your contracts. + +:::info A note obout entropy + +While entropy is random for each smart contract request, entropy is constant within a request. This means multiple calls to get entropy within the same request will return the same value. + +::: + +## Example + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "@iota/iscmagic/ISC.sol"; + +contract Random { + event Int(uint256); + event Bytes(bytes); + + uint256 private _nonce; + + function getNonce() internal returns (bytes32) { + return bytes32(_nonce++); + } + + function getInt() public returns (uint256) { + bytes32 entropy = ISC.sandbox.getEntropy(); + bytes32 nonce = getNonce(); + bytes32 digest = keccak256(bytes.concat(entropy, nonce)); + + uint256 value = uint256(digest); + + emit Int(value); + return value; + } + + function getBytes(uint length) public returns (bytes memory) { + bytes32 entropy = ISC.sandbox.getEntropy(); + bytes32 nonce = getNonce(); + bytes32 digest = keccak256(bytes.concat(entropy, nonce)); + + bytes memory value = new bytes(length); + for (uint i = 0; i < length; i += 32) { + digest = keccak256(bytes.concat(digest)); + for (uint j = 0; j < 32 && i + j < length; j++) { + value[i + j] = digest[j]; + } + } + + emit Bytes(value); + return value; + } +} + +``` + +## Explanation + +When you want to generate multiple random values within a single request, you need to take into account that entropy is constant within a request. In this contract we use an increasing nonce in addition to the entropy, to make sure we are generating unique values: + +```solidity +uint256 private _nonce; + +function getNonce() internal returns (bytes32) { + return bytes32(_nonce++); +} +``` + +### Generating integers + +To then generate a random integer, you can take the entropy and a unique nonce and hash them together: + +```solidity +bytes32 entropy = ISC.sandbox.getEntropy(); +bytes32 nonce = getNonce(); +bytes32 digest = keccak256(bytes.concat(entropy, nonce)); +``` + +And then cast the digest to an integer: + +```solidity +uint256 value = uint256(digest); +``` + +### Generating integers + +Similarly to generating a random integer, you can generate any sequence of random bytes by taking the entropy and a unique nonce and hash them together: + +```solidity +bytes32 entropy = ISC.sandbox.getEntropy(); +bytes32 nonce = getNonce(); +bytes32 digest = keccak256(bytes.concat(entropy, nonce)); +``` + +And then repeatidly hash the digest and copy it in a sequence of bytes until you reach the required length. + +```solidity +bytes memory value = new bytes(length); +for (uint i = 0; i < length; i += 32) { + digest = keccak256(bytes.concat(digest)); + for (uint j = 0; j < 32 && i + j < length; j++) { + value[i + j] = digest[j]; + } +} +``` diff --git a/docs/build/isc/v1.0.0-rc.6/sidebars.js b/docs/build/isc/v1.0.0-rc.6/sidebars.js index 44bbc29a6ea..45871a1ba3c 100644 --- a/docs/build/isc/v1.0.0-rc.6/sidebars.js +++ b/docs/build/isc/v1.0.0-rc.6/sidebars.js @@ -213,6 +213,11 @@ module.exports = { }, ], }, + { + type: 'doc', + label: 'Get Randomness on L2', + id: 'how-tos/get-randomness-on-l2', + }, ], }, ],