Skip to main content

Ecosystem Currency - Getting started

· 5 min read
David Atkinson

Let’s start with something basic. The first game currency we want to build has just a max supply. We could write that without even using the expression engine.

Max supply currency without an expression

Design Fixed supply Mint immediately Single wallet

We enter the details below in configuration and leave the expression empty

Link: https://toy-token.on.fleek.co/ Name: Symbol: Address to immediately mint token for: Amount of the token to immediately mint:

Max supply currency with an expression

Or you could do this with an expression

Design Supply amount Mint immediately Single wallet

Then create your expression

Link: https://toy-token.on.fleek.co/
Expression: eager_if(less_than(ierc20_total_supply(this_address()), 100000), 100000, 0)

You can see below an expression I've deployed using the code above:

https://toy-token.on.fleek.co/#/token/0x046829F2EFCBa6398995F428Df978AD490DF4630

You can now go ahead and creat your own. You can change the supply amount and amount you can mint (both set at 100,000 at the moment).

Max supply currency released daily linear single wallet

Design Fixed supply Mint over period of time Mint shared between verified wallets Mint amount based on difference between available amount and previous claim Minted wallets must belong to relevant list, membership, tier

First I have to set up a list or tier or membership.

To do that I can go to https://toolkit.rainprotocol.xyz/ and experiment with various tiers. I could use ERC20 balance, ERC20 transfer, ERC721 balance, Verify or Combine Tiers.

What is a Tier?

ITier is a simple interface that contracts can implement to provide membership lists for other contracts. A "membership" can represent many things Exclusive access, participation in some event or process, KYC completion, combination of sub-memberships. Read more here - https://docs.rainprotocol.xyz/developer-tools/smart-contracts/tier/ITier

In this case we want to limit activity to all validated wallets. So we load the Rain Protocol Toolkit and create a Verify Tier

https://toolkit.rainprotocol.xyz/#/verify/deploy

Here is the verify I've created

Verify: 0xDE5b95Dd290cEE7bfddd5c9eFAC7fD042a0eDea5

We then manage the Verify to add / remove validated wallets.

Administering the verify: https://toolkit.rainprotocol.xyz/#/verify/administer/0xDE5b95Dd290cEE7bfddd5c9eFAC7fD042a0eDea5

And then we create a VerifyTier from the Verify contract.

VerifyTier: 0x38ecA941B8c139C2Ed995Be5CACdD9c855c1eC28

The VerifyTier simply takes the Verify contracts and makes the interface tier consistent.

Writing the expression

    eager_if(
iszero(report(verifyTierAddress context(0)))
0
sub(
min(mul(sub(current-timestamp() deployTimestamp) amountChangePerTimestampPerWallet)
div(1000000000 numberOfVerifiedWallets))
min(mul(saturating-sub(single-report(this-address() context(0) 1) deployTimestamp)
amountChangePerTimestampPerWallet) div(1000000000 numberOfVerifiedWallets))
)
)

Variables

verifyTierAddress = 0x38ecA941B8c139C2Ed995Be5CACdD9c855c1eC28 in my example; or the address of the VerifyTier you've created

MaxUint256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; this checks whether the wallet is part of the VerifyTier

current-timestamp = Creating a timestamp

deployTimestamp = Creating the deploy timestamp

amountChangePerTimestampPerWallet = We get the current timestamp and subtract it by deploy timestamp , which gives us how many timestamp has passed since deploy time, and then multuply it by that amountChange to get how much token should be released at this point in time

numberOfVerifiedWallets = Number of wallets that are eligible to mint

Explanations

    iszero(report(verifyTierAddress context(0)))

Requires the recipient addresses be approved in a verify tier contract for control over who can and cannot mint.

The expression above checks the report of the verify tier contract to see if the address interacting is on the verify tier or not

    min(mul(sub(current-timestamp() deployTimestamp) amountChangePerTimestampPerWallet) 
div(1000000000 numberOfVerifiedWallets))

This expression calculates the mintable amount for a verified address, there are some variables here such as “amountChangePerTimestampPerWallet” which needs to be calculated before hand, or it can be written as expression itself, but the less expressions the lower the gas fee, so we try to do any calculations before hand if we can as much as possible, to calculate “amountChangePerTimestampPerWallet” we do:

10 years in timestamp = 10 365 24 60 60 = 315360000 amountChangePerTimestamp = 1000000000 / 315360000 amountChangePerTimestampPerWallet = amountChangePerTimestamp / numberOfVerfiedWallets

Other calculations might be

1 hour in timestamp = 1 60 60 = 3600 1 day in timestamp = 1 24 60 60 = 86400 1 month in timestamp = 365 / 12 24 60 60 = 2628000 1 years in timestamp = 1 365 24 60 60 = 31536000

So now we know by each timestamp passing how many tokens can a wallet mint. The min() opcode makes sure that we don't go above the 1B token cap.

Now we need to calculate the amount that was previously minted by the wallet and subtract it by the amount that the wallet can mint (number 2)

    min(mul(saturating-sub(single-report(this-address() context(0) 1) deployTimestamp)         
amountChangePerTimestampPerWallet) div(1000000000 numberOfVerifiedWallets))

We check the emissions report to see what was the last time that the wallet has minted, then we calculate the minted amount based on that as we know how many tokens can be minted per timestamp per wallet, then we just subtract number 2 from number 3, ie the amount that can be minted by the wallet minus the amount the wallet has already minted. Which gives us the result that we want.

So the whole expression work as if the wallet is verified then it can mint certain amount of tokens at each timestamp over the span of 10 years capped at 1B.

Without variables & ready to be pasted directly

Example

Here's an example without variables & ready to be pasted directly

    eager_if(equal_to(ITIERV2_REPORT(0xDe61D65dBaBC7274f18c747b6243b03E11933feC context(0)) 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) 0 sub(min(mul(sub(block_timestamp() 1664806958) 5787037037037037037037) div(1000000000000000000000000000 2)) min(mul(saturating_sub(ITIERV2_REPORT_TIME_FOR_TIER(this_address() context(0) 1) 1664806958) 5787037037037037037037) div(1000000000000000000000000000 2))))

And, here is a deployed contract on the Toy Token website to play with - https://toy-token.on.fleek.co/#/token/0x0E56abd2906C3e461300D09032C3C55da2840a61

You can see my wallet is eligble to claim a lot. What happens when you connect your wallet?