Stateful Smart Accounts: Part 1

Hi guys,

We’ve recently descussed one possible path for the future of Waves Smart Contracts, but prior to do that, let’s revisit what we already have with current release
[SPOILER: it’s more that multisig]:

Below is a copy of the post:

Revisiting Data Transactions

Data Transactions were introduced to the Waves Platform with the goal of being able to post user data to the blockchain, thereby also enabling Data Oracles. These are simply regular accounts that post real-world data like weather conditions, exchange rates and any other information. That data can be accessed by Smart Account code.

Diving deeper, DataTransaction is just a set of key-value pairs, like:

DataTransaction([sender: XXX], "name" -> "Ilya", "age" -> 29)

When an account posts several DataTransaction values for the same keys, these values get overwritten with the latest one , when accessed through a REST or Smart Account API. Let’s say the London Stock Exchange fully embraces the power of Waves Smart Accounts (and crypto in general) and starts providing real-time quotes for everyone using DataTransactions, in this order (prices in cents):

DataTransaction([sender: LSE], "eur/usd" : 122, "btc/usd" : 630000)
DataTransaction([sender: LSE], "marketOpen" : false)
DataTransaction([sender: LSE], "eur/usd" : 116, "waves/usd": 220)
DataTransaction([sender: LSE], "marketOpen" : true)

If a Smart Contract reads this oracle after the transactions are posted, it will get the most up-to-date value for any key:

getInteger(LSE,"eur/usd")     => 116
getInteger(LSE, "btc/usd")    => 630000
getInteger(LSE, "waves/usd")  => 220
getInteger(LSE, "marketOpen") => true

It’s as simple as that: there are no restrictions on posting data, and the latest values for keys are accessible through any contract.

Contract State through Data Transactions

Now, what if a Smart Account wants to restrict its DataTransactions based on its own state , formed by its previous DataTransactions? Let’s write a straightforward script that only allows posting a number which is greater than the previous by one:

match (tx) {
  case tx:DataTransaction =>
    let oldX = extract(getInteger(tx.sender, "x"))
    let newX = extract(getInteger(tx.data, "x")
    newX == oldX + 1
  case _ => false
}

This will allow for the following sequence of DataTransactions:

DataTransaction([sender: XXX], "x" -> 0)
DataTransaction([sender: XXX], "x" -> 1)
DataTransaction([sender: XXX], "x" -> 2)

but deny this:

DataTransaction([sender: XXX], "x" -> 0)
DataTransaction([sender: XXX], "x" -> 1)
DataTransaction([sender: XXX], "x" -> 35) <-- this transaction will fail

Here’s this contract deployed to testnet:
https://testnet.wavesexplorer.com/address/3MsDHpfvm1p3FCrgQmHHYyXDtEey3V8qjr3

By the way, as you can see from the account script, anyone can post DataTransactions — the transitions need to be under current account state . Give it a try.

So, the combination of DataTransactions and Smart Accounts do form a stateful contract. Of course, this is just a tiny example, but worth exploration and extrapolation. It is the first post in the series covering the true capabilities of Waves Smart Accounts. We have a lot more to discuss. Until then, please upgrade your node to version 0.14.4 and start voting for Feature 4.

Stay tuned!

1 Like