Liquidity Tutorials — Hands-on Series — Part 2

Marty Stumpf
Jun 18, 2019 · 5 min read
Photo by Weiwei Chen from Pexels

This is the second part of a tutorial series on writing smart contracts in Liquidity. See the first part here.

Last time we wrote the identity contract, and ran a simulation of it. This time, we’ll write a contract that sends one tez to another account. We’ll also deploy the contract to the testnet (Alphanet), and call it to see it in action!

The contract

The caller of this contract initiates a transfer from the contract’s account to the destination (receiver’s) address. The Liquidity code below is saved as send_one_tez.liq

type storage = unit 

let%entry main
(key : key_hash)
_storage =
let op = Account.transfer ~dest:key ~amount:1tz in
( [op], () )

In this contract:

  • the storage is unit.

its inputs are:

  1. the parameter of the contract, i.e., the address of the receiver of the transfer, of type key_hash.

its output is a pair of operation list and storage:

  1. the operation list has one element, op, of type operation, and it is the Account.transfer operation. More on this below.

Let’s take a closer look at the Account.transfer operation. It has the following type signature:

dest:key_hash -> amount:tez -> operation

It takes two inputs, dest, of type key_hash, and amount, of type tez. In Liquidity, it is represented by tz. The output is of type operation. The contract executes an internal operation: a transfer, of the amount specified, from the contract to the implicit (default) account of dest. In this contract, we have specified the dest to be the parameter (named key) and the amount to be 1 tz.

Deploy and call

Now let’s verify that the contract does what it intends to do. We’ll first check the balances of the relevant parties. Then, we deploy and call the contract. After the call we check the balances again to see the change in balances.

Accounts and balances

In this example I have three accounts (adam, alice, and bob) activated. Follow this for instructions on activating accounts.

Adam deploys/originates the contract. Alice calls the contract. Bob is the recipient of the 1 tez.

To call the contract (with Liquidity), we need to know alice’s private key and hash, and bob’s hash.

Running tezos-client show address alice -S --show-secret shows the following for alice:

Hash: tz1ccqAEwfPgeoipnXtjAv1iucrpQv3DFmmS
Public Key: edpku5LTYXxXKTjmzj9qtHR6TTYH1K6JU7bFe8MyJs6qabUs9kiZes
Secret Key: unencrypted:edsk2gKnmssYQB5sNCAL6sCcgfPRZDuK1zixBowAQ1H1WCt78JxEhf

alice is a fake account on the testnet. Remember, NEVER disclose your secret key!

Running tezos-client show address bob shows the following for bob:

Hash: tz1Ra8yQVQN4Nd7LpPQ6UT6t3bsWWqHZ9wa6
Public Key: edpktqrmQgDqvdCZM4msb9eDpe2adQ6NDgE7Jax34ABPzvw2Pk9SaT

Before we call the contract, which will execute the transfer of 1 tez, let’s check the balances of the accounts:

tezos-client get balance for adam

11331.543993 ꜩ

tezos-client get balance for alice

29399.641915 ꜩ

tezos-client get balance for bob

7704.71877 ꜩ

Deploy

Compile send_one_tez.liq to .tz (by running liquidity send_one_tez.liq). Deploy the contract with on the Tezos command line interface (CLI) with:

tezos-client originate contract sendtez for adam transferring 1 from adam running [path to]/send_one_tez.tz --burn-cap 0.43

  • I name the contract sendtez.

Alternatively, one can deploy/call a contract using Liquidity or the Liquidity online editor.

The output confirms that the contract is injected to the network with the address KT1Cm2wXCJVUb7QMqHEK4xFtvGh9XUMQ2Py8:

Node is bootstrapped, ready for injecting operations.
Estimated gas: 14470 units (will add 100 for safety)
Estimated storage: 430 bytes added (will add 20 for safety)
Operation successfully injected in the node.
Operation hash is 'ooAS5avXzYK8KsZc7e5DfY7o6Pd2trHvqkgsYFFRVbpn9eXSEkq'
Waiting for the operation to be included...
Operation found in block: BMVp7boyyk1r8mcEKyeG5kzDvUD6zB4zfXrbSDAHaSEFWCAsnLZ (pass: 3, offset: 0)
This sequence of operations was run:
Manager signed operations:
From: tz1fPjyo55HwUAkd1xcL5vo6DGzJrkxAMpiD
Fee to the baker: ꜩ0.001886
Expected counter: 40385
Gas limit: 14570
Storage limit: 450 bytes
Balance updates:
tz1fPjyo55HwUAkd1xcL5vo6DGzJrkxAMpiD ............. -ꜩ0.001886
fees(tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5,177) ... +ꜩ0.001886
Origination:
From: tz1fPjyo55HwUAkd1xcL5vo6DGzJrkxAMpiD
For: tz1fPjyo55HwUAkd1xcL5vo6DGzJrkxAMpiD
Credit: ꜩ1
Script:
{ parameter key_hash ;
storage unit ;
code { DUP ;
DIP { CDR @_storage_slash_1 } ;
DIP { DROP } ;
CAR @key_slash_2 ;
IMPLICIT_ACCOUNT ;
PUSH mutez 1000000 ;
UNIT ;
TRANSFER_TOKENS @op ;
UNIT ;
NIL operation ;
DUUUP ;
DIIIP { DROP } ;
CONS ;
PAIR } }
Initial storage: Unit
No delegate for this contract
This origination was successfully applied
Originated contracts:
KT1Cm2wXCJVUb7QMqHEK4xFtvGh9XUMQ2Py8
Storage size: 173 bytes
Paid storage size diff: 173 bytes
Consumed gas: 14470
Balance updates:
tz1fPjyo55HwUAkd1xcL5vo6DGzJrkxAMpiD ... -ꜩ0.173
tz1fPjyo55HwUAkd1xcL5vo6DGzJrkxAMpiD ... -ꜩ0.257
tz1fPjyo55HwUAkd1xcL5vo6DGzJrkxAMpiD ... -ꜩ1
KT1Cm2wXCJVUb7QMqHEK4xFtvGh9XUMQ2Py8 ... +ꜩ1

New contract KT1Cm2wXCJVUb7QMqHEK4xFtvGh9XUMQ2Py8 originated.
The operation has only been included 0 blocks ago.
We recommend to wait more.
Use command
tezos-client wait for ooAS5avXzYK8KsZc7e5DfY7o6Pd2trHvqkgsYFFRVbpn9eXSEkq to be included --confirmations 30 --branch BL8o7pZFbHAgAVheKMFLKWUwWJtSj6eaz7QvQLYojKJavmvTAyf
and/or an external block explorer.
Contract memorized as sendtez.

The output also shows that Adam paid for various fees to deploy the contract, and the contract’s balance is increased by 1 tez. We can check that the contract has a balance of 1 tez:

tezos-client get balance for sendtez
1 ꜩ

Call

Now we can call the contract. Let’s use Liquidity this time! Use the Liquidity command (see the full list of commands with liquidity --help) --call [contract address] [entry point name] [receipent's key_hash] (in my case, bob’s key hash):

The output confirms that the call is successful:

Main contract Send_one_tez
Successful call to contract KT1Cm2wXCJVUb7QMqHEK4xFtvGh9XUMQ2Py8 in operation opANAeVfLmiVnXvgNVvtkuqMBFW73ZPPZQZ5SCkEpcjmZzSZo3A

To check that one tez was transferred from the contract to bob, let’s check their balances:

tezos-client get balance for sendtez
0 ꜩ
tezos-client get balance for bob
7705.71877 ꜩ

bob’s balance has indeed gone up by 1tz. alice paid for the transaction fees that calls the contract, so her balance is down by a little:

tezos-client get balance for alice
29399.591915 ꜩ

In the next tutorial, we’ll step up our game and write a contract that publishes authenticated data. Stay tuned!


[1]: In the future, one may save the code in a .ligo file and deploy with LIGO via the CameLIGO syntax.

Cryptium Labs Tezos

Cryptium Labs offers secure and highly available digital signatures for Proof-of-Stake networks, such as Tezos, Cøsmos, and Polkadot. This blog is dedicated to anyone in the blockchain ecosystem and aims to provide educational content for all audiences on topics such as security.

Marty Stumpf

Written by

Blockchain protocol/smart contract engineer @CryptiumLabs. thealmarty.com, twitter: @MartyStumpf.

Cryptium Labs Tezos

Cryptium Labs offers secure and highly available digital signatures for Proof-of-Stake networks, such as Tezos, Cøsmos, and Polkadot. This blog is dedicated to anyone in the blockchain ecosystem and aims to provide educational content for all audiences on topics such as security.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade