How Cozy Reef Used Multiple Chainlink Services to Power Its Advanced Gaming dApp

Chainlink services enable decentralized gaming ecosystems to dodge some of the common pitfalls faced by blockchain games and create a deeper, more rewarding experience for players. For their Chainlink Hackathon 2021 project, Cozy Reef Labs integrated multiple Chainlink services into their first game, Slingshot Sailers, using Chainlink Automation for decentralized game state management, Chainlink VRF for provable randomness, and Chainlink External Adapters to leverage different blockchains for the settlement and gaming layers. In this technical walkthrough, go behind the scenes of Cozy Reef’s build and learn how their team leveraged these various Chainlink services to compose an advanced gaming dApp. 

By Cozy Reef Labs

Welcome to Cozy Reef

Welcome to Cozy Reef

Cozy Reef Labs was founded to create deep, community-based gaming experiences that take advantage of the unique capabilities of blockchain technologies. 

Each member of the team has extensive experience working in the video game industry and wanted to put a fun, meaningful player experience first. In order to do this well, the team set an ambitious goal: Instead of building a single game, we would build an ecosystem of games that players can come back to over time. These games would be easy to learn but difficult to master, fit into a larger world that players would want to explore and experience, and be competitive and rewarding of a player’s time. 

We realized that Chainlink technology could help us accomplish these goals and much more. We would be able to build fully on-chain games that provide players with an unprecedented level of transparency while fostering a competitive playing environment with a play-to-earn ethos. By combining public blockchains with the ecosystem of Chainlink services, we are able to build a decentralized platform that keeps the focus squarely on the game experience. 

Cozy Reef will launch as a series of elimination games where the survivors are invited to participate in the future direction of the platform as a Cozy Reef Killer. Each game will later be available to replay in a broader ecosystem, where players can play, compete, and earn rewards. 

Chainlink Automation Drives the Core Game Loop

Slingshot Sailors

Slingshot Sailors is the first elimination game of season one of Cozy Reef. Players must pick one of five slingshots with different attributes to launch themselves away from the pursuing Cozy Reef Killers. The more players in a sling, the higher its distance bonus and chance to fire. But it isn’t all sunshine and big multipliers—the number of players in a sling also increases its chance of misfiring, resulting in a distance penalty. In order to successfully evade the Cozy Reef Killers for the entire game, players have to balance risk and reward and react to other players’ decisions throughout each round. The core game loop cycles through the following phases:

  • MOVEMENT—Players are able to choose which sling to jump on. The number of players on a sling alters the chance of the sling firing or backfiring, and affects the distance multiplier.
  • LOCKOUT—Players are no longer able to select slings. This period is to allow the chain to reach finality on block confirmation to prevent frontrunning of the VRF call and block re-orgs.
  • VRF_REQUESTED—A request is made to Chainlink VRF for a random number, which determines the resulting outcomes for each sling.
  • VRF_RECEIVED—The random number has successfully been processed and the round end is computed. We created this additional state because the round computation exceeds the maximum gas allowed in a VRF call (200,000 gas). Note: Developers can configure maximum gas when registering their dApp to Automation.

Slingshot Sailors screenshot 2

A smart contract alone is not sufficient to act as a game runner in a time-based environment, as it requires an external call to facilitate phase transition. Chainlink Automation allows us to check and trigger phase transitions in a decentralized manner. We do this by hooking up the `checkUpKeep` function to check if we need to move the game to the next phase, which is primarily driven by `block.timestamp`:

function checkUpkeep(bytes calldata) external view override returns (bool, bytes memory) {
    bytes memory empty;
    return (canTick(), empty);
  }

function canTick() public view returns (bool) {
    return
      state.game.phase != Phase.NONE &&
      state.game.phase != Phase.END &&
      block.timestamp >= state.game.phaseScheduledEnd;
  }

When the `checkUpKeep` function returns true, Automation then calls `performUpKeep` to transition the game to the next phase:

function performUpkeep(bytes calldata) external override {
    tickState(false);
  }

function tickState(bool force) public {
    if (!(force || canTick())) return;

    if (state.game.phase == Phase.LOCKOUT) {
      require(LINK.balanceOf(address(this)) >= vrfState.fee, "Not enough LINK");
      requestRandomness(vrfState.keyHash, vrfState.fee);
    }

    if (state.game.phase == Phase.VRF_RECEIVED) {
      sweepLanes(state.game.random);
      state.game.sweep++;
      state.game.lastRandom = state.game.random;
    }

    Phase previous = state.game.phase;
    state.gotoNextState();
    emit StateUpdated(previous, state.game.phase);
    return;
  }

In the `tickState` function, different actions occur based on the game phase. For example, if the phase is currently in the LOCKOUT phase, a VRF request is emitted and the state will change to VRF_REQUESTED. A `StateUpdated` event is emitted by the contract and players’ browsers respond by calling view functions against the updated contract state. In order to be gas- and cost-efficient, the game contract only stores the raw game events (slingshots fired, player move history, etc.). The browser that runs the game then fetches these events from the game contract and lazily computes the game state that the player sees on their screen (this process is more comprehensively described in the whitepaper.) The full game contract for Slingshot Sailors will be open-sourced shortly after the first instance of the game is launched. We encourage the community to reference this contract for their own game projects!

Chainlink VRF Enables Dynamic Player Interactions

Cozy Reef Chainlink Keepers and VRF diagram

Players must make decisions around risk management and pick slingshots that they believe have the best reward (firing chance, distance multiplier) versus risk (backfire chance, distance penalty). Making decisions based on probability and how other players behave is core to the excitement of Slingshot Sailors. Chainlink VRF allows us to generate provably random numbers in a decentralized manner to drive unique outcomes each round. With a single VRF call, we’re able to determine whether each of the five slingshots fires, backfires, or does nothing. 

As mentioned in the previous section, when the game phase transitions from `LOCKOUT` to `VRF_REQUEST`, the `requestRandomness` function is called, passing in the keyHash value and fee. VRF will generate and pass back a random number through the `fulfillRandomness` callback, as seen below:

function fulfillRandomness(bytes32, uint256 randomness) internal override {
    state.game.random = randomness;
    state.gotoNextPhase();
  }

function gotoNextPhase(State storage self) public {
    …
    } else if (self.game.phase == Phase.VRF_REQUESTED) {
      self.game.phase = Phase.VRF_RECEIVED;
      self.game.phaseScheduledEnd = uint48(block.timestamp);
    }
    …
    self.game.phaseStart = uint48(block.timestamp);
  }

function tickState(bool force) public {
    …
    if (state.game.phase == Phase.VRF_RECEIVED) {
      sweepLanes(state.game.random);
      state.game.sweep++;
      state.game.lastRandom = state.game.random;
    }

    Phase previous = state.game.phase;
    state.gotoNextState();
    emit StateUpdated(previous, state.game.phase);
    return;
  }

The callback function sets the random number and triggers the next phase change, which a Chainlink Automation node updates, ultimately calling the `tickState` function and resolving the round through `sweepLanes.` 

Chainlink External Adapters Enable a Multi-Chain Ecosystem

Cozy Reef Chainlink External Adapters diagram

We are developing Cozy Reef with accessibility as one of our core principles: Players should not have to pay exorbitant prices to play our on-chain games. Through some initial cost analysis (refer to our whitepaper), we estimated that playing SlingShot Sailors on a sidechain such as Polygon is up to 7500 times cheaper than on Ethereum mainnet. However, we recognize that Ethereum mainnet is still the ideal blockchain for settlements.

Our solution is to mint the genesis NFTs on Ethereum mainnet and run the games on Polygon. In order to validate ownership and admit a player to a game, we built a proof of reserve service leveraging the View-Function External Adapter. Players who own a Cozy Reef NFT on Ethereum mainnet call a validator on Polygon, which verifies token ownership and admits the player to the game instance. Taking this approach enables multi-chain capabilities while putting player experience first:

  • All contract calls are made on the side chain, which is significantly cheaper than if the player had to bridge through contract calls on Ethereum mainnet.
  • Ephemeral game instances and validation for each game instance removes the major challenges with de-synced ownership across chains.
  • Using a proof of reserve model as opposed to an NFT bridge removes the security risks of having the NFTs managed by a custodial account.
  • The cost of sidechain tokens is low enough that Cozy Reef Labs can sustainably use revenue to airdrop tokens to players to offset costs and abstract token bridging complexities.

A prototype of the NFT proof of reserve along with a technical breakdown is available on GitHub. Future development will include further decentralizing this component by powering the protocol with a Chainlink DON. 

Future Development

Our first major milestone for Cozy Reef is to deliver season one of the on-chain elimination games and invite the survivors to join the Cozy Reef Killers. As Cozy Reef grows into a broader gaming platform we will need to build out additional infrastructure. We are excited to continue to capitalize on the capabilities of Chainlink Automation to fully decentralize the entire ecosystem. 

Game Scheduling—Slingshot Sailors will be run on a per-instance basis with a set start and end time for each game cycle. We intend to rerun this and future games on a recurring basis for players to continue to compete and earn rewards. Chainlink Automation is a great candidate to decentralize game scheduling in a predictable and reliable way.

Post-Game Processing—Players will earn tokens based on how well they performed in each game. Chainlink Automation is a great candidate to scalably decentralize and manage post-game processing such as rewards allocation.

Scholarship and Staking Management—We’d like to create opportunities for Cozy Reef owners to stake their tokens and participate in on-chain supported scholarship programs. Chainlink Automation unlocks our ability to build comprehensive systems to manage these programs and distribute rewards. 

Cozy Reef artwork

With season one of Cozy Reef launching soon, the team hopes to expand on what’s possible in the blockchain gaming space. Chainlink technology has enabled us to bring the experience fully on-chain in a way that’s transparent, engaging, and accessible to the wider gaming community. 

Learn More

If you’re a developer and want to connect your smart contract to existing data and infrastructure outside the underlying blockchain, reach out here or visit the developer documentation.

Need Integration Support?
Talk to an expert
Faucets
Get testnet tokens
Read the Docs
Technical documentation