**Week 13 Learning Experience at Blockfuse Labs: Exploring Chainlink VRF, Automation, and Functions** Week 13 at Blockfuse Labs was an intense deep dive into Chainlink's powerful oracle services, specifically focusing on Verifiable Random Function (VRF), Automation (formerly Keepers), and Chainlink Functions. This week challenged me to build practical implementations of these technologies, pushing me to research extensively and solve several complex problems along the way. **Project 1: Building a Mini Lottery DApp with Chainlink VRF and Automation** The first major task was to create a decentralized lottery application that leverages Chainlink VRF for provably fair random number generation and Chainlink Automation to trigger periodic draws. **Initial Implementation on Ethereum** I started by building the lottery contract on Ethereum testnet using the standard Chainlink VRF v2 implementation: ``` // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import "@chainlink/contracts/src/v0.8/interfaces/KeeperCompatibleInterface.sol"; contract Lottery is VRFConsumerBaseV2, KeeperCompatibleInterface { VRFCoordinatorV2Interface public COORDINATOR; // Chainlink VRF variables uint64 public s_subscriptionId; bytes32 public s_keyHash; uint32 public callbackGasLimit = 100000; uint16 public requestConfirmations = 3; uint32 public numWords = 1; // Lottery variables address[] public participants; address public recentWinner; uint256 public lastDrawTimestamp; uint256 public drawInterval; // VRF request tracking uint256 public requestId; constructor( uint64 subscriptionId, address vrfCoordinator, bytes32 keyHash, uint256 interval ) VRFConsumerBaseV2(vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); s_subscriptionId = subscriptionId; s_keyHash = keyHash; drawInterval = interval; lastDrawTimestamp = block.timestamp; } function enterLottery() public payable { require(msg.value == 0.01 ether, "Must send exactly 0.01 ETH"); participants.push(msg.sender); } function checkUpkeep(bytes calldata /* checkData */) external view override returns (bool upkeepNeeded, bytes memory /* performData */) { bool hasParticipants = participants.length > 0; bool timePassed = (block.timestamp - lastDrawTimestamp) > drawInterval; upkeepNeeded = hasParticipants && timePassed; } function performUpkeep(bytes calldata /* performData */) external override { (bool upkeepNeeded, ) = this.checkUpkeep(""); require(upkeepNeeded, "Upkeep not needed"); requestId = COORDINATOR.requestRandomWords( s_keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords ); } function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override { uint256 index = randomWords[0] % participants.length; recentWinner = participants[index]; // Reset lottery for next round participants = new address[](0); lastDrawTimestamp = block.timestamp; // Send prize to winner (bool success, ) = recentWinner.call{value: address(this).balance}(""); require(success, "Transfer failed"); } } ``` **Challenges and Research** 1. Understanding VRF v2 Architecture: I spent considerable time studying how VRF v2 differs from v1, particularly the subscription model that separates payment from usage. 2. Automation Timing: Figuring out the optimal drawInterval and gas parameters required testing different values on testnet. **Porting to Flare Blockchain** The real challenge came when I decided to re-implement this on Flare blockchain. While the core logic remained similar, several adjustments were needed: ``` // Flare-specific adjustments constructor( uint64 subscriptionId, address vrfCoordinator, bytes32 keyHash, uint256 interval ) VRFConsumerBaseV2(vrfCoordinator) { // Flare uses different coordinator addresses COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); s_subscriptionId = subscriptionId; s_keyHash = keyHash; // Different keyHash for Flare drawInterval = interval; lastDrawTimestamp = block.timestamp; } ``` Here is the link to my implementation https://github.com/jerrymusaga/lottery **Project 2: Interacting with External APIs using Chainlink Functions** The second major task was using Chainlink Functions to fetch external API data onto the blockchain. This required understanding a completely different aspect of Chainlink's oracle services. https://github.com/chain-builders/api-consumer **Challenges and Solutions** 1. API Response Handling: Understanding how to properly structure the JavaScript code that runs in the Chainlink Function environment required multiple iterations. 2. Data Encoding: Figuring out how to properly encode different data types for blockchain consumption was non-trivial. **Conclusion** Week 13 at Blockfuse Labs was one of the most technically challenging yet rewarding weeks so far. The amount of research required to properly implement these Chainlink services was substantial, but the hands-on experience gave me confidence in working with oracle solutions. The process of porting the lottery DApp to Flare blockchain particularly deepened my understanding of cross-chain development considerations. These projects have equipped me with practical skills that I can apply to build more sophisticated, real-world blockchain applications that require reliable external data and automation.