<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matej Plavevski</title>
    <description>The latest articles on DEV Community by Matej Plavevski (@matejmecka).</description>
    <link>https://dev.to/matejmecka</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F117721%2Faed252a1-e4e6-4448-b46d-1d5d128bc68b.png</url>
      <title>DEV Community: Matej Plavevski</title>
      <link>https://dev.to/matejmecka</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matejmecka"/>
    <language>en</language>
    <item>
      <title>Euro Guesser: A Stellar Oracle Tutorial Using Reflector</title>
      <dc:creator>Matej Plavevski</dc:creator>
      <pubDate>Fri, 22 Aug 2025 15:56:02 +0000</pubDate>
      <link>https://dev.to/matejmecka/euro-guesser-a-stellar-oracle-tutorial-using-reflector-3fad</link>
      <guid>https://dev.to/matejmecka/euro-guesser-a-stellar-oracle-tutorial-using-reflector-3fad</guid>
      <description>&lt;h3&gt;
  
  
  Our Main Tool: The Reflector Oracle
&lt;/h3&gt;

&lt;p&gt;&lt;a href="//reflector.network"&gt;Reflector&lt;/a&gt; is the go-to Stellar oracle. It provides reliable, tamper-proof oracle price feeds to smart contracts written in Soroban, Stellar's Rust-based smart contract language, by aggregating information from multiple on- and off-chain data sources. Reflector is used by leading Stellar ecosystem projects including &lt;a href="//blend.capital"&gt;Blend&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reflector currently supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time cryptocurrency prices across multiple blockchains&lt;/li&gt;
&lt;li&gt;Price feeds for assets traded on Stellar Mainnet&lt;/li&gt;
&lt;li&gt;Exchange rates for fiat currencies&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What We're Building Today
&lt;/h3&gt;

&lt;p&gt;We're going to build something fun - a Stellar smart contract that lets users bet on whether the Euro (EUR) will go up or down over a 5-minute window. It's like a mini prediction market! The contract will tap into Reflector to get real-time EUR price data, making it actually useful instead of just guessing randomly.&lt;/p&gt;

&lt;p&gt;By the time you're done, you'll have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built and deployed your very own Stellar smart contract on testnet&lt;/li&gt;
&lt;li&gt;Connected to Reflector as your data oracle (fancy!)&lt;/li&gt;
&lt;li&gt;Created functions that let users make predictions and check if they were right&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The contract will have two main functions that do all the heavy lifting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;make_guess&lt;/code&gt;: Users put down some XLM and make their prediction, while the contract grabs current price data from Reflector&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;verify_guess&lt;/code&gt;: Checks if predictions were correct by comparing prices at two different times, and rewards the winners with double their bet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a perfect example of how oracles can supercharge your smart contracts with real-world information, opening doors to DeFi apps, prediction markets, and dynamic NFTs that actually respond to what's happening in the world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stellar CLI&lt;/strong&gt; (&lt;a href="https://developers.stellar.org/docs/build/smart-contracts/getting-started/setup" rel="noopener noreferrer"&gt;Setup Instructions&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Funded Stellar account on Testnet&lt;/li&gt;
&lt;li&gt;A warm cup of hot chocolate (totally optional but highly recommended ☕)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Important Disclaimer&lt;/strong&gt;: The following tutorial has not been audited by a pentester. You have the authors permission to audit it. Please use any of the published code with caution, and nobody is responsible for any loss of funds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Initialize a New Contract
&lt;/h3&gt;

&lt;p&gt;First things first - let's create our project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;stellar contract init euro_guesser
&lt;span class="nb"&gt;cd &lt;/span&gt;euro_guesser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll be doing all our coding magic in the &lt;code&gt;lib.rs&lt;/code&gt; file. Feel free to delete all those default comments and focus on the &lt;code&gt;impl Contract&lt;/code&gt; code block - that's where the fun happens!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Download the Necessary Contract Interface
&lt;/h3&gt;

&lt;p&gt;Time to head over to the Reflector documentation and find the "&lt;a href="https://reflector.network/docs/interface" rel="noopener noreferrer"&gt;Use Public Feed&lt;/a&gt;" section. Make sure you select &lt;strong&gt;Testnet&lt;/strong&gt; as your network and &lt;strong&gt;Foreign Exchange Rates&lt;/strong&gt; as your data source - we want those sweet EUR prices!&lt;/p&gt;

&lt;p&gt;Scroll down and copy the interface code from Reflector and save it as reflector.rs. This file will simplify interactions with the oracle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Connect to Reflector
&lt;/h3&gt;

&lt;p&gt;At the top of your lib.rs file, import the Reflector interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;reflector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;reflector&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;ReflectorClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Asset&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ReflectorAsset&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's start building our &lt;code&gt;make_guess&lt;/code&gt; function. It needs three things from users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Their address (so we know who's betting)&lt;/li&gt;
&lt;li&gt;A boolean for their prediction (true = EUR goes up, false = EUR goes down)&lt;/li&gt;
&lt;li&gt;How much they want to bet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's begin with some basic validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;make_guess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;will_rise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="nf"&gt;.require_auth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LowBalance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Interact with the Oracle
&lt;/h3&gt;

&lt;p&gt;Here's where things get interesting! To chat with an oracle, we first need to connect to it using its contract address. You can find all the available addresses in the /Oracles tab on the ~&lt;a href="https://reflector.network/oracles" rel="noopener noreferrer"&gt;Reflector website&lt;/a&gt;~.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Fetch Price&lt;/span&gt;
&lt;span class="c1"&gt;// Oracles on-chain are Smart Contracts, therefore we interface them via a contract address.&lt;/span&gt;
&lt;span class="c1"&gt;// Here we convert the address from String to an Address object&lt;/span&gt;
&lt;span class="c1"&gt;// Each Dataset has it's own smart contract address, in our case, for testnet it's the following address&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;oracle_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"CCYOZJCOPG34LLQQ7N24YXBM7LL62R7ONMZ3G6WZAAYPB5OYKOMJRN63"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Create client for working with oracle&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reflector_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ReflectorClient&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;oracle_address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reflector supports two asset types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stellar&lt;/strong&gt;: Assets that live on the Stellar Network&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other&lt;/strong&gt;: External assets like USD, EUR, GBP
Since EUR is not a Stellar asset, we create a Symbol with the currency name:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Set Asset&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ReflectorAsset&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Other&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EUR"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="c1"&gt;// Fetch the most recent price record for it&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reflector_client&lt;/span&gt;&lt;span class="nf"&gt;.lastprice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Check the result&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="nf"&gt;.is_none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LimitReached&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve the price itself&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lastprice function returns an Option containing a struct with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Price&lt;/strong&gt;: Latest price as an i128 value&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp&lt;/strong&gt;: When the data was fetched as a u64 value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Option lets us gracefully handle cases where Reflector might not have data available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Detour: Error Handling in Soroban
&lt;/h3&gt;

&lt;p&gt;You probably noticed our function returns Result - this is Rust's way of saying "I'll either give you a boolean if everything goes well, or an error if something goes wrong."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[contracterror]&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Copy,&lt;/span&gt; &lt;span class="nd"&gt;Clone,&lt;/span&gt; &lt;span class="nd"&gt;Debug,&lt;/span&gt; &lt;span class="nd"&gt;Eq,&lt;/span&gt; &lt;span class="nd"&gt;PartialEq,&lt;/span&gt; &lt;span class="nd"&gt;PartialOrd,&lt;/span&gt; &lt;span class="nd"&gt;Ord)]&lt;/span&gt;
&lt;span class="nd"&gt;#[repr(u32)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;NoPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;LowBalance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Broke&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;NoGuesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TimeNotPassed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;WrongAnswer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Soroban, errors are just u32 enums - each error type gets a simple integer. When we write return Err(Error::NoPrice), we're telling the user exactly what went wrong.&lt;br&gt;
A few things to remember when creating error enums:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must have the &lt;code&gt;#[repr(u32)]&lt;/code&gt; attribute&lt;/li&gt;
&lt;li&gt;Must have the &lt;code&gt;#[derive(Copy)]&lt;/code&gt; attribute&lt;/li&gt;
&lt;li&gt;Every error needs an explicit integer value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⠀Our contract has these error scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oracle didn't return a price&lt;/li&gt;
&lt;li&gt;User doesn't have enough balance&lt;/li&gt;
&lt;li&gt;Contract is out of liquidity&lt;/li&gt;
&lt;li&gt;User trying to verify but hasn't made any guesses&lt;/li&gt;
&lt;li&gt;5 minutes haven't passed yet&lt;/li&gt;
&lt;li&gt;User's prediction was wrong&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Getting Cozy with Soroban Storage:
&lt;/h3&gt;

&lt;p&gt;Soroban is pretty cool when it comes to storing data. It handles simple stuff like integers and strings, but it also lets you store complex objects that you define as structs. One key thing to remember is that Soroban uses key-value storage - think of it like a giant dictionary where you need a key to find your value.&lt;/p&gt;

&lt;p&gt;For simple storage, you start by creating a Symbol:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const NUMBER: Symbol = symbol_short!("NUMBER");&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then storing data is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="nf"&gt;.storage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.instance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;COUNTER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Chosen by Fair Dice Roll&lt;/span&gt;
                       &lt;span class="c1"&gt;// Guaranteed to be Random&lt;/span&gt;
                       &lt;span class="c1"&gt;// https://xkcd.com/221/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably noticed that instance() function - let's talk about Soroban's three storage personalities:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Three Types of Storage
&lt;/h3&gt;

&lt;p&gt;Soroban gives you three different storage options, each with its own personality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Temporary Storage&lt;/strong&gt; - The cheapest option that's perfect for short-term data. You can use unlimited keys, but here's the catch: when temporary storage expires, your data is gone forever. No take-backs, no "oops I need that back" - it's deleted permanently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instance Storage&lt;/strong&gt; - This is more expensive than temporary but has a safety net. When instance storage expires, your data gets "archived" instead of deleted. Think of it like putting something in a storage unit - it's not immediately accessible, but you can get it back if you need it. Instance storage is limited by entry size, so you can't go completely crazy with the amount of data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent Storage&lt;/strong&gt; - The most expensive option, but also the most reliable. Like instance storage, when persistent storage expires, it gets archived rather than deleted. The big advantage? Unlimited keys, so you can store as much as you want (budget permitting).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Time to Live (TTL) - The Ticking Clock
&lt;/h2&gt;

&lt;p&gt;Here's where things get interesting. Every piece of data in Soroban has something called a Time to Live (TTL) that needs to be periodically extended - kind of like renewing a library book. When a TTL hits zero:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Temporary storage&lt;/strong&gt;: Your data vanishes into the digital void&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instance and Persistent storage&lt;/strong&gt;: Your data gets moved to off-chain archived storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When data is archived, your Stellar smart contract can't access it anymore, but it's not gone forever. You can bring it back using the RestoreFootprintOp operation - think of it as retrieving something from that storage unit we mentioned earlier.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It All Works
&lt;/h3&gt;

&lt;p&gt;Every storage type works like a completely separate map (or dictionary) from arbitrary keys to arbitrary values. The cool thing is that these maps are totally independent - you could store different data for the same key in each storage type. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In temporary storage: key number might have a value of &lt;code&gt;543&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In persistent storage: the same number key could have a completely different value like &lt;code&gt;412&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's how you'd retrieve data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;
    &lt;span class="nf"&gt;.storage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.instance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.unwrap_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// If no value set, assume 0.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three storage types work almost identically, with the main differences being cost, what happens when TTL expires, and limits on the number of keys. Choose based on your needs: temporary for short-term data you don't mind losing, instance for moderate amounts of important data, and persistent for large amounts of critical data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storing Complex Data with Structs
&lt;/h2&gt;

&lt;p&gt;One of Soroban's superpowers is that you're not limited to storing simple numbers or strings. You can create custom data structures using Rust structs and store those directly! This is incredibly useful when you need to keep track of multiple related pieces of information together.&lt;br&gt;
To make a struct work with Soroban storage, you need to add some special attributes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[contracttype]&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Clone)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Guess&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;will_rise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;#[contracttype]&lt;/code&gt; attribute tells Soroban "hey, this struct can be stored on the blockchain," while&lt;code&gt;#[derive(Clone)]&lt;/code&gt; gives the struct the ability to be copied when needed.&lt;/p&gt;

&lt;p&gt;In our euro guesser example, each Guess struct bundles together everything we need to know about a user's prediction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;user&lt;/strong&gt;: Who made the guess&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;will_rise&lt;/strong&gt;: Whether they think EUR will go up or down&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;amount&lt;/strong&gt;: How much XLM they're betting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;time&lt;/strong&gt;: When they made the guess (crucial for our 5-minute verification)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⠀You can then store and retrieve these structs just like any other data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store a guess&lt;/span&gt;
&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="nf"&gt;.storage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.instance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve it later&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stored_guess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="nf"&gt;.storage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.instance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Complete the Guess Function
&lt;/h3&gt;

&lt;p&gt;Here's the remaining logic for storing data and transferring XLM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 2. Check Users Balance&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;native_asset_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;native_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;token&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;native_asset_address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;native_client&lt;/span&gt;&lt;span class="nf"&gt;.balance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LowBalance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// 3. Create the guess&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Guess&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;will_rise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="nf"&gt;.ledger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.timestamp&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="c1"&gt;// 4. Store user's guesses in a Vec, one can do multiple guesses why not&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;user_guesses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guess&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="nf"&gt;.storage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.instance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="n"&gt;user_guesses&lt;/span&gt;&lt;span class="nf"&gt;.push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="nf"&gt;.storage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.instance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user_guesses&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="c1"&gt;// 5. Transfer tokens&lt;/span&gt;
&lt;span class="n"&gt;native_client&lt;/span&gt;&lt;span class="nf"&gt;.transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="nf"&gt;.current_contract_address&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Interacting with Smart Contracts &amp;amp; Performing Payments
&lt;/h3&gt;

&lt;p&gt;Now that we've got the basic structure down, let's dive into one of the most important aspects of our contract - handling payments and user authentication. Since our euro guesser involves real money (XLM), we need to understand how funds move around safely in Soroban.&lt;/p&gt;

&lt;p&gt;You probably noticed this line at the beginning of our function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="nf"&gt;.require_auth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple line is doing some serious heavy lifting behind the scenes. It's Soroban's way of saying "prove you own this account before we let you spend money." When this function runs, it checks that the transaction was properly signed by the user's private key. No signature = no dice!&lt;br&gt;
Think of it like requiring a PIN at an ATM - we need proof that you're really you before we let you touch your money.&lt;/p&gt;
&lt;h3&gt;
  
  
  Working with Token Contracts
&lt;/h3&gt;

&lt;p&gt;Here's something cool about Stellar/Soroban - everything is a contract, even XLM (the native Stellar token) is handled through a contract interface. To work with any token, we need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect to the token contract&lt;/li&gt;
&lt;li&gt;Check balances&lt;/li&gt;
&lt;li&gt;Transfer funds&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's how it works for XLM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Connect to the native XLM token contract&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;native_asset_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;native_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;token&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;native_asset_address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That long address string is the contract address for XLM on the Stellar network on testnet. Every token has its own contract address - think of it as XLM's "home address" on the blockchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking Balances - Making Sure Users Have Enough to Play
&lt;/h3&gt;

&lt;p&gt;Before accepting any bets, we should probably check if users actually have the XLM they're trying to bet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;native_client&lt;/span&gt;&lt;span class="nf"&gt;.balance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LowBalance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents the super awkward situation where someone tries to bet 1000 XLM when they only have 5 XLM in their account. The balance() function queries the token contract to get the user's current balance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Moving Money Around - The Transfer
&lt;/h3&gt;

&lt;p&gt;Once we've verified everything checks out (user is authenticated, has enough balance), we can actually move their XLM to our contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;native_client&lt;/span&gt;&lt;span class="nf"&gt;.transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="nf"&gt;.current_contract_address&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Complete Payment Flow&lt;/strong&gt;&lt;br&gt;
Putting it all together, here's what happens when someone makes a bet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt;: user.require_auth() - prove you own the account&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Balance Check&lt;/strong&gt;: Make sure they have enough XLM&lt;/li&gt;
&lt;li&gt;Transfer**: Move their XLM to our contract for safekeeping&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record&lt;/strong&gt;: Store their guess for later verification&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;⠀This pattern of auth → validate → transfer is super common in DeFi applications, so understanding it well will serve you in building all kinds of financial smart contracts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 6: Verify Guesses with Historical Data
&lt;/h3&gt;

&lt;p&gt;Here's where we get sneaky to prevent cheating! We don't want users waiting around for favorable price movements before claiming their winnings. Instead, we use Reflector's historical data feature to check prices at specific timestamps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Fetch the price 5 minutes after the time stored, prevents an attack where one could wait for the price to actually increase when voting&lt;/span&gt;
&lt;span class="c1"&gt;// Fetch the data from exactly the timestamp. Since we know the time, we do not have to story an entry and pay fees&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;newPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reflector_client&lt;/span&gt;&lt;span class="nf"&gt;.price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;guess_data&lt;/span&gt;&lt;span class="py"&gt;.time&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;priceBefore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reflector_client&lt;/span&gt;&lt;span class="nf"&gt;.price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;guess_data&lt;/span&gt;&lt;span class="py"&gt;.time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures fair verification by comparing prices exactly 5 minutes apart. No waiting for the perfect moment to cash in!&lt;/p&gt;

&lt;h3&gt;
  
  
  You Did It! 🎉
&lt;/h3&gt;

&lt;p&gt;Congratulations! You've successfully connected real-world data to your Stellar smart contract using Reflector. This opens up a whole universe of possibilities for building sophisticated dapps, prediction markets, and other data-driven smart contracts that actually know what's happening in the real world.&lt;/p&gt;

&lt;p&gt;View the complete contract code on SoroPg: &lt;a href="https://soropg.com/?codeUrl=https%3A%2F%2Fgist.github.com%2FMatejMecka%2Fed6c77c5f50bc98090552b751ab5d3cb" rel="noopener noreferrer"&gt;contract.rs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now go build something amazing! 🚀&lt;/p&gt;

</description>
      <category>soroban</category>
      <category>stellar</category>
      <category>smartcontracts</category>
      <category>oracles</category>
    </item>
  </channel>
</rss>
