<?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: Mikołaj Bul</title>
    <description>The latest articles on DEV Community by Mikołaj Bul (@mikkolaj).</description>
    <link>https://dev.to/mikkolaj</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%2F1053087%2F05767275-85a0-40e1-942a-32d5c6b9552f.jpg</url>
      <title>DEV Community: Mikołaj Bul</title>
      <link>https://dev.to/mikkolaj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mikkolaj"/>
    <language>en</language>
    <item>
      <title>From Zero to Smart Contract Developer: Soroban</title>
      <dc:creator>Mikołaj Bul</dc:creator>
      <pubDate>Fri, 31 Mar 2023 11:13:20 +0000</pubDate>
      <link>https://dev.to/mikkolaj/from-zero-to-smart-contract-developer-soroban-402c</link>
      <guid>https://dev.to/mikkolaj/from-zero-to-smart-contract-developer-soroban-402c</guid>
      <description>&lt;p&gt;This part of the series covers the process of designing and implementing an example smart contract application on the Soroban network. It assumes that you're familiar with the basics of blockchain and you know how classic Stellar assets work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning is key
&lt;/h2&gt;

&lt;p&gt;As a software developer you've probably at least once had a conversation with one of your friends that went something like this:&lt;br&gt;
- Hey man, I've got a great business idea but I need someone who knows programming. Are you in?&lt;br&gt;
- Sounds cool, what is it about?&lt;br&gt;
- A simple website like Google, white background and a search bar.&lt;br&gt;
- Yeah, right...&lt;br&gt;
This time I was the one with an idea but without necessary knowledge. Instead of finding myself a bored Soroban Developer I decided to figure it out myself.&lt;/p&gt;
&lt;h2&gt;
  
  
  General idea
&lt;/h2&gt;

&lt;p&gt;Imagine a platform where content creators could raise money for specific goals they want to achieve. A creator would list a few goals, and optionally include some secret content they want to release as soon as a particular goal is met - it would act as a way to motivate viewers to take part in fundraising. Currently donations usually go through third party providers that apply a significant fee on each donation. By transferring it through blockchain those fees could be substantially lower.&lt;/p&gt;

&lt;p&gt;Visually speaking:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz1vu7em98sdceybpvbo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz1vu7em98sdceybpvbo.png" alt="Fundraising app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;money can be withdrawn only after reaching a certain goal, otherwise there would be no fun and the actual goals would mean nothing&lt;/li&gt;
&lt;li&gt;viewers specify max amount they want to tip, if the last goal is going to be fulfilled with a lesser tip, then they are going to pay less&lt;/li&gt;
&lt;li&gt;our app will track total tips per user to later form a scoreboard&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Built on Soroban
&lt;/h2&gt;

&lt;p&gt;It's time to take into account some aspects of the technology we're going to use.&lt;/p&gt;

&lt;p&gt;Soroban contracts are written in Rust. If you have never used Rust before, don't panic. About two weeks ago I also knew nothing about it. You'll figure it out. &lt;/p&gt;

&lt;p&gt;As you know blockchain is like a public ledger and thus storing secrets isn't its primary use case. That's why extracting this feature to some backend app will probably be the easiest solution. We're only going to implement the core functionality of handling tips inside our smart contract. The contract however still needs a way to communicate with the outside world.&lt;/p&gt;

&lt;p&gt;Storing data is another concern. It would probably be a bit cumbersome to handle all users and all their sets of goals in one place. That's why we're going to use Soroban's ability to dynamically deploy smart contracts. We'll deploy one contract responsible for deploying smaller contracts which in turn will handle only a particular set of goals for a single user.&lt;/p&gt;

&lt;p&gt;More detailed visualization of our app:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxabg7zqeayf4oa5qs3hs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxabg7zqeayf4oa5qs3hs.png" alt="Soroban app architecture"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up the environment
&lt;/h2&gt;

&lt;p&gt;Installing all the necessary things is pretty easy and already documented in Soroban's Getting Started guide, so I suggest you visit this &lt;a href="https://soroban.stellar.org/docs/getting-started/setup" rel="noopener noreferrer"&gt;site&lt;/a&gt; first and follow the setup instructions. Two main CLI tools you'll need later on are &lt;code&gt;cargo&lt;/code&gt; and &lt;code&gt;soroban&lt;/code&gt;. Cargo is a package manager for Rust and &lt;code&gt;soroban&lt;/code&gt; will help you interact with Soroban network. Execute &lt;code&gt;soroban --help&lt;/code&gt; to get a sneak-peek of what it can help you with.&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's learn Rust
&lt;/h2&gt;

&lt;p&gt;Rust is a language that has some unique features compared to other ones like C or Java. For me the one that distinguishes it the most is the idea of ownership. But first we're going to look at some code examples.&lt;/p&gt;
&lt;h3&gt;
  
  
  Constants and variables
&lt;/h3&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;variable&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;variable&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="c1"&gt;// all good&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;constant&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;constant&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="c1"&gt;// compile error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Defining a function:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&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;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Calculating sum"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You don't have to use "return" keyword. If the last executed line inside a function doesn't end with a semicolon, then its result is going to be the returned value.&lt;/p&gt;
&lt;h3&gt;
  
  
  Structs
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greet_owner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hi {}!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.owner&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&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;pet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Garfield"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Jon"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="nf"&gt;.greet_owner&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;There are no classes in Rust, instead we define structs. However we can attach an impl block to a struct to extend it with some functions that can later be called in a handy method-call-like way.&lt;/p&gt;
&lt;h3&gt;
  
  
  Attributes
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Clone)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&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;Attributes are pieces of metadata that can, among others, be used to automatically generate some functionality like a &lt;code&gt;.clone()&lt;/code&gt; function.&lt;/p&gt;
&lt;h3&gt;
  
  
  Modules
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Rust allows you to organize your code into modules, stored in separate files, which can then be included in other files by using the mod keyword.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ownership
&lt;/h3&gt;

&lt;p&gt;Ownership is the mechanism that simplifies memory management in Rust. You don't have to handle it manually like in C, yet there is no garbage collector. The idea is that every variable lives only within a scope and has one owner. Variable can go out of scope when function returns or the ownership is passed to another scope. For example calling a function with a variable passes the ownership to that function. If we don't want to change the owner of the variable we can borrow it to the 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="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;takes_ownership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// types prefixed with &amp;amp; are borrowed to the function&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;borrows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;borrows&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;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// borrowed variables are prefixed with &amp;amp;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// name still valid here&lt;/span&gt;
    &lt;span class="nf"&gt;takes_ownership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// compile error, name already freed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice it's a bit more complicated than what I tried to explain here so I recommend you check out &lt;a href="https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html" rel="noopener noreferrer"&gt;this&lt;/a&gt; chapter from Rust docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soroban's architecture - deeper dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Contract execution
&lt;/h3&gt;

&lt;p&gt;Smart contracts on Soroban are written as libraries in Rust. Those libraries are then compiled into WASM that is executed inside Virtual Machines on the Hosts belonging to the network. Those VM instances are intended to be lightweight and short-lived. Their lifecycles span from the contract call to function exit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Isolated, but connected
&lt;/h3&gt;

&lt;p&gt;Functions inside the contract reach out of the VM by accessing the Host's API. Each function accepts an Env object that allows it to make those interactions (e.g. persist data, emit events that can later be polled from the Internet).&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimizations
&lt;/h3&gt;

&lt;p&gt;In order to optimize the binary we need to accept some tradeoffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By default we exclude the standard Rust library as it causes the binaries to grow too much in size.&lt;/li&gt;
&lt;li&gt;Dynamic memory allocation withing guest's linear memory is expensive. Instead we can store dynamically allocated data inside Host objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Interoperability with classic Stellar assets
&lt;/h3&gt;

&lt;p&gt;For a classic Stellar asset to be accessible on Soroban it needs to have a corresponding Stellar Asset Contract deployed. Token contracts generally implement the &lt;a href="https://soroban.stellar.org/docs/reference/interfaces/token-interface" rel="noopener noreferrer"&gt;Token Interface&lt;/a&gt;. The XLM contract is already deployed on the Futurenet, so later on we'll only have to find its ID.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contract lifecycle
&lt;/h3&gt;

&lt;p&gt;For a contract to be deployed on the network it's code needs to be installed there first. The result of installing a contract with &lt;code&gt;soroban&lt;/code&gt; CLI is a wasm hash that identifies the location of contract's code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pulling the code
&lt;/h2&gt;

&lt;p&gt;Go ahead and pull the project from my &lt;a href="https://github.com/mikkolaj/FundMyGoals" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; and switch to the &lt;code&gt;chapter2&lt;/code&gt; branch. But before you look at it I'll try to walk you through some examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hello World
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://soroban.stellar.org/docs/getting-started/hello-world" rel="noopener noreferrer"&gt;Hello World&lt;/a&gt; example from Soroban's Getting Started guide shows clearly how the contract is built. Let's take a look at it.&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;#![no_std]&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;soroban_sdk&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;contractimpl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vec&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;Symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;};&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;Contract&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[contractimpl]&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;hello&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;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Symbol&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;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="nd"&gt;symbol!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;]&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;There are a few things to note here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each contract starts with a &lt;code&gt;#![no_std]&lt;/code&gt; attribute which excludes the Rust's standard library&lt;/li&gt;
&lt;li&gt;We define a contract by creating an empty struct and attaching an &lt;code&gt;impl&lt;/code&gt; block to it&lt;/li&gt;
&lt;li&gt;The impl block needs to have a &lt;code&gt;#[contractimpl]&lt;/code&gt; attribute attached&lt;/li&gt;
&lt;li&gt;Contract functions which intend to be accessible by the caller need to be public and the function name must be at most 10 characters long&lt;/li&gt;
&lt;li&gt;Each public function accepts an Env object as the first argument, the following arguments are provided by the caller&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vec!&lt;/code&gt; is a macro that creates a &lt;code&gt;Vec&lt;/code&gt; data structure from soroban_sdk. It is a growable vector stored in the host environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Public interface
&lt;/h3&gt;

&lt;p&gt;The tip-contract is going to comprise four public functions described by the trait (interface) below. We're not actually going to use this trait but it describes well what we're trying to accomplish.&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;trait&lt;/span&gt; &lt;span class="n"&gt;ContractTrait&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// initializes the contract with Goal Description&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;init&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;goal_desc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GoalDesc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Function used by viewers, they specify their identity&lt;/span&gt;
    &lt;span class="c1"&gt;// and the max amount they want to tip&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;tip&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;tipper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tipper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_transfer&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;i128&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Pays out the tokens due to the creator for completed goals&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;withdraw&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Returns a scoreboard with nicknames mapped to&lt;/span&gt;
    &lt;span class="c1"&gt;// the sum of tips&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;scoreboard&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;
  
  
  Contract types
&lt;/h3&gt;

&lt;p&gt;Fields present in custom contract types also need to be at most 10 characters long. Sometimes it is challenging to find a good name that is this short and still explains the meaning well.&lt;/p&gt;

&lt;p&gt;Types exposed to the user:&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="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;GoalDesc&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;creator&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;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BytesN&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;goals&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="nb"&gt;i128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&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;Tipper&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;nickname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bytes&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;address&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Another important attribute is &lt;code&gt;#[contracttype]&lt;/code&gt;. Each custom type we want to use in the contract needs to be annotated with it.&lt;/li&gt;
&lt;li&gt;Address is a built-in type that identifies an account&lt;/li&gt;
&lt;li&gt;Our contract is also going to support tokens other than XLM, provided they implement the Token Interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contract types:&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="nd"&gt;Copy,&lt;/span&gt; &lt;span class="nd"&gt;PartialEq)]&lt;/span&gt;
&lt;span class="c1"&gt;// Order: Uninitialized -&amp;gt; Initialized -&amp;gt; Completed&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;Phase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Uninitlzd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Initlzd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Completed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[contracttype]&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Clone)]&lt;/span&gt;
&lt;span class="c1"&gt;// used for storing things in the key-value store.&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;DataKey&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GoalDesc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CurState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[contracttype]&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Clone)]&lt;/span&gt;
&lt;span class="c1"&gt;// describes the whole mutable state of the contract.&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;CurrentState&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;phase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Phase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// amount of money already tipped for the current goal&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;goal_money&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="c1"&gt;// first unpaid goal&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;unpaid_idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// index of the current goal&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;cur_goal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&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;scoreboard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;i128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;
  
  
  Importing Soroban Token Spec
&lt;/h3&gt;

&lt;p&gt;To make use of the token client we need to import the token specification in the form of a .wasm binary. At first it was a bit odd to me that there wasn't a dedicated package in the SDK that would handle standard token operations, but maybe there's a reason for that.&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;token&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;soroban_sdk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;contractimport!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"soroban_token_spec.wasm"&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;To import a binary into the contract we use &lt;code&gt;contractimport!&lt;/code&gt; macro from the SDK.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storing data
&lt;/h3&gt;

&lt;p&gt;Retrieving and storing data is pretty straightforward. Env.storage() object provides us with &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; functions which access the data by key. We can use DataKey type we've defined earlier for this purpose.&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;cur_state&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;.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="nn"&gt;DataKey&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CurState&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;span class="nf"&gt;.unwrap&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;.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="nn"&gt;DataKey&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CurState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nf"&gt;empty_state&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="nn"&gt;Phase&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Initlzd&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Panicking
&lt;/h3&gt;

&lt;p&gt;One way to stop the contract execution is to invoke the &lt;code&gt;panic!&lt;/code&gt; macro which causes the program to exit immediately. None of the changes made in the contract call which panicked are persisted to the network.&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;fn&lt;/span&gt; &lt;span class="nf"&gt;verify_init&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="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;goals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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="nb"&gt;i128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;current_phase&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;!=&lt;/span&gt; &lt;span class="nn"&gt;Phase&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Uninitlzd&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Contract already initialized!"&lt;/span&gt;&lt;span class="p"&gt;)&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;
  
  
  Emitting events
&lt;/h3&gt;

&lt;p&gt;To emit events we use the &lt;code&gt;Env.events().publish()&lt;/code&gt; function which accepts a tuple of topics (up to 4) and a value that we want to publish to the topic.&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;const&lt;/span&gt; &lt;span class="n"&gt;GOALS_TOPIC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;symbol!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"goals"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;emit_events&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="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;goals_met&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="nb"&gt;i128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;goals_met&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;.events&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.publish&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;GOALS_TOPIC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;());&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;
  
  
  Transfering tokens
&lt;/h3&gt;

&lt;p&gt;Finally we've made it to the point where we transfer the tokens. It can be achieved by creating the token client we've imported earlier and calling it's &lt;code&gt;.xfer()&lt;/code&gt; function. Below is an example of a transfer from the tipper to the 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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;contract&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;.current_contract_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;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;goal_desc&lt;/span&gt;&lt;span class="py"&gt;.token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.xfer&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;tipper&lt;/span&gt;&lt;span class="py"&gt;.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;contract&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;h3&gt;
  
  
  Contract-deployer
&lt;/h3&gt;

&lt;p&gt;The code of contract deployer is relatively short but utilizes two important functions from the Env object.&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;#[contractimpl]&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Deployer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;deploy&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;salt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;wasm_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BytesN&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;32&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;creator&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;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BytesN&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;32&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;goals&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="nb"&gt;i128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;BytesN&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;id&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;.deployer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.with_current_contract&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;salt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.deploy&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;wasm_hash&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;goal_desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;tip_contract&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GoalDesc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;creator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;goals&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;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&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;.invoke_contract&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;symbol!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"init"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goal_desc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into_val&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;id&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;Contract ids of dynamically deployed contracts are deterministic and generated based on the deploying contract's id and provided salt. That's why during each deployment we'll need to pass a unique salt.&lt;/p&gt;

&lt;p&gt;To invoke a contract function we need to provide the contract id, the name of the fuction and its arguments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;All the commands described here are also present in the repo in the &lt;code&gt;scripts&lt;/code&gt; folder. You'll also find a template there that will help you manage the things you should note down to successfully go through the demo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating necessary accounts
&lt;/h3&gt;

&lt;p&gt;Generate 3 keypairs for accounts on the Futurenet and fund each of them using Friendbot. One of the accounts is going to act as the creator and two of them are going to be viewers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing tip-contract
&lt;/h3&gt;

&lt;p&gt;If we want to deploy the tip-contract multiple times with the contract-deployer, then we need to install the code of tip-contract on the network first. But before that let's build the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build &lt;span class="nt"&gt;--target&lt;/span&gt; wasm32-unknown-unknown &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we install the contract on the network. Replace &amp;lt;tags&amp;gt; with your generated credentials.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;soroban contract &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--wasm&lt;/span&gt; ../target/wasm32-unknown-unknown/release/tip_contract.wasm &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secret-key&lt;/span&gt; &amp;lt;Creators private key&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc-futurenet.stellar.org:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-passphrase&lt;/span&gt; &lt;span class="s1"&gt;'Test SDF Future Network ; October 2022'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this call is a wasm hash that identifies the contract code on the network.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying contract-deployer
&lt;/h3&gt;

&lt;p&gt;The contract deployer needs to be deployed only once, so we can skip the step of separately installing the contract and instead use &lt;code&gt;soroban contract deploy&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;soroban contract deploy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--wasm&lt;/span&gt; ../target/wasm32-unknown-unknown/release/contract_deployer.wasm &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secret-key&lt;/span&gt; &amp;lt;Creator private key&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc-futurenet.stellar.org:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-passphrase&lt;/span&gt; &lt;span class="s1"&gt;'Test SDF Future Network ; October 2022'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploying and initializing tip-contract
&lt;/h3&gt;

&lt;p&gt;Deployment and initialization happens during one call to &lt;code&gt;deploy()&lt;/code&gt; in contract-deployer. That's why we need to specify the Goal Description together with deployment details i.e. wasm hash and salt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Goals are specified in stroops (1XLM = 10.000.000 Stroops)&lt;/span&gt;
soroban contract invoke &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--id&lt;/span&gt; &amp;lt;Contract deployers contract &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secret-key&lt;/span&gt; &amp;lt;Creator private key&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc-futurenet.stellar.org:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-passphrase&lt;/span&gt; &lt;span class="s1"&gt;'Test SDF Future Network ; October 2022'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--fn&lt;/span&gt; deploy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--salt&lt;/span&gt; 0000000000000000000000000000000000000000000000000000000000000000 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--wasm_hash&lt;/span&gt; &amp;lt;Wasm &lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--creator&lt;/span&gt; &amp;lt;Creator public key&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--token&lt;/span&gt; d93f5c7bb0ebc4a9c8f727c5cebc4e41194d38257e1d0d910356b43bfc528813 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--goals&lt;/span&gt; &lt;span class="s1"&gt;'["10000000","100000000"]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Value specified here for the token is the id of XLM Stellar Asset Contract.&lt;br&gt;
After you executing the command above go to the &lt;a href="https://horizon-futurenet.stellar.org/" rel="noopener noreferrer"&gt;Horizon&lt;/a&gt; endpoint and note down the &lt;code&gt;core_latest_ledger&lt;/code&gt; number.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tipping
&lt;/h3&gt;

&lt;p&gt;As an example we're going to send two tips from different accounts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# First Tip&lt;/span&gt;
soroban contract invoke &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--id&lt;/span&gt; &amp;lt;Tip contract contract &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secret-key&lt;/span&gt; &amp;lt;Tipper1 private key&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc-futurenet.stellar.org:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-passphrase&lt;/span&gt; &lt;span class="s1"&gt;'Test SDF Future Network ; October 2022'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--fn&lt;/span&gt; tip &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tipper&lt;/span&gt; &lt;span class="s1"&gt;'{"nickname":"4A6F686E20446F64", "address": "&amp;lt;Tipper1 public key&amp;gt;"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--max_transfer&lt;/span&gt; 10000000

&lt;span class="c"&gt;# Second Tip&lt;/span&gt;
soroban contract invoke &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--id&lt;/span&gt; &amp;lt;Tip contract contract &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secret-key&lt;/span&gt; &amp;lt;Tipper2 private key&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc-futurenet.stellar.org:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-passphrase&lt;/span&gt; &lt;span class="s1"&gt;'Test SDF Future Network ; October 2022'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--fn&lt;/span&gt; tip &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tipper&lt;/span&gt; &lt;span class="s1"&gt;'{"nickname":"4A6F686E20446F65", "address": "&amp;lt;Tipper2 public key&amp;gt;"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--max_transfer&lt;/span&gt; 100000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take a look at the way we pass custom types to the functions. We represent Tipper as a JSON object and since we've defined the nickname as Bytes, we need to pass it as a hex encoded string. More on custom types can be found in &lt;a href="https://quest.stellar.org/soroban" rel="noopener noreferrer"&gt;Soroban Quest&lt;/a&gt; chapter 5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Withdrawing
&lt;/h2&gt;

&lt;p&gt;In the previous step we've sent a total of 11 XLM and completed all the goals for the contract. Now it's time for the creator to withdraw the tokens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;soroban contract invoke &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--id&lt;/span&gt; &amp;lt;Tip contract contract &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secret-key&lt;/span&gt; &amp;lt;Creator private key&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc-futurenet.stellar.org:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-passphrase&lt;/span&gt; &lt;span class="s1"&gt;'Test SDF Future Network ; October 2022'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--fn&lt;/span&gt; withdraw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scoreboard
&lt;/h3&gt;

&lt;p&gt;Let's fetch the scoreboard to see if the results are accurate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;soroban contract invoke &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--id&lt;/span&gt; &amp;lt;Tip contract contract &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secret-key&lt;/span&gt; &amp;lt;Any private key&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc-futurenet.stellar.org:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-passphrase&lt;/span&gt; &lt;span class="s1"&gt;'Test SDF Future Network ; October 2022'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--fn&lt;/span&gt; scoreboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fee730ktx6a4lf4eu8gno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fee730ktx6a4lf4eu8gno.png" alt="Contract scoreboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seems like the result is correct.&lt;/p&gt;

&lt;h3&gt;
  
  
  Events
&lt;/h3&gt;

&lt;p&gt;The last thing we can check are the events emitted by our contract. Now you'll use the &lt;code&gt;core_latest_ledger&lt;/code&gt; number you've noted down earlier - it tells the API where to start looking for the events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;soroban events &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc-futurenet.stellar.org:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--start-ledger&lt;/span&gt; &amp;lt;Start ledger&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--id&lt;/span&gt; &amp;lt;Tip contract contract &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5viukaaokhk24l29nyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5viukaaokhk24l29nyz.png" alt="Soroban events"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Success! The contract emitted events that correspond to the goals that were completed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking the balance
&lt;/h3&gt;

&lt;p&gt;Head over to &lt;a href="https://laboratory.stellar.org/#explorer?resource=accounts&amp;amp;endpoint=single&amp;amp;network=futurenet" rel="noopener noreferrer"&gt;Stellar Lab&lt;/a&gt; and check the balances of your accounts. If everything went fine the tips should be transferred from viewers to the creator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;If you've come this far then congratulations! You now know the basics of developing Smart Contracts on Soroban. This chapter comes to an end without actually completing the rest of the app presented at the beginning, because this post is already a bit long. There are also few things that I would like to mention now.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My implementation of the contract definitely has some shortcomings e.g. it lacks proper error handling. To see correct examples take a look at the docs.&lt;/li&gt;
&lt;li&gt;This guide doesn't cover the topic of testing. You can find some tests in the repo, but they only check one happy path needed for the Demo.&lt;/li&gt;
&lt;li&gt;This contract implements no authentication. I encourage you to poke around in the code to see if you'll be able to exploit it in some fun way.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recommended sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://soroban.stellar.org/docs/" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt; - official Soroban guide for beginners&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://soroban.stellar.org/docs/category/learn" rel="noopener noreferrer"&gt;Soroban Learn&lt;/a&gt; - official docs explaining the architecture of Soroban&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.sorobandev.com/" rel="noopener noreferrer"&gt;Sorobandev blog&lt;/a&gt; - it explains the examples presented in Soroban docs but in greater detail &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://quest.stellar.org/soroban" rel="noopener noreferrer"&gt;Soroban Quest&lt;/a&gt; - an interactive quest where you can learn more about Soroban&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>stellar</category>
      <category>soroban</category>
      <category>sorobanathon</category>
    </item>
    <item>
      <title>From Zero to Smart Contract Developer: Stellar</title>
      <dc:creator>Mikołaj Bul</dc:creator>
      <pubDate>Fri, 31 Mar 2023 11:12:58 +0000</pubDate>
      <link>https://dev.to/mikkolaj/from-zero-to-smart-contract-developer-stellar-classic-hoe</link>
      <guid>https://dev.to/mikkolaj/from-zero-to-smart-contract-developer-stellar-classic-hoe</guid>
      <description>&lt;p&gt;In this series of tutorials you'll go through the basics of blockchain technology, send example transactions on Stellar's network and finally write a smart contract for content creators and their viewers. If you're already familiar with classic Stellar assets you can move on to the next post in the series which covers the smart contracts alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is blockchain?
&lt;/h2&gt;

&lt;p&gt;You can think of blockchain as a decentralized public ledger that records all the transactions in the network. Its general use case is transferring digital money between people and parties. Currently there are lots of blockchains that accomplish this task and some of them additionally support a feature called Smart contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart contracts
&lt;/h2&gt;

&lt;p&gt;Smart contracts are a way to implement an arbitrary user-defined logic that handles transactions on the network. The possibilities are basically infinite but some example use cases that could benefit from incorporating this feature are: your own digital token, a fundraising app or a multiplayer game that distributes collectibles to players.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stellar and Soroban
&lt;/h2&gt;

&lt;p&gt;Stellar is a blockchain that was created in 2014. One of the traits that distinguishes it from older Proof-of-Work platforms like Bitcoin is very low transaction fees. Recently the team behind Stellar started developing their own smart contract platform called Soroban that integrates with classic Stellar assets. This tutorial focused on those two technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stellar assets
&lt;/h2&gt;

&lt;p&gt;Stellar's native asset is Lumen (XLM). It represents a real world value and can be acquired for example on crypto exchanges. To take part in this tutorial you don't have have to actually spend any money. Stellar hosts two more networks (Test and Futurenet) in addition to its main network, where you can fund your account for free and experiment with all the blockchain's features. We'll use Futurenet from now on as it also supports Soroban. There is a great tool that makes it easy to experiment with Stellar's features called Laboratory and you can find it &lt;a href="https://laboratory.stellar.org/#?network=futurenet" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an account
&lt;/h2&gt;

&lt;p&gt;Stellar uses asymmetric cryptography to enable authentication of transactions. Each account is associated with two keys - public and private. Public key provides you with an identity on the network and private key is needed for signing transactions. Let's start by generating this keypair and funding your account with some starting funds by using &lt;a href="https://laboratory.stellar.org/#account-creator?network=futurenet" rel="noopener noreferrer"&gt;Stellar Lab&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbquyxp9icj5r2ff8v2h9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbquyxp9icj5r2ff8v2h9.png" alt="Creating and funding Stellar account"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your first transaction
&lt;/h2&gt;

&lt;p&gt;To send your first payment in XLM, you'll have to generate and fund another account first. Note down the keypair you've generated earlier - if you lose it, you'll lose access to the account. Then go to "Build transaction" and fill out the necessary fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source account&lt;/li&gt;
&lt;li&gt;Click "Fetch next sequence number..." (it needs to be re-fetched after each transaction on an account)&lt;/li&gt;
&lt;li&gt;Operation type: Payment&lt;/li&gt;
&lt;li&gt;Destination&lt;/li&gt;
&lt;li&gt;Asset: Native (XLM)&lt;/li&gt;
&lt;li&gt;Amount (e.g. 5000)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljsrkn0yqfwnimj2g6ll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljsrkn0yqfwnimj2g6ll.png" alt="Stellar transaction source account"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbmzoc3clk95xndp8u0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbmzoc3clk95xndp8u0h.png" alt="Stellar transaction destination"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click "Sign in Transaction Signer", enter private key of the source account, click "Submit in Transaction Submitter" and then "Submit Transaction".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8cw08u98a4l5bmt5hz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8cw08u98a4l5bmt5hz1.png" alt="Signing stellar transaction with private key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If everything went well you'll see a success message informing  you that this transaction was a success.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking your balance
&lt;/h2&gt;

&lt;p&gt;Usually you'd check the details of your account on a blockchain explorer like &lt;a href="https://stellar.expert/explorer/public" rel="noopener noreferrer"&gt;StellarExpert&lt;/a&gt;, but Futurenet is not supported yet, so we'll query the endpoint for our account with Stellar Lab. Open up this &lt;a href="https://laboratory.stellar.org/#explorer?resource=accounts&amp;amp;endpoint=single&amp;amp;network=futurenet" rel="noopener noreferrer"&gt;link&lt;/a&gt; and check the response for both of your accounts. The response will contain the information we're looking for somewhere at the bottom in "balances" section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgg4wf7hra6esafnn3ylf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgg4wf7hra6esafnn3ylf.png" alt="Stellar account balance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see our balance has been reduced by the amount we've sent to the receiving account plus a small fee of 0.0000200 XLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Now that you're familiar with the basics of classic Stellar assets we can move on to designing our own smart contract application with the help of Soroban platform. If you want to learn more &lt;a href="https://quest.stellar.org/learn" rel="noopener noreferrer"&gt;Stellar Quest Learn&lt;/a&gt; is a place where you can learn about blockchain and also earn some real XLM for completing the tasks. It's also worth mentioning that in everyday use you'd use a hardware or software wallet instead of Stellar Lab. They make it a lot easier to operate your account.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>stellar</category>
      <category>soroban</category>
      <category>sorobanathon</category>
    </item>
  </channel>
</rss>
