Documentation Randomizer Quick Start

Funding your contract

  1. Open the Dashboard, connect with Metamask to the desired network and wallet.
  2. Under Fund Contract, paste your contract address.
  3. Enter an amount of ETH you'd like to fund the contract with and click Deposit.

Make sure your contract remains funded so it can make request calls. You can also have contract end-users pay for the fee by implementing getFeeEstimate. To withdraw funds from Randomizer, implement the clientWithdrawTo function.

Making a request

NOTE: zkSync v2 Testnet version is coming back soon.

To make a request, make sure your contract is funded with ETH and then implement the function randomizer.request(uint256 callbackGasLimit) in an external function within your smart contract. This function will return a unique uint128 ID that your contract can store and retrieve once it receives the callback.

The Randomizer protocol will then call your randomizerCallback(uint128 id, bytes32 value) function with the request id and random value.

Contract addresses

Implement any address below to make calls to Randomizer.

  • Arbitrum Nitro Devnet (Goerli): 0xE1B6CcAc0BB0355C01A049e78909231Bfa13620B
  • Binance Smart Chain Testnet: 0xb65F5A47e2A49351fb2a1d8fad3DDA6E0c79Ea37

Contract Example

// Randomizer protocol interface
interface IRandomizer {
    function request(uint256 callbackGasLimit) external returns (uint256);
    function clientWithdrawTo(address _to, uint256 _amount) external;
}

// Coinflip contract
contract CoinFlip {
	IRandomizer public randomizer = 0x0000000000000000000000000000000000000000;
	address public owner = 0x0000000000000000000000000000000000000000;

	// Stores each game to the player
    mapping(uint128 => address) public flipToAddress;

    // Events
    event Win(address winner);
    event Lose(address loser);

	modifier onlyOwner() {
		require(msg.sender == owner, "Sender is not owner");
	}

    // The coin flip containing the random request
    function flip() external returns (uint128) {
        // Get the latest randomizer contract from the testnet proxy
        // Request a random number from the randomizer contract (50k callback limit)
        uint128 id = randomizer.request(50000);
        // Store the flip ID and the player address
        flipToAddress[id] = msg.sender;
        // Return the flip ID
        return id;
    }

    // Callback function called by the randomizer contract when the random value is generated
    function randomizerCallback(uint128 _id, bytes32 _value) external {
		//Callback can only be called by randomizer
		require(msg.sender == randomizer, "Caller not Randomizer");
        // Get the player address from the flip ID
        address player = flipToAddress[_id];
        // Convert the random bytes to a number between 0 and 99
        uint256 random = uint256(_value) % 99;
        // If the random number is less than 50, the player wins
        if (random < 50) {
            emit Win(player);
        } else {
            emit Lose(player);
        }
    }

    // Allows the owner to withdraw their deposited randomizer funds
    function randomizerWithdraw(uint256 amount)
        external
        onlyOwner
    {
        randomizer.clientWithdrawTo(msg.sender, amount);
    }
}

Withdrawing Funds

To withdraw funds, implement the function randomizer.clientWithdrawTo(address to, uint256 amount) into your smart contract. Make sure it's only callable by pre-approved accounts.

You can also call randomizer.getFeeEstimate(uint256 callbackGasLimit, boolean optimistic) to get the fee estimate before making a request. You can use this to get the contract user to pay for the gas fee before making the request, by making your request-making function "payable" and adding require(msg.value >= feeEstimate).

Real-time Results

You can implement Randomizer's Sequencer service to give users a real-time experience. For example, you can display the results of a coinflip directly after a "flip" transaction, and update the user balance immediately in the front-end, all before the result is on-chain and your contract's callback function is called.

Try out this real-time Coinflip game here. The front-end source code + smart contract is available here.

How it works: Beacons send their VRF data to the sequencer before their transactions are verified on-chain. This lets the sequencer process the data off-chain and send the expected result to your front-end using websockets.

Expected Result Ensurance: In the case where a beacon sent VRF data to the sequencer but hasn't submitted the data on-chain (e.g. due to inability to pay for gas fees), the sequencer can submit the beacon's VRF data on their behalf after 5 minutes + 10 blocks. This helps to ensure that the expected real-time result matches the eventual on-chain result. This time window is enforced in the smart contract, so the Sequencer can never front-run any beacons.

Roadmap

  1. Launch alpha versions on zkSync v2 Testnet, Ethereum L1, Arbitrum, and Optimism.
  2. Onboard community-operated beacons.
  3. Complete code audits.
  4. Open-source the platform under a time-delayed GPL-2.0-or-later license.
  5. Launch platform across mainnets.
  6. Distribute Governance NFT.

Beacons

Randomizer beacons on testnet are operated by the developer. Beacons are operated by independent projects on the mainnet contracts.

Governance

The protocol will be governed by holders of an original NFT collection, TBA.