Getting started with Liquidity 2: authentication

July 31, 2018
easy liquidity cryptocurrency tezos michelson blockchain smart contracts

I’ve updated the first Liquidity article for betanet/zeronet. If you haven’t read it yet, you should start there. Today, we’ll review the contract we’ve written last time and try to figure out what’s wrong with it. Then we’ll make some improvements and talk about authentication.

After a closer look, you’ll notice that the bet can be resolved only after both players have revealed their number. Nothing forces the players to actually reveal it – each of the players can hold the bet hostage indefinitely, if they think they are going to lose. We can add a deadline and force the players to reveal a number or forfeit the bet.

We can use the timestamp data type for keeping track of the deadline. The function Current.time will give us the current time, just like NOW in Michelson. To be precise, it actually gives us the timestamp of the block that would include our transaction. It is called with a unit argument, symbolized by () in Liquidity.

Timestamps can be set with the RFC3339 short format and incremented with + and a number of seconds:

let someTime = 1970-01-01T00:00:00Z in
let later = someTime + 60 in
(* ... *)

When do we want to set the deadline and when do we want to reset it? Do we need to use it anywhere else? Try to add the deadline functionality. You can check my code below.

Now both players are required to commit (at least) the same amount to the bet and the winner takes all.

If you get stuck or want to compare solutions, here’s my code implementing the additional features.

You are now familiar with some limitations of smart contracts, and in the rest of the article, we’ll look at different ways to authenticate callers of our contracts.

When we don’t need to exclude smart contracts, we have a few choices. We can use Current.source (SOURCE in Michelson) to get the address which started the current transaction sequence. This will be a PKH or a spendable contract. Note that using SOURCE to authenticate users is dangerous – users can be conned into calling a malicious contract, which then calls our contract and acts on their behalf. On one hand, users should make sure they understand the contracts they are calling, but it’s almost a certainty that majority of users won’t audit the contracts they use.

Luckily, we can use Current.sender (SENDER in Michelson), which gives us the previous address in the current transaction sequence. This way we can avoid the issue completely, and our contract will also be compatible with smart contract callers, e.g. multi-sig wallets.

Another approach is to use signatures. This requires holding a public key in our contract, and verifying that incoming calls were signed by the corresponding private key. Any address can be a source of such transaction, as long as the signature checks out. We should make sure the signature can’t be reused, either by using a counter or otherwise making it useless to re-transmit the old data and signatures.

It’s still early days for Tezos, so things aren’t standardized yet. Come to the developer channel and discuss your use case and what the best approach is.

To get notified about my articles, you can subscribe to my email list.

tzsuite: event driven library for Tezos

October 2, 2018
golang tezos michelson cryptocurrency blockchain smart contracts applications oracles automation

Getting started with Liquidity: coinflip

May 27, 2018
easy liquidity cryptocurrency tezos michelson blockchain smart contracts

Tezos changes: zeronet update

April 15, 2018
cryptocurrency tezos michelson blockchain smart contracts applications oracles