Waves Protocol
Published in

Waves Protocol

Application of Waves Smart Accounts: from Auctions to Customer Loyalty Schemes

Blockchain is often associated solely with cryptocurrencies, but application areas for DLT are far broader. One of the most promising directions for blockchain application is smart contracts: code that is executed automatically and that doesn’t require trust between the parties who agree it.

RIDE: a smart contract language

Waves has developed a special language for smart contracts, RIDE. Complete documentation is available here.

A RIDE-based contract is a predicate and returns either “true” or “false”. Respectively, a transaction is either added to the blockchain or rejected. A smart contract fully guarantees the execution of conditions set out in it. At this point, the option of generating transactions from a RIDE contract is not available.

Currently, Waves offers two types of smart contracts, smart accounts and smart assets. A smart account is a user’s regular account, for which a script can be set that controls all transactions. A Smart Account’s script could look, for instance, like this:

tx is a processed transaction that we allow, using the pattern matching tool, unless it is a TransferTransaction. In RIDE, pattern matching is used for checking the type of transaction. All existing [transaction types] (https://docs.wavesplatform.com/en/waves-environment/waves-protocol/transactions-structure.html) can be processed in a Smart Account’s script.

A script can also use variables, “if-then-else” statements and other methods of proper verification of conditions. To facilitate contracts’ provable termination and complexity (value) that can be predicted prior to the contract’s execution, RIDE doesn’t have cycles or jump operators.

Among Waves accounts’ other features is the state. An indefinite number of pairs (key, value) can be added to an account’s state using DataTransactions. Subsequently, that information can be processed either over REST API, or directly in the smart contract.

Every transaction can contain an array of proofs, in which a participant’s signature, a transaction ID, etc, might be entered.

Using RIDE in IDE https://ide.wavesplatform.com/ enables display of a smart contract’s compiled view (as long as it can be compiled), creation of new accounts and setting scripts for them, as well as sending transactions from the command prompt.

For a full cycle that includes creating an account, adding a smart contract to it and sending a transaction, a library for REST API can be used (such as C#, C, Java, JavaScript, Python, Rust or Elixir). To start using IDE, just hit the NEW button.

Smart contracts’ possible applications range from banning transactions to selected addresses (blacklisting) to creating complex dApps.

Now we’ll consider several specific examples of smart contract application in business, such as auctions, insurance and customer loyalty programs.


Transparency is one of the conditions necessary for running a successful auction: participants have to be sure that bid manipulation is impossible. This can be achieved thanks to a blockchain on which immutable data for all bids and the times when they were made is available to all participants.

On Waves’ blockchain, bids can be recorded in the auction’s account state using DataTransactions.

In addition, the auction’s start and end times can be set using block numbers, as Waves’ block generation frequency is roughly 60 seconds.

1. English (ascending price) auction

In an English auction, buyers place bids, competing with each other to set the highest price. Every higher bid displaces an earlier bid. If no competing bidder challenges the current bid within a given time frame, the bidder who placed it becomes the winner.

In a variation of this, the seller sets a minimum price for an item. If no buyer places a higher bid than this minimum price, the item remains unsold.

In this example, we show a smart account specifically created for an auction. The auction’s time frame equals 3,000 blocks and the initial price equals 0.001 WAVES. A buyer can place a bid by sending a DataTransaction with the key “price” and the value of their bid. A public key and the sender’s signature will have to be added to the transaction proofs.

The price of any new bid has to be higher than the current price, and the bidder has to have at least [new price + fee] tokens in their balance. The bidder’s address is added to the “sender” field in a DataTransaction and the current height of the block has to be within the auction’s time frame.

If a buyer places the highest bid, they pay for the item with an ExchangeTransaction specifying the price and asset pair.

2. Dutch (descending-price) auction

In a Dutch auction, an item is initially offered at a price exceeding the amount the buyer expects to pay. Then the price is gradually lowered until a bidder accepts the current price.

In this example, we use the same tools as in the previous one, also adding a delta for a step price. The account’s script checks if a participant has actually placed the first bid for the current price. A public key and the sender’s signature will have to be added to the transaction proofs. Otherwise, the blockchain doesn’t accept the DataTransaction.

3. All-pay auction

An all-pay auction is an auction in which all bidders pay, regardless of who wins the item. Every new bidder has to pay their bid, and the highest bidder wins the item, as in a conventional auction.

In our example, every participant places a bid by sending a DataTransaction with (key, value)* = (“winner”, address),(“price”, price). A bidder’s Data Transaction only gets approved if a TransferTransaction signed by them already exists and the bid is higher than the earlier bids. The auction runs until endHeight is reached.

Insurance / Crowdfunding

Let’s consider a situation where we need to protect users’ assets from financial loss. For instance, a user may want to ensure that they will be able to recover the entire amount paid for tokens in case of the token’s devaluation, and are prepared to pay a reasonable insurance premium.

For that purpose, “insurance tokens” will be issued. A script to the insured’s account is applied, allowing only ExchangeTransactions that meet certain conditions.

To prevent double spending, the insured user initially needs to send a DataTransaction to the insurer’s account with (key, value) = (purchaseTransactionId, sellOrderId) and prohibit sending DataTransactions with the same keys.

Consequently, the user’s proofs have to contain the ID of the transaction for the purchase of the insurance token. The asset pair has to be the same as in the purchase transaction. The price has to be equal to the token purchase price, with the insurance premium price deducted.

It is implied that the insurer’s account will later buy the insurance tokens from the user at a price no lower than the purchase price. The insurer’s account will create an ExchangeTransaction, and the insured user will sign an order (if the transaction is correct). The insurer’s account will sign the second order and the entire transaction, and send it to the blockchain.

If no purchase takes place, the user can create an order under conditions set in the script and send the transaction to the blockchain. That way, the user will recover the funds spent for the purchase of insured tokens.

The insurance token can be made a smart asset — for example, to prohibit its transfer to third parties.

This scheme can also be used for crowdfunding tokens, which are to be returned to the holders if a required sum of money has not been collected.


Smart contracts are also applicable in a situation when every transaction for several types of asset needs to be taxed. This can be implemented with a new asset, with added sponsorship for smart asset transactions:

  1. We issue FeeCoin, which will be sent to users at a fixed price: 0.01 WAVES = 0.001 FeeCoin.
  2. We set sponsorship for FeeCoin and specify the exchange rate: 0.001 WAVES = 0.001 FeeCoin.
  3. We set the following script for the smart asset:

Now, every time someone transfers N smart assets, they will send you N / taxDivisor FeeCoins (which could be bought from you at 10 *N / taxDivisor WAVES) and will send N / taxDivisor WAVES to the miner. As a result, you will collect a profit (tax) of 9 *N / taxDivisor WAVES.

Taxation could also be implemented with a smart asset script and MassTransferTransaction:

Cashback and loyalty schemes

Cashback is a type of a customer loyalty scheme in which a percentage of funds spent on goods or services is paid back to the customer.

In the implementation of this case with a smart account, we need to check proofs in the same way as in the insurance use case. To prevent double spending, before collecting a cashback, a user has to send a DataTransaction with (key, value) = (purchaseTransactionId, cashbackTransactionId).

Also, we need to prohibit setting DataTransactions with the same keys. cashbackDivisor is a reverse number for a cashback share. If the cashback share is 0.1, cashbackDivisor will be 1 / 0.1 = 10.

Atomic swap

An atomic swap enables users to swap assets without using exchanges. In an atomic swap, approval from both participants of the transaction is required within a specified time frame.

If at least one of the participants fails to approve the transaction within the specified time frame, the transaction is cancelled and funds are not exchanged.

In our example, we use a smart account script:

In our next article, we’ll look at the application of smart accounts for financial tools, such as options, futures and bills of exchange.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Waves Tech

Waves Tech is a powerful blockchain-agnostic ecosystem focused on inter-chain DeFi, the embodiment of technological freedom for blockchain-based finance.