You know the "Fibonacci Sequence" right? I'm not getting all weird here. It's not magical, or supernatural, or anything like that. I just like using it as a practice problem when I'm trying to learn a programming language, or some other technology. Anyway, the sequence goes like this:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
That's just the first 10 digits, but you probably get the idea. Each number is
derived by adding the previous two numbers. If you're curious, here's a small
python script I wrote to give you n
digits of the sequence.
#!/usr/bin/env python3
import sys
"""Returns `n` Digits of the Fibonacci Sequence.
Run this from your shell like `./fibonacci.py 25`
"""
# The sequence always starts with [0, 1], so we'll start there
f_seq = [ 0, 1 ]
while len(f_seq) <= int(sys.argv[1]):
f_seq.append(f_seq[-1] + f_seq[-2])
print(f_seq)
I'm sure it's bad, gimme a break. I wrote it (*checks notes*) ALMOST 10 YEARS AGO!!!??? Oof, I'm old.
Anyway, enough with the math lesson. Let's move on to what I have here. But first, a brief message from our legal department:
Disclaimer: This Fibonacci Faucet is a unique, interesting, and terrible-in-practice scheme for distributing a smart asset on Soroban. This is (hopefully obviously) not meant to be developed or deployed in the real world, but rather is a thought experiment. It's meant as a tangible, "graspable" concept to use as I familiarize myself with Soroban and Rust. Don't do this in real life. No, seriously. Just. Don't.
So, the basic flow of what happens in this (once the contract has been initialized, more on that later):
- A user invokes the
signup
function to add their address to the list of members. - The contract will check a few things:
- the FibFaucet is open,
- there is room on the list,
- the invoking
Address
is not already a member, - the invoking
Address
is not theAdmin
user, and - the
signup
function was invoked by anAccount
rather than aContract
, sorry no cross-contract calls for this function.
- If all that checks out, the
Address
of the invoker will be added to theSignups
vec, as well as stored in aMember(Address)
data key with the calculated payout. - When the
Admin
user chooses to do so, they can invoke thedisburse
function to iterate through theSignups
vec, and mint the required number of tokens to each member.
As long as the contract has not already been initialized, any Account
invoker
(again, no cross-contract calls in this part) can invoke the init
function
which then deploys a token contract, sets the Admin
user to be the invoker,
and sets up some CONTRACT_DATA
placeholders.
The FibFaucet contract is set as the Admin
for this token, allowing us to
mint
those tokens by using simple invoker()
authentication. The token
contract ID is salted using the first 11 digits of the Fibonacci Sequence, as
Bytes
.
Here's a grab bag of other things that are running through my mind as I put this together.
- Ownership in Rust continues to confuse me. Have I used the
&
borrower thing in the right place(s)? Have I used theclone()
method inefficiently (probably)? Are there any general rules/conventions to guide the use of those kinds of things (again, probably)? - Literally, this is just giving tokens to anybody who asks for them. Potentially lots of them, too. It would be trivial for someone to use a second account to game the system and get more of the token. In this experiment, I don't really care about that, tbh.
- As for performance, is there any benefit/detriment to abstracting so many
data().set/get()
calls into different functions like I've done here? - I'd be interested to run some experiments on pricing and such for how this contract runs/lives on-chain. Of course, that kind of stuff is still being determined, but still could be interesting.
As far as I'm concerned, this is still a bit of a work-in-progress. Some ideas I'm considering for implementation are included here:
- Some kind of "token admin" function where the
admin
user can submit functions and arguments that will then be passed on to the token contract so it can be interfaced with and managed like any other Soroban token. - MOAR TESTS!! Or, rather, ANY TESTS!! Also, I want to figure out the
difference between
test.rs
andtestutils.rs
, since I see those two files a lot in these projects. - Improved returns on successful invokation. Something more meaningful than
null
would be probably be helpful to a user. - Some way to display the chain (in order) of everyone who's been a part of
the sequence.
- Maybe it would be interesteing to provide the transaction hash or something from when they signed up and/or when they were paid.
- An "automatic" mode. The user signs up and is paid right then. This could
be turned on/off by the admin account at
init
time, orreset
time, or any time I s'pose. - I thought about some kind of "shuffle" system. Maybe the signups are
locked in when someone invokes the
signup
function, but when thedisburse
function is invoked by an admin, the signups are shuffled and the payments are decided then?