Lilium is the native token of Wayports community. The intent is to produce an deflationary token, which is when the market value of the token is always ascending in the broader picture. Besides that, we want to create an environment that is friendly and welcoming to the newcomers of the crypto world, but also can serve well the users that are already familiar with how the blockchain works and know how to store and manage their assets.

Behind Lilium

Lilium is built on top of the Flow blockchain, a project that have principles similar to the ones that we envisioned for our token, which is to have a consumer-friendly on-boarding. Also, Flow provides us, the developers, great tooling that can make the development process of smart contracts easier.

Backing the Lilium development we also have Blocto as our go to crypto wallet. Blocto abstracts the whole process of creating a new wallet, writing down the seed phrase in a offline fashion, to guarantee that it don't get leaked or hacked and the user ends up losing all his/her assets. All that is required in order to create a new wallet using Blocto it is an e-mail. The user receives a code, pastes it on the wallet app and the login is successfully validated and concluded.

The contracts

In this section we will discuss the Lilium contract, the process of minting new Lilium as well as the transaction that configures the user wallet to receive Lilium, and how the contract for transferring the token between account looks like.

Smart contracts on Flow blockchains are written in the Cadence language, which is a language created exclusively for this blockchain. In case you need further explanation than the one provided by this documentation, you can always consult the Cadence docs.

Lilium contract

The declaration of a new public contract on Cadence is as follows:

pub contract Lilium {

}

By now, the only attribute that we will need to have on our Lilium contract is the one that will tell us what is the current circulating supply, which will be an unsigned 64 byte integer and the largest number possible to represent in that type being 18446744073709551615 , so if we decided that the maximum circulating supply could go bigger that 2 ^ (64 − 1) we need to change this attribute type

pub contract Lilium {
	pub var totalSupply: UFix64
}

Next we will need to create a series of Flow resources (more info on that here), in order to allow users to have complete control over their assets instead of transacting the asset over a central ledger.

Central ledgers are common on the Ethereum and the Binance Smart Chain networks, where the token balance of a given wallet is stored by the token contract, and not the user's wallet itself.

The first resource we are going to define is the Vault. A Vault will be where Lilium is going to get stored on the user's wallet, and each user needs a copy of this Vault in their wallet before doing any kind of transaction with Lilium. The setting up of the users' wallet will be covered later, for now we need just to create the Vault resource inside our main contract.

The following is how we declare a new Vault resource:

pub contract Lilium {
	pub var totalSupply: UFix64

	pub resource Vault: Provider, Receiver, Balance {
        pub var balance: UFix64

        init(balance: UFix64) {
            self.balance = balance
        }

        pub fun withdraw(amount: UFix64): @Vault {
            self.balance = self.balance - amount
            return <-create Vault(balance: amount)
        }

        pub fun deposit(from: @Vault) {
            self.balance = self.balance + from.balance
            destroy from
        }
    }
}

As you can see the resource Vault has balance as attribute, which of course it'll be used to track the token balance in a given wallet. Vault also extends three interface Provider, Receiver and Balance . Like any programming language, interfaces demands the caller to implement methods that matches the signatures that are present in the interface declaration.

Those three interfaces are implemented as follows:

pub contract Lilium {
	pub var totalSupply: UFix64

	pub resource Vault: Provider, Receiver, Balance {
        pub var balance: UFix64

        init(balance: UFix64) {
            self.balance = balance
        }

        pub fun withdraw(amount: UFix64): @Vault {
            self.balance = self.balance - amount
            return <-create Vault(balance: amount)
        }

        pub fun deposit(from: @Vault) {
            self.balance = self.balance + from.balance
            destroy from
        }
    }

	 pub resource interface Provider {
        pub fun withdraw(amount: UFix64): @Vault {
            post {
                result.balance == UFix64(amount):
                    "Withdrawal amount must be the same as the balance of the withdrawn Vault"
            }
        }
    }

    pub resource interface Receiver {
        pub fun deposit(from: @Vault)
    }

    pub resource interface Balance {
        pub var balance: UFix64
    }
}