Get a Random Number
#
OverviewPlatON built-in system contract (contract address: lat1xqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpe9fgva) provides the function of generating VRF random numbers. The contract supports returning up to 500 random numbers, and the return value is an array of []bytes, where each 32 bytes represents a random number.
#
Input parameters- input []byte: The number of random numbers to be obtained, which cannot exceed 500. The input parameter is expressed as a uint64 value, padded to 32 bytes. For example: 0x00000000000000000000000000000000000000000000000000000000000006 means get 6 random numbers
#
return value- ret[]byte: every 32 bytes represents a random number
#
Code Example#
Python SDK callsfrom client_sdk_python import Web3, WebsocketProvider
w3 = Web3(WebsocketProvider('ws://192.168.120.121:7789'))
txn = { "to": 'lat1xqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpe9fgva', "data": 0x000000000000000000000000000000000000000000000000000000000000001f4,}
crypt_hex = w3.platon.call(txn).hex()[2:]crypts = [crypt_hex[i: i + 64] for i in range(len(crypt_hex)) if i % 64 == 0]
print(len(crypts), crypts)
#
Solidity cross-contract calls// SPDX-License-Identifier: MITpragma solidity ^0.8.0;
contract VRF {
error InvalidRandomWords(uint32 numWords, uint256 returnValueLength);
// VrfInnerContract system contract address vrfInnerContractAddr = 0x3000000000000000000000000000000000000001;
// every 32 bytes represents a random number uint32 base = 32;
/** * Get Random Number * @param numWords */ function requestRandomWords(uint32 numWords) internal returns (uint256[] memory) { bytes memory data = abi.encode(numWords); bytes memory returnValue = assemblyCall(data, vrfInnerContractAddr);
if (numWords * base != returnValue.length) { revert InvalidRandomWords( numWords, returnValue.length ); }
uint256[] memory randomWords = new uint256[](numWords); for(uint i = 0; i < numWords; i++) { uint start = i * base; randomWords[i] = sliceUint(returnValue, start); }
return randomWords; }
/** * delegatecall * @param data contract input data * @param addr contract address */ function assemblyCall(bytes memory data, address addr) internal returns (bytes memory) { uint256 len = data.length; uint retsize; bytes memory resval; assembly { let result := delegatecall(gas(), addr, add(data, 0x20), len, 0, 0) retsize := returndatasize() } resval = new bytes(retsize); assembly { returndatacopy(add(resval, 0x20), 0, returndatasize()) } return resval; }
function sliceUint(bytes memory bs, uint start) internal pure returns (uint256) { require(bs.length >= start + 32, "slicing out of range"); uint256 x; assembly { x := mload(add(bs, add(0x20, start))) } return x; }}