<?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: Row-Bear</title>
    <description>The latest articles on DEV Community by Row-Bear (@row-bear).</description>
    <link>https://dev.to/row-bear</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%2F1174093%2Fbd1ef380-8234-4975-9ca0-a6b0d3d715d1.jpg</url>
      <title>DEV Community: Row-Bear</title>
      <link>https://dev.to/row-bear</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/row-bear"/>
    <language>en</language>
    <item>
      <title>Launch your own SorobanRPC server</title>
      <dc:creator>Row-Bear</dc:creator>
      <pubDate>Fri, 16 Aug 2024 21:24:51 +0000</pubDate>
      <link>https://dev.to/row-bear/launch-your-own-sorobanrpc-server-bin</link>
      <guid>https://dev.to/row-bear/launch-your-own-sorobanrpc-server-bin</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/stellar"&gt;Build Better on Stellar: Smart Contract Challenge &lt;/a&gt;: Create a Tutorial&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Tutorial
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/row-bear/rpc-for-soroban-mainnet-36eo"&gt;https://dev.to/row-bear/rpc-for-soroban-mainnet-36eo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Created
&lt;/h2&gt;

&lt;p&gt;This is a tutorial I wrote shortly after the launch of Soroban, to help devs set up their own SorobanRPC server.&lt;br&gt;
Now, there are also good public RPC services available, but this may still be useful for someone out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;Int he days leading up to the launch of Soroban, I had set myself the goal to be the first to invoke a Soroban contract.&lt;br&gt;
I realized that there'd likely not be any public RPC service available off the bat, so I figured out how to use the SorobanRPC docker image to run my own.&lt;/p&gt;

&lt;p&gt;Alas, I did think of the RPC Server, but did not properly account for the resource limits.&lt;br&gt;
Deploying the XLM contract was not possible with the CLI during phase 0, so my RPC Server ended up not used. Overcat managed to deploy the contracts via SDK, leaving me the dubious honour of being the first to 'burn' a stroop via smart contract transfer.&lt;/p&gt;

&lt;p&gt;Anyway, I hope this may still come in handy for anyone wanting their own RPC server for developing and testing purposes.&lt;/p&gt;

&lt;p&gt;As always, join the &lt;a href="https://discord.gg/stellardev" rel="noopener noreferrer"&gt;Stellar Dev&lt;/a&gt; discord to discuss the technical stuff, and the &lt;a href="https://discord.gg/stellar-global-761985725453303838" rel="noopener noreferrer"&gt;Stellar Global&lt;/a&gt; discord for everything Stellar.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>stellarchallenge</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>Soroban RPC - on Windows</title>
      <dc:creator>Row-Bear</dc:creator>
      <pubDate>Sat, 24 Feb 2024 21:58:16 +0000</pubDate>
      <link>https://dev.to/row-bear/soroban-rpc-on-windows-47kd</link>
      <guid>https://dev.to/row-bear/soroban-rpc-on-windows-47kd</guid>
      <description>&lt;p&gt;Earlier, I &lt;a href="https://dev.to/row-bear/rpc-for-soroban-mainnet-36eo"&gt;posted&lt;/a&gt; how to run the Soroban RPC Docker image locally on Linux.&lt;br&gt;
Today, I'll give you the steps for Windows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) Install Docker Desktop&lt;/strong&gt;&lt;br&gt;
You can just use the installer.&lt;br&gt;
&lt;a href="https://docs.docker.com/desktop/install/windows-install/"&gt;https://docs.docker.com/desktop/install/windows-install/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) Sign in (or not)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrh1cnnoef1rhn3rykum.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrh1cnnoef1rhn3rykum.png" alt="Docker desktop login screen" width="608" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) Search for stellar/soroban-rpc and pull it&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmox8h8b40mk7i7nf3ne4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmox8h8b40mk7i7nf3ne4.png" alt="Search results for stellar/soroban-rpc in Docker Desktop" width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4) Create a stellar-core.toml config file&lt;/strong&gt;&lt;br&gt;
I use the example I stored &lt;a href="https://gist.githubusercontent.com/Row-Bear/952266e78ab8a5c623786fa4fa5feba2/raw/7d4d798d3b3db36282fee18cfcbb47aa1e3b1a9f/stellar-core.toml"&gt;here&lt;/a&gt; but as Kalepail pointed out during his stream on the Stellar Dev discord, you can use one from the &lt;a href="https://github.com/stellar/quickstart/blob/master/pubnet/core/etc/stellar-core.cfg"&gt;Quickstart image&lt;/a&gt;.&lt;br&gt;
You may need to remove some lines from the header.&lt;/p&gt;

&lt;p&gt;I placed it at c:\soroban-rpc&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4) Start a terminal (cmd) window and run the container:&lt;/strong&gt;&lt;br&gt;
I used the following command to start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -p 8001:8001 -p 8000:8000 ^
-v c:/soroban-rpc:/config stellar/soroban-rpc ^
--captive-core-config-path="/config/stellar-core.toml" ^
--captive-core-storage-path="/var/lib/stellar/captive-core" ^
--stellar-core-binary-path="/usr/bin/stellar-core" ^
--db-path="/var/lib/stellar/soroban-rpc-db.sqlite" ^
--stellar-captive-core-http-port=11626 ^
--network-passphrase="Public Global Stellar Network ; September 2015" ^
--history-archive-urls="https://history.stellar.org/prd/core-live/core_live_001" ^
--admin-endpoint="0.0.0.0:8001" ^
--endpoint="0.0.0.0:8000"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things of note: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;notice how I used the directory of the stellar-core.toml config in the second line.&lt;/li&gt;
&lt;li&gt;Windows cmd uses ^ for multi-line input. Delightfully, Powershell uses ` (backtick) ¯\_(ツ)_/¯
You can probably do this from the Docker Desktop UI, but I haven't figured out how to easily launch it with all these flags.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5) Go back to Docker Desktop and check the containers tab.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2z722dq411qauahl7a93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2z722dq411qauahl7a93.png" alt="Container overview in Docker Desktop" width="800" height="457"&gt;&lt;/a&gt;&lt;br&gt;
You can start/stop the container from here, and also see its stats.&lt;/p&gt;

&lt;p&gt;During initial sync, it uses ~50% of my CPU (&lt;a href="https://www.intel.com/content/www/us/en/products/sku/132222/intel-core-i512450h-processor-12m-cache-up-to-4-40-ghz/specifications.html"&gt;i5 12450h&lt;/a&gt;) and about 4-5 GB RAM, but after about 15 minutes that dropped to 15% and 1GB. Docker Desktop itself uses 7GB RAM though, I guess it reserves quite some headroom.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1tciq6unqzxdxhko51v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1tciq6unqzxdxhko51v.png" alt="Container resource usage graphs" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any practical tips for others, please share them in the comments :-)&lt;/p&gt;

&lt;p&gt;As always, join the &lt;a href="https://discord.gg/stellardev"&gt;Stellar Dev&lt;/a&gt; discord to discuss the technical stuff, and the &lt;a href="https://discord.gg/stellar-global-761985725453303838"&gt;Stellar Global&lt;/a&gt; discord for everything Stellar.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>soroban</category>
      <category>stellar</category>
    </item>
    <item>
      <title>RPC for Soroban mainnet</title>
      <dc:creator>Row-Bear</dc:creator>
      <pubDate>Thu, 22 Feb 2024 12:01:52 +0000</pubDate>
      <link>https://dev.to/row-bear/rpc-for-soroban-mainnet-36eo</link>
      <guid>https://dev.to/row-bear/rpc-for-soroban-mainnet-36eo</guid>
      <description>&lt;p&gt;It's here! Soroban smart contracts have launched on Stellar mainnet on &lt;a href="https://stellar.org/blog/developers/protocol-20-and-smart-contracts-are-live-on-mainnet" rel="noopener noreferrer"&gt;20 Feb 2024 at 17:00 UTC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The validators cast their votes at 17:00 UTC, and the first ledger after that (&lt;a href="https://stellar.expert/explorer/public/ledger/50457424" rel="noopener noreferrer"&gt;50457424&lt;/a&gt;) was running on protocol 20.&lt;br&gt;
And within seconds, the first smart contract was deployed:  &lt;a href="https://stellar.expert/explorer/public/contract/CDGFGODCSQQQFFBUEJGS7NIDUA5OQKBRFQ57IOKZAZIEJDNQNHS3RV5O" rel="noopener noreferrer"&gt;CDGFGODCSQQQFFBUEJGS7NIDUA5OQKBRFQ57IOKZAZIEJDNQNHS3RV5O&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;But then.. quiet!? No other contract calls. Why is that?&lt;br&gt;
First of all, Soroban is in phase 0 for the first week, with very low limits on resources contracts can use.&lt;br&gt;
But another thing that perhaps caught devs by surprise was the lack of RPC servers.&lt;br&gt;
See, you need an RPC server to interact with Soroban. And for testnet and futurenet, the SDF has made their RPC server publicly availabe. Not so on mainnet though.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what's a dev to do?&lt;/strong&gt;&lt;br&gt;
The docs have a &lt;a href="https://soroban.stellar.org/docs/reference/rpc-list" rel="noopener noreferrer"&gt;list of public RPC providers&lt;/a&gt; you can have a look at. &lt;br&gt;
There are paid and free plans, and even no-signup options.&lt;br&gt;
But you can also run one yourself. It's not very hard, I managed to do it.&lt;br&gt;
There is a page in the &lt;a href="https://soroban.stellar.org/docs/reference/rpc#docker-image" rel="noopener noreferrer"&gt;Soroban docs&lt;/a&gt;, but I found myself needing more info.&lt;br&gt;
And I've compiled that info and steps into a bite-size guide here!&lt;/p&gt;

&lt;p&gt;You will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~ 80GB of disk space&lt;/li&gt;
&lt;li&gt;~ 1 hour for initial sync&lt;/li&gt;
&lt;li&gt;~ 1o minutes for re-sync when you re-start it&lt;/li&gt;
&lt;li&gt;An internet connection&lt;/li&gt;
&lt;li&gt;At least some CPU and RAM, I run it comfortably on my laptop with (&lt;a href="https://www.intel.com/content/www/us/en/products/sku/132222/intel-core-i512450h-processor-12m-cache-up-to-4-40-ghz/specifications.html" rel="noopener noreferrer"&gt;i5 12450h&lt;/a&gt; CPU and 16 GB RAM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The below is for Linux, see my &lt;a href="https://dev.to/row-bear/soroban-rpc-on-windows-47kd"&gt;other post&lt;/a&gt; for Windows.&lt;/p&gt;

&lt;p&gt;I give you my&lt;/p&gt;

&lt;h2&gt;
  
  
  10 easy steps to run Soroban-RPC
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1) Docker&lt;/strong&gt;&lt;br&gt;
First, you'll need to install docker on your PC.&lt;br&gt;
I followed &lt;a href="https://www.linuxtechi.com/how-to-install-docker-on-linux-mint/" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) Set up a folder&lt;/strong&gt;&lt;br&gt;
Create a folder in your home/user dir, called soroban-rpc&lt;br&gt;
For me, that is at /home/row-bear/soroban-rpc&lt;br&gt;
(Or whatever you like, just remember the name)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) Get the Docker image&lt;/strong&gt;&lt;br&gt;
In a new terminal window: &lt;code&gt;docker pull stellar/soroban-rpc image&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4) Configure&lt;/strong&gt;&lt;br&gt;
The RPC image will need a stellar-core.toml file.&lt;br&gt;
The best practice is to craft one yourself, so you can evaluate which validators you want to include or exclude in your trust set.&lt;br&gt;
I use &lt;a href="https://gist.github.com/Row-Bear/952266e78ab8a5c623786fa4fa5feba2" rel="noopener noreferrer"&gt;this one&lt;/a&gt;.&lt;br&gt;
Place that file in the folder you made in step 2.&lt;br&gt;
For me, it's at /home/row-bear/soroban-rpc/stellar-core.toml&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5) Start it up!&lt;/strong&gt;&lt;br&gt;
Replace 'row-bear' in the below command with your username (or the whole path with whichever directory you made) and in a new terminal window, run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker run -p 8001:8001 -p 8000:8000 \
--name sorobanrpc \
-v /home/row-bear/soroban-rpc:/config stellar/soroban-rpc \
--captive-core-config-path="/config/stellar-core.toml" \
--captive-core-storage-path="/var/lib/stellar/captive-core" \
--stellar-core-binary-path="/usr/bin/stellar-core" \
--db-path="/var/lib/stellar/soroban-rpc-db.sqlite" \
--stellar-captive-core-http-port=11626 \
--network-passphrase="Public Global Stellar Network ; September 2015" \
--history-archive-urls="https://history.stellar.org/prd/core-live/core_live_001" \
--admin-endpoint="0.0.0.0:8001" \
--endpoint="0.0.0.0:8000"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(Edited to add the --name parameter, as suggested by Alex in the comments. Much easier than fiddling with the ID later on!)&lt;/p&gt;

&lt;p&gt;You may need to use &lt;code&gt;sudo&lt;/code&gt;, depending on your system config.&lt;br&gt;
If you want it to run on testnet or futurenet, adjust the passphrase in the command (and modify your stellar-core.toml !).&lt;/p&gt;

&lt;p&gt;It will start and start to sync. This can take up to an hour, for the first time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6) Find the container ID&lt;/strong&gt;&lt;br&gt;
To make sure you can stop and restart the image without doing the full sync again (and eating your disk space in the process!) we'll need to find the container id.&lt;br&gt;
In a new terminal, run &lt;code&gt;docker container ls -a&lt;/code&gt;&lt;br&gt;
Remember the -a flag. Else, it will only show running containers. One might assume the container is gone, and keep creating new ones.. 1/10 would not recommend.&lt;br&gt;
If it does happen to you: &lt;code&gt;docker container prune&lt;/code&gt; will remove the stopped containers&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%2Fin9ewlt71kcemyjiun8m.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%2Fin9ewlt71kcemyjiun8m.png" alt="Docker lists it's containers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note down the ID of the container that is running. For me, it's 929de777dddc.&lt;br&gt;
Alternatively, you can use the name we supplied when starting it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7) Stopping and starting it&lt;/strong&gt;&lt;br&gt;
In a terminal window, run &lt;br&gt;
&lt;code&gt;sudo docker stop &amp;lt;id&amp;gt;&lt;/code&gt; and then&lt;br&gt;
&lt;code&gt;sudo docker start &amp;lt;id&amp;gt;&lt;/code&gt;&lt;br&gt;
So, for me: &lt;code&gt;sudo docker stop 929de777dddc&lt;/code&gt;&lt;br&gt;
Or: &lt;code&gt;sudo docker stop sorobanrpc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8) Monitor the logs&lt;/strong&gt;&lt;br&gt;
After restarting, you won't see the log output in your terminal window. If you want that, run:&lt;br&gt;
&lt;code&gt;sudo docker logs -f sorobanrpc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9) Check the status&lt;/strong&gt;&lt;br&gt;
Again in a terminal, you can run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

curl --location 'http://localhost:8000' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc":"2.0",
"id":2,
"method":"getHealth"
}'


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If it's synced, you'll get: &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%2Fs4mc56bhf2fzjo1scj0s.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%2Fs4mc56bhf2fzjo1scj0s.png" alt="Soroban-RPC reports 'Healthy' status"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10) Now let's use it!&lt;/strong&gt;&lt;br&gt;
It's up and running, and hopefully synced.&lt;br&gt;
If you use soroban-cli, you can now add a network to use your RPC: &lt;code&gt;soroban network add local_rpc --rpc-url http://localhost:8000 --network-passphrase "Public Global Stellar Network ; September 2015"&lt;/code&gt;&lt;br&gt;
Then, in your next &lt;code&gt;soroban contract invoke&lt;/code&gt;, you can use your very own RPC with &lt;code&gt;--network local_rpc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you have any practical tips for others, please share them in the comments :-)&lt;/p&gt;

&lt;p&gt;As always, join the &lt;a href="https://discord.gg/stellardev" rel="noopener noreferrer"&gt;Stellar Dev&lt;/a&gt; discord to discuss the technical stuff, and the &lt;a href="https://discord.gg/stellar-global-761985725453303838" rel="noopener noreferrer"&gt;Stellar Global&lt;/a&gt; discord for everything Stellar.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>stellar</category>
      <category>soroban</category>
    </item>
    <item>
      <title>Soroban Reverse Auction</title>
      <dc:creator>Row-Bear</dc:creator>
      <pubDate>Fri, 22 Dec 2023 22:42:52 +0000</pubDate>
      <link>https://dev.to/row-bear/soroban-reverse-auction-203k</link>
      <guid>https://dev.to/row-bear/soroban-reverse-auction-203k</guid>
      <description>&lt;p&gt;The past week, I have been tinkering with a new Soroban project.&lt;br&gt;
It's been quite a learning experience, both in Soroban and in frontend.&lt;br&gt;
I'll talk you through how I built my app, and share some of my lessons and thoughts.&lt;/p&gt;

&lt;p&gt;The code (and a large readme) can be found on &lt;a href="https://github.com/Row-Bear/soroban_reverse_auction"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reverse Dutch Auction&lt;/strong&gt;&lt;br&gt;
What I've made is a Reverse Dutch Auction.&lt;br&gt;
I am still missing a few cards from my RPCiege collection, so I want to find a way to acquire the missing ones.&lt;/p&gt;

&lt;p&gt;With a Reverse Auction, a buyer can:&lt;br&gt;
-Set a (low) starting price&lt;br&gt;
-Define how much and how often the price will increase over time&lt;/p&gt;

&lt;p&gt;A seller can then interact with the auction, to sell their card/asset when the price is high enough for them.&lt;br&gt;
However, if they wait too long, someone else may take the offer!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Soroban&lt;/strong&gt;&lt;br&gt;
To set this up in Soroban, I've made a contract with 5 functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;setup_auction&lt;/strong&gt;&lt;br&gt;
The first function is for setting up the auction.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FbiuLTEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lyho11tc90adzz0xq46b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FbiuLTEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lyho11tc90adzz0xq46b.png" alt="Image description" width="489" height="202"&gt;&lt;/a&gt;&lt;br&gt;
It takes in some arguments, and returns a Status (or an error)&lt;br&gt;
The arguments define what's being bought and sold, and how the price behaves.&lt;br&gt;
For example: I (host) will buy 1 RPCiege card (auction_asset) and pay in XLM (counter_asset). My starting bid will be 20 XLM (starting_bid), and I will increase it with 10 XLM (bid_incr_amount) every 17000 ledgers (about 1x per day) (bid_incr_interval).&lt;br&gt;
I will increase it 10 times (bid_incr_times).&lt;/p&gt;

&lt;p&gt;That means I will pay at least 20 XLM, up to 120 XLM after 10 days.&lt;/p&gt;

&lt;p&gt;The function starts out with some sanity checks:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T3BLAHG1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sv8ubj3gypiv1gzjv4k7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T3BLAHG1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sv8ubj3gypiv1gzjv4k7.png" alt="Image description" width="800" height="275"&gt;&lt;/a&gt;&lt;br&gt;
The host must be authorised: in effect, that means the address/account we provide must sign the transaction. After all, they will provide the 'money' to buy the asset with.&lt;/p&gt;

&lt;p&gt;Then we check if the contract was already initialised/started.&lt;br&gt;
We do that by seeing if there is already a Datakey for State set in storage.&lt;br&gt;
If there is, we return an Status::AuctionAlreadyInitialised.&lt;br&gt;
This lets users know what's up, without a full error.&lt;/p&gt;

&lt;p&gt;Then, we check if the bid is actually positive. We don't want any weird negative prices being paid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J-0pXYFe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8iczw8v0sobq7mrz1dx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J-0pXYFe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8iczw8v0sobq7mrz1dx.png" alt="Image description" width="718" height="90"&gt;&lt;/a&gt;&lt;br&gt;
Next, we ensure that the contract will have it's rent paid for the duration of the auction.&lt;br&gt;
In Soroban, entries need to pay rent to stay on the ledger.&lt;br&gt;
This avoids bloating the ledger with old and irrelevant data.&lt;br&gt;
In this case, I've put all the contract's data in the &lt;code&gt;.instance()&lt;/code&gt; storage.&lt;br&gt;
That means any bump/extend_ttl operation will pay the rent for our data and the contract itself.&lt;/p&gt;

&lt;p&gt;Then, we transfer the counter_asset from the buyer to the contract:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J2yRL1_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u4z2gfeeiwoha0meboxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J2yRL1_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u4z2gfeeiwoha0meboxc.png" alt="Image description" width="800" height="192"&gt;&lt;/a&gt;&lt;br&gt;
That means the contract acts as broker, and the funds are guaranteed to be available for a seller.&lt;br&gt;
Note that we use the &lt;code&gt;try_transfer&lt;/code&gt; method. If it were to fail, we can catch that error.&lt;/p&gt;

&lt;p&gt;Then, we save all the information we have received and calculated.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LP_5LBk---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ekw9t3vzhae41xyv56wc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LP_5LBk---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ekw9t3vzhae41xyv56wc.png" alt="Image description" width="729" height="404"&gt;&lt;/a&gt;&lt;br&gt;
I've made a custom struct AuctionData to hold all that information.&lt;br&gt;
That makes it easier to pass that object around, for example into and out of storage. It's probably not the most efficient way though.&lt;br&gt;
We store that AuctionData struct into the &lt;code&gt;instance()&lt;/code&gt; storage.&lt;br&gt;
We also store a datakey to show that the auction is now Running.&lt;/p&gt;

&lt;p&gt;Next, we emit an event.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h6pIszpS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyo7du6jvy78uxkphm5y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h6pIszpS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyo7du6jvy78uxkphm5y.png" alt="Image description" width="800" height="51"&gt;&lt;/a&gt;&lt;br&gt;
Events can be monitored via the Soroban RPC servers.&lt;br&gt;
We emit all information needed to calculate how the bid changes over time, so that sellers don't need to invoke the contract.&lt;/p&gt;

&lt;p&gt;Then finally, we return a Status to the user, to let them know the auction has started.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xuy5mixM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qdv9n5tvn6mke0c02pec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xuy5mixM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qdv9n5tvn6mke0c02pec.png" alt="Image description" width="368" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since a Soroban contract/transaction will execute atomically, any errors will result in the whole function failing/reverting.&lt;br&gt;
No need to worry whether any funds were transferred if the contract fails to save it's data. It's all or nothing!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;get_bid_info&lt;/strong&gt;&lt;br&gt;
The second function in the auction contract is get_bid_info().&lt;br&gt;
This one doesn't take any parameters!&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8bwbI_ZR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4j3uccx3mxaqiup1b135.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8bwbI_ZR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4j3uccx3mxaqiup1b135.png" alt="Image description" width="800" height="42"&gt;&lt;/a&gt;&lt;br&gt;
It does return another custom struct: BidInfo.&lt;br&gt;
This functions does the basic arthritics to determine what the price is at this moment.&lt;br&gt;
The price increase happens not strictly on a time base, but on the closing of ledgers. A ledger will generally close every 5 or 6 seconds.&lt;/p&gt;

&lt;p&gt;First, we do a bit of state checking:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9rgbXLQl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pc1gmqpi4v0dosqcj5la.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9rgbXLQl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pc1gmqpi4v0dosqcj5la.png" alt="Image description" width="800" height="229"&gt;&lt;/a&gt;&lt;br&gt;
If there is no State datakey set, the auction has not been setup, so we throw an error.&lt;br&gt;
And similar, if the State is anything other than Running, we also throw an error.&lt;/p&gt;

&lt;p&gt;Then, we ask the Soroban env what the current ledger is. We also retrieve our AuctionData from storage:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FLo2fw71--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/srpcmqtijeszeab6z6ek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FLo2fw71--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/srpcmqtijeszeab6z6ek.png" alt="Image description" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After some basic calculations, we stumble on some mildly interesting (to me) Rust.&lt;br&gt;
I want to have two different flows, based on if the price has reached its maximum or not.&lt;br&gt;
But if we declare the variables inside the scope of the if, we can't use them outside it.&lt;br&gt;
So, we declare (but don't assign values to) the variables first.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k2AQ5waw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1uvz30j63nyqp6w9d79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k2AQ5waw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1uvz30j63nyqp6w9d79.png" alt="Image description" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, we go on to calculate what the price is now, when it will increase, and when it will reach the maximum:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n1rhrggn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y7mmma363c9g3v9wezoy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n1rhrggn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y7mmma363c9g3v9wezoy.png" alt="Image description" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we create a BidInfo struct with all this information, and return that.&lt;br&gt;
We also emit an event, for anyone interested. It saves them a contract invoke.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B8wFOZpT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adhhi3bqwamuz31xolel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B8wFOZpT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adhhi3bqwamuz31xolel.png" alt="Image description" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sell_asset&lt;/strong&gt;&lt;br&gt;
Next up is the function to be used by a seller.&lt;br&gt;
They call the sell_asset function, which requires their address as parameter:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tBuTa3tB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwwcmc940hdmzjyei7x4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tBuTa3tB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwwcmc940hdmzjyei7x4.png" alt="Image description" width="800" height="67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then make sure the state of the auction is right, and that the seller is authorised (has signed the transaction):&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OCRn-0nr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jaw3zbe2b4newzshmhag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OCRn-0nr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jaw3zbe2b4newzshmhag.png" alt="Image description" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To proceed with the sale, we retrieve the auction data, but we also need to know what the current bid is.&lt;br&gt;
Good thing we already wrote a function to get that bid information!&lt;br&gt;
We call the contracts own get_bid_info() function with &lt;code&gt;Self::get_bid_info(env.clone()).unwrap().current_bid;&lt;/code&gt;&lt;br&gt;
We pass it a clone of the current env, then take the current bid value out.&lt;br&gt;
It's not the most efficient way. We spend some cycles to calculate things we don't need, we only use the &lt;code&gt;.current_bid&lt;/code&gt;&lt;br&gt;
But, it saves me from writing that specific part of code.&lt;br&gt;
And this function will only rarely be used: once per auction. So, I accept that overhead.&lt;/p&gt;

&lt;p&gt;We go on to transfer the funds:&lt;br&gt;
The seller sends 1 stroop of the NFT asset to to contract, and the contract returns the current price.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PZZWA3bF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xg0s0iqbx5j5nu4on3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PZZWA3bF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xg0s0iqbx5j5nu4on3b.png" alt="Image description" width="800" height="243"&gt;&lt;/a&gt;&lt;br&gt;
Again, this happens all at once, or not at all.&lt;br&gt;
The way Soroban is built ensures that execution can not stop after the first transfer. If the second transfer fails, none of the operations take place.&lt;/p&gt;

&lt;p&gt;We emit an event with the sell price, set the auction state to Fulfilled and return a Status message to the seller, and that's it for this function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;close_auction&lt;/strong&gt;&lt;br&gt;
The organiser of the auction (the buyer) has the option to close the auction down again.&lt;br&gt;
They can do this before or after a seller sells their asset.&lt;br&gt;
If it's done before, the auction is Aborted, the funds return to the buyer and the auction becomes inactive.&lt;br&gt;
If it's done after the sale took place, it goes slightly different.&lt;br&gt;
The NFT is transferred to the buyer, along with any left-over funds.&lt;br&gt;
Then, the auction is set to Closed&lt;/p&gt;

&lt;p&gt;We start again with some checks on the state of the auction:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--noY0w3-F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l40g9kbkalnz6gghjvpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--noY0w3-F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l40g9kbkalnz6gghjvpc.png" alt="Image description" width="800" height="235"&gt;&lt;/a&gt;&lt;br&gt;
Then, we load the auction data and make sure the host/organiser is signing the transaction:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R4fiSgBT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phq27o0h2yevq9jqba5b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R4fiSgBT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phq27o0h2yevq9jqba5b.png" alt="Image description" width="800" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the auction is running, we return all the funds to the buyer, before setting the status to Aborted.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--la53z8eU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ecfyvc100pe74gpx6sqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--la53z8eU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ecfyvc100pe74gpx6sqn.png" alt="Image description" width="800" height="169"&gt;&lt;/a&gt;&lt;br&gt;
Notice how we get the balance: we cross contract call the contract of the funds, and ask it for the balance of our contract.&lt;br&gt;
It's possible to avoid this by keeping track of the balance ourselves.&lt;br&gt;
But, that also opens up chances for errors and bugs.&lt;br&gt;
Again, I'll take that overhead cost and use this method of getting the balance.&lt;/p&gt;

&lt;p&gt;If the auction was Fulfilled, we use two transfers.&lt;br&gt;
One for the NFT, and one for any remaining funds (if any, we check to see if that is &amp;gt; 0).&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rTqXjX8z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n22ulko2hd64o25kf6ss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rTqXjX8z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n22ulko2hd64o25kf6ss.png" alt="Image description" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All that remains is to set the state to Closed and return the buyer the good news:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jc5riwCf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/juyah1zzafjxmeijddun.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jc5riwCf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/juyah1zzafjxmeijddun.png" alt="Image description" width="737" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;reset_auction&lt;/strong&gt;&lt;br&gt;
For demonstration purposes, I've added a reset function to the auction.&lt;br&gt;
If it has been closed, we remove the storage information.&lt;br&gt;
Effectively, this means the auction contract can be reset again.&lt;br&gt;
For here, the interesting part is to show how we clear the storage:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Izbpg6a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmgt7s9xjm5rgvro412d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Izbpg6a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmgt7s9xjm5rgvro412d.png" alt="Image description" width="746" height="126"&gt;&lt;/a&gt;&lt;br&gt;
We only have the two datakeys, one for State and one for AuctionData.&lt;br&gt;
We simply remove them.&lt;br&gt;
Note though, the information can still be found by people going back through ledger histories. So don't put any secrets in a public ledger, thinking you can remove them later :)&lt;/p&gt;

&lt;p&gt;That concludes the Rust code used in the Soroban Reverse Auction.&lt;br&gt;
The readme on &lt;a href="https://github.com/Row-Bear/soroban_reverse_auction"&gt;github&lt;/a&gt; has a detailed step-by-step guide on how to compile(build), deploy and interact with this contract yourself.&lt;br&gt;
It also has files and instructions for hosting a local copy of the interactive demo, so you can experiment with your own auction contract.&lt;/p&gt;

&lt;p&gt;I'll spare you the details of the many hours spent getting that demo working. I'll summarize:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rwYQ6o7x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2u4x0x4xx9jycbfpvwg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rwYQ6o7x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2u4x0x4xx9jycbfpvwg6.png" alt="Image description" width="792" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>soroban</category>
      <category>stellar</category>
    </item>
    <item>
      <title>RPCIEGE - Skirmish 10</title>
      <dc:creator>Row-Bear</dc:creator>
      <pubDate>Fri, 06 Oct 2023 14:46:34 +0000</pubDate>
      <link>https://dev.to/row-bear/rpciege-skirmish-10-3in7</link>
      <guid>https://dev.to/row-bear/rpciege-skirmish-10-3in7</guid>
      <description>&lt;p&gt;And we're already moving on to Skirmish 10 of the &lt;a href="https://rpciege.com"&gt;RPCiege&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Have a look at the &lt;a href="https://rpciege.com/booklet"&gt;booklet&lt;/a&gt; for the exact details of the mission. Here's my summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have been given a game contract, and its code&lt;/li&gt;
&lt;li&gt;To complete the skirmish, we have to guess an "unpredictable" number, and invoke the contract with that number as parameter.&lt;/li&gt;
&lt;li&gt;Since we have the code, the number is not exactly unpredictable. We just have to extract it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a small diversion, you can try to make a manual guess.&lt;br&gt;
After all, you have about 1 in 4 billion chance to guess correct.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z_a0708k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2sgmlvqtzk67i8qcuymu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z_a0708k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2sgmlvqtzk67i8qcuymu.png" alt="Image description" width="800" height="298"&gt;&lt;/a&gt;&lt;br&gt;
Okay, that's not going to work. We'll have to look at the contracts code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5V5iXzV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9wv7jait0k7xjkhsf96n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5V5iXzV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9wv7jait0k7xjkhsf96n.png" alt="Image description" width="698" height="856"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The magic happens in this part of the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let state = u64::MIN
    .wrapping_add(env.ledger().timestamp())
    .wrapping_add(env.ledger().sequence() as u64);
let mut rng = SmallRng::seed_from_u64(state);

if guess != rng.gen_range(0..1_000_000_000) {
    return Err(Error::WrongGuess);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see that a random number is derived from the ledger timestamp and ledger sequence.&lt;br&gt;
Then, our guess is compared to that number.&lt;br&gt;
Back in Skirmish 6 there was a similar situation. Then, there was some room to calculate the number, then quickly invoke the game contract.&lt;/p&gt;

&lt;p&gt;Now, we don't have that option. We have to make the guess in the same ledger as the calculation happens.&lt;br&gt;
Luckily, cross-contract calls come to the rescue.&lt;br&gt;
If your contract calls another contract, that will happen in the same ledger. &lt;br&gt;
So, we can make our own contract and use the same logic to calculate the guess. Then call the game contract from our own contract, and since it happens in the same ledger, the timestamp and sequence will be the same.&lt;/p&gt;

&lt;p&gt;The Soroban Examples include a cross-contract &lt;a href="https://github.com/stellar/soroban-examples/tree/main/cross_contract"&gt;example&lt;/a&gt;, which I've used as the basis for the solution.&lt;br&gt;
Like the in previous skirmish, we can use &lt;code&gt;soroban contract fetch&lt;/code&gt; in soroban-cli to retreive the game contract.&lt;/p&gt;

&lt;p&gt;Then, it can be imported in your own contract code, so you can interact with it.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SYZl_gMx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/183hjmjq50x75w4kqwsd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SYZl_gMx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/183hjmjq50x75w4kqwsd.png" alt="Image description" width="467" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm not going to give out the full solution, but I'll share my &lt;code&gt;wrong_guess&lt;/code&gt; function.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CfF7LtHl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwad4nq996vo6dw9ofeg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CfF7LtHl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwad4nq996vo6dw9ofeg.png" alt="Image description" width="800" height="130"&gt;&lt;/a&gt;&lt;br&gt;
It sets my guess to 1, then calls the target contract with it.&lt;br&gt;
Notice how I've put a &lt;code&gt;target: Address&lt;/code&gt; parameter in the contract.&lt;br&gt;
When invoking my contract, I have to put the game contract in as argument. That way, my contract knows which contract to shoot the &lt;code&gt;guess&lt;/code&gt; at.&lt;/p&gt;

&lt;p&gt;Now it's up to you to replace &lt;code&gt;let guess: u32 = 1;&lt;/code&gt; with the calculation for the correct number. With the information above and in the booklet, you should be able to :-)&lt;br&gt;
And if not, leave a comment, or even better, hop in the &lt;a href="https://discord.gg/6ZCcYqbC96"&gt;Stellar Dev Discord&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Happy cieging!&lt;/p&gt;

&lt;p&gt;Row-Bear&lt;/p&gt;

&lt;p&gt;PS: If you get stuck, chances are you'll have to add a dependency or two to your Cargo.toml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[dependencies]
soroban-sdk = "20.0.0-rc2"
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }
getrandom = { version = "0.2", features = ["js"] }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>stellar</category>
      <category>soroban</category>
      <category>rust</category>
    </item>
    <item>
      <title>RPCIEGE - Skirmish 9</title>
      <dc:creator>Row-Bear</dc:creator>
      <pubDate>Thu, 05 Oct 2023 21:31:07 +0000</pubDate>
      <link>https://dev.to/row-bear/rpciege-skirmish-9-3jdm</link>
      <guid>https://dev.to/row-bear/rpciege-skirmish-9-3jdm</guid>
      <description>&lt;p&gt;It's time to have a go at Skirmish 9 of the Soroban &lt;a href="https://www.rpciege.com"&gt;RPCiege&lt;/a&gt;!&lt;br&gt;
For a short recap on what RPCiege is, see my &lt;a href="https://dev.to/row-bear/rpciege-skirmish-8-349g"&gt;previous&lt;/a&gt; post.&lt;/p&gt;

&lt;p&gt;Skirmish 9 is about &lt;a href="https://soroban.stellar.org/docs/basic-tutorials/upgrading-contracts"&gt;upgrading&lt;/a&gt; our contract.&lt;/p&gt;

&lt;p&gt;Our mission:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9STuCS9W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/891pzml3wncfl28qz8ah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9STuCS9W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/891pzml3wncfl28qz8ah.png" alt="Image description" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're pointed to the game contract, which is a deployer: it will deploy a contract for us to work with.&lt;br&gt;
Let's call it, then see what we have to work with.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1wc70oEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pblanct38t1eoa7ssyda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1wc70oEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pblanct38t1eoa7ssyda.png" alt="Image description" width="800" height="27"&gt;&lt;/a&gt;&lt;br&gt;
(You'll notice I took the lazy route with the salt again: copied the example value and adjusted it slightly. You'll have to generate your own unique one)&lt;br&gt;
A little spoiler: after you've used the &lt;code&gt;deploy&lt;/code&gt; function, you don't need to do anything with the deployer contract anymore.&lt;/p&gt;

&lt;p&gt;Now that we have a contract, let's see what it does.&lt;br&gt;
Last time we used &lt;code&gt;-h&lt;/code&gt; to let soroban-cli show us information about the functions. This time, we'll use &lt;code&gt;fetch&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soroban contract fetch --network rpciege --id &amp;lt;your_contract_id_here&amp;gt; -o skirmish_9.wasm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets soroban-sli download the contract (through the specified RPC server) and store it in the specified &lt;code&gt;-o&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Then, we can inspect it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soroban contract inspect --wasm skirmish_9.wasm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FLEIpmrA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeh6p9o8e6bfq2fx41cz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FLEIpmrA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeh6p9o8e6bfq2fx41cz.png" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's not as pretty as &lt;code&gt;-h&lt;/code&gt;, but it does show all functions and their parameters at once.&lt;br&gt;
Here we can see that the &lt;code&gt;run&lt;/code&gt; function doesn't take any parameters, and that the &lt;code&gt;upgrade_contract&lt;/code&gt; function takes one parameter, named &lt;code&gt;hash&lt;/code&gt;. It takes a value of the types BytesN. &lt;br&gt;
Luckily, soroban-cli will handle the conversion from String to BytesN for us.&lt;/p&gt;

&lt;p&gt;If you've completed any of the other skirmishes, you may notice that there's no parameter for &lt;code&gt;_nft_dest&lt;/code&gt;.&lt;br&gt;
That means we can't claim those slick trading cards!&lt;/p&gt;

&lt;p&gt;But you've probably connected the dots by now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Contract with missing function parameter&lt;/li&gt;
&lt;li&gt;Upgradable contract&lt;/li&gt;
&lt;li&gt;??&lt;/li&gt;
&lt;li&gt;Profit!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Yes, you need to write a new contract now.&lt;br&gt;
I'm not going to show the exact Rust code to use.&lt;br&gt;
You could write one from scratch, or modify one you have. I don't know if it &lt;em&gt;must&lt;/em&gt; have a function called &lt;code&gt;run&lt;/code&gt;, but I named my function that.&lt;br&gt;
I know it doesn't &lt;em&gt;need&lt;/em&gt; to do anything, but you can be creative.&lt;br&gt;
Just make sure it also has a parameter &lt;code&gt;_nft_dest&lt;/code&gt;.&lt;br&gt;
Now &lt;code&gt;soroban contract build&lt;/code&gt; it, and let's get to upgrading.&lt;/p&gt;

&lt;p&gt;To upgrade a contract, three things are needed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An existing contract with code to upgrade itself (already provided)&lt;/li&gt;
&lt;li&gt;A new wasm thats been installed on the ledger. (It doesn't have to be &lt;em&gt;deployed&lt;/em&gt; though)&lt;/li&gt;
&lt;li&gt;A hash to identify which wasm you want to use.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To install the wasm of your new upgrade, you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soroban contract install --network rpciege --source &amp;lt;your identity&amp;gt; --wasm &amp;lt;path_to_your_wasm&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;install&lt;/code&gt; command will return you the hash of your installed contract.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yxlDPdUU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7s3vuzt6ixk48vqdcfrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yxlDPdUU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7s3vuzt6ixk48vqdcfrg.png" alt="Image description" width="800" height="19"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;So, we finally reach the conclusion:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You have a target contract, with an &lt;code&gt;upgrade_contract&lt;/code&gt; function that takes a &lt;code&gt;--hash&lt;/code&gt; argument.&lt;/li&gt;
&lt;li&gt;You also have your own contract, installed, and its hash&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Happy cieging!&lt;/p&gt;

</description>
      <category>stellar</category>
      <category>soroban</category>
      <category>rust</category>
    </item>
    <item>
      <title>RPCIEGE - Skirmish 8</title>
      <dc:creator>Row-Bear</dc:creator>
      <pubDate>Mon, 02 Oct 2023 21:51:25 +0000</pubDate>
      <link>https://dev.to/row-bear/rpciege-skirmish-8-349g</link>
      <guid>https://dev.to/row-bear/rpciege-skirmish-8-349g</guid>
      <description>&lt;p&gt;So, I'll give this a try: my writeup of Skirmish 8 in the RPCiege.&lt;/p&gt;

&lt;p&gt;On the off-chance someone reads this without knowing what that is, here's a brief summary.&lt;br&gt;
On &lt;a href="http://www.rpciege.com"&gt;www.rpciege.com&lt;/a&gt; there is a series of coding games/challenges on the Soroban smart contract platform. It's currently in a testing stage, aiming to go live end of 2023.&lt;br&gt;
RPCiege (and its predecessor Stellar Quest) will let you get familiar with the language and platform, and gives you kick-ass collectible cards to boot.&lt;/p&gt;

&lt;p&gt;So, on to Skirmish 8. I'll give a brief writeup of how I attempted to tackle this, and give some hints on how you can solve it.&lt;br&gt;
No full solution, but enough to get you going.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aImqdfsN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ibiws3tcm64wgie7g5ex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aImqdfsN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ibiws3tcm64wgie7g5ex.png" alt="Image description" width="800" height="313"&gt;&lt;/a&gt;&lt;br&gt;
The booklet gives you your mission, and a helpful link to documentation. However, with the latest preview release, you don't actually need the linked docs!&lt;/p&gt;

&lt;p&gt;To get started, we have a contract. I always start by pointing my friend &lt;code&gt;-h&lt;/code&gt; at the contract.&lt;br&gt;
It will tell you what functions the contract has, which is always a good start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7H045j2W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w33by8ikrmseary3uw7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7H045j2W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w33by8ikrmseary3uw7r.png" alt="Image description" width="773" height="188"&gt;&lt;/a&gt;&lt;br&gt;
And you can also use &lt;code&gt;-h&lt;/code&gt; on those functions itself, to get information about what parameters the function expects. Let's have a look:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7AzgGVpQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7tg8wqzo2tssdifx261.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7AzgGVpQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7tg8wqzo2tssdifx261.png" alt="Image description" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;_nft_dest&lt;/code&gt; is optional, so I'll skip it. I already have the cards and my spot on the leaderboard :)&lt;br&gt;
For source, I'll just use my configured identity.&lt;br&gt;
But notice how &lt;code&gt;--answer&lt;/code&gt; expects an &lt;code&gt;&amp;lt;Array&amp;lt;u32&amp;gt;&amp;gt;&lt;/code&gt;? And it even gives an example of such an array.&lt;br&gt;
I took the lazy route, and just tried it with that example. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I8RrGE2k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23dejklbkyh1pemucngr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I8RrGE2k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23dejklbkyh1pemucngr.png" alt="Image description" width="800" height="635"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the current release, we see a lot of diagnostic events, along with the return of the function.&lt;br&gt;
So, a few things to unwrap here:&lt;br&gt;
1) I just passed [1] as answer&lt;br&gt;
2) The diagnostics return a vector: [0, 4508]&lt;br&gt;
3) We died.. that's usually not good.&lt;/p&gt;

&lt;p&gt;So, we didn't solve this yet. But did you expect that, with an answer of &lt;code&gt;[1]&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;I'll give a hint here: the 0 in that vector is the number of positions we got correct.&lt;br&gt;
And we got some information: the number 4508.&lt;br&gt;
So, let's try &lt;code&gt;--answer&lt;/code&gt; with that as input:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---yL7Wfzs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yoi0yrq6se5g9t2ry6aa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---yL7Wfzs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yoi0yrq6se5g9t2ry6aa.png" alt="Image description" width="800" height="27"&gt;&lt;/a&gt;&lt;br&gt;
And now we starved.. so something has changed.&lt;br&gt;
And notice that we did not get a screen full of diagnostic info.&lt;br&gt;
So, when we &lt;code&gt;Died&lt;/code&gt;, the contract emitted a diagnostic event, and when we &lt;code&gt;Starved&lt;/code&gt;, it did not.&lt;/p&gt;

&lt;p&gt;But that also leaves us stuck for a bit.&lt;br&gt;
Any random input leads to &lt;code&gt;Died&lt;/code&gt;, except for that number we got returned earlier.&lt;br&gt;
But &lt;code&gt;--answer&lt;/code&gt; takes a vector! So we can input more numbers.&lt;br&gt;
After some fiddling around, I decided to add my random guess after the 4508:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NaH_Ndth--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l3lj95hsmgy27d850tul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NaH_Ndth--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l3lj95hsmgy27d850tul.png" alt="Image description" width="788" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We still &lt;code&gt;Died&lt;/code&gt;, but have a different diagnostic event.&lt;br&gt;
So we're getting somewhere. 1 correct position, and the number 4509.&lt;/p&gt;

&lt;p&gt;That should be enough to get you going.&lt;br&gt;
For reference, there is another way to get the diagnostic events. &lt;br&gt;
Soroban-cli has a command for it. You can point it at a contract, and it will return (recent) events emitted by it. &lt;br&gt;
The part that always trips me up is the &lt;code&gt;--start-ledger&lt;/code&gt;&lt;br&gt;
I end up getting that from Stellar Laboratory. If there's a better way to find out what the latest ledger is, let me know!&lt;/p&gt;

&lt;p&gt;Row-Bear&lt;/p&gt;

&lt;p&gt;PS: After you have some parts of your sequence right, you might be able to predict the next parts..&lt;br&gt;
If you're smarter than me, that may take you less time than uncovering them one by one.&lt;/p&gt;

&lt;p&gt;PPS: Other than &lt;code&gt;Died&lt;/code&gt; or &lt;code&gt;Starved&lt;/code&gt;, you can also get &lt;code&gt;Exploded&lt;/code&gt;. Bonus points if you reach that :)&lt;/p&gt;

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