HowTo VeChain Blockchain — Part 4

MiRei
4 min readJul 21, 2020

--

Creating a multi-clause transaction

(Links to all parts at the bottom)

In this part, the concept of clauses will be explained and a transaction with multiple clauses containing VET will be send in testnet.

What is a clause on the VeChain blockchain?

A clause is part of a transaction. One transaction can have multiple clauses. A clause carries the actual data that should be written to the blockchain. The VeChain transaction model says “an array of Clause objects each of which contains fields To, Value and Data to enable a single transaction to carry multiple tasks issued by the transaction sender”. This unique feature is called Multi-Task-Transaction or MTT.

In Bitcoin or Ethereum a transaction has three basic parts: “From”, “To” and “Payload”. Every transaction has one sender, one recipient and one payload for that recipient (this payload may carry multiple contractcalls for one contract).
In Vechain there are also these three parts but only the “From” is unique. With clauses, one transaction can carry payloads for multiple recipients or multiple payloads for one recipient, wether it’s the transfer of VET, VTHO or other contract data.
Once we have created a transaction with multiple clauses, it will be pretty clear!

In Part 3 a transaction was created, that send 1 VET to 0x0000000000000000000000000000000000000000.
We now will create ONE transaction that will send:
1 VET to 0x0000000000000000000000000000000000000000
1 VET to 0x0000000000000000000000000000000000000009
(Addresses lower than 0x0000000000000000000000000000000000000009 are contracts and will consume more gas than expected. Contract interaction will be covered in a later part).

Create a multi-clause-transaction

The transaction body to this is almost the same as in Part 3.

body = {
"chainTag": 39,
"blockRef": '0x0063603cdce346e6',
"expiration": 720,
"clauses": [
{
"to": '0x0000000000000000000000000000000000000000',
"value": 1000000000000000000,
"data": '0x'
},
{
"to": '0x0000000000000000000000000000000000000009'
"value": 1000000000000000000,
"data": '0x'
}
],
"gasPriceCoef": 0,
"gas": 37000,
"dependsOn": None,
"nonce": 12345678
}

There are of course differences in the body:

Blockref: Needs to be updated to the latest block (as shown in Part 2)

Clauses: (This is the part where it hit me with “What?! Is is really that easy?”) To send VET to another destination within THE SAME transaction, simply add another set of “to”, “value”, “data” to the clause-part of the body. This can be repeated until the gas-limit of the block is reached.

Gas: The more clauses a transaction contains, the more gas the transaction needs. As covered in Part 2, the calculation for this VET clauses is simple:
5000 (base-cost) + 16000 + 16000 (for non-contract-creation clauses) = 37000 gas.

Other than that, it’s the same script as in Part 3. Create a new file (4_multiclause.py) and update Blockref to your needs.

from thor_devkit import cry, transaction
import requests
body = {
"chainTag": 39,
"blockRef": '0x006360a563534115',
"expiration": 720,
"clauses": [
{
"to": '0x0000000000000000000000000000000000000000',
"value": 1000000000000000000,
"data": '0x'
},
{
"to": '0x0000000000000000000000000000000000000009',
"value": 1000000000000000000,
"data": '0x'
}
],
"gasPriceCoef": 0,
"gas": 37000,
"dependsOn": None,
"nonce": 12345678
}
# Construct an unsigned transaction.
tx = transaction.Transaction(body)
# Sign the transaction with a private key.
priv_key = bytes.fromhex('61faba91ef7516969e885d197f59feeb2007ea2c6057908d1696d6f056ca69d4')
message_hash = tx.get_signing_hash()
signature = cry.secp256k1.sign(message_hash, priv_key)
# Set the signature on the transaction.
tx.set_signature(signature)
print('Created a transaction from ' + tx.get_origin() + ' to 0x0000000000000000000000000000000000000000 with TXID: ' + tx.get_id() + '.')
print('')
encoded_bytes = tx.encode()# pretty print the encoded bytes.
print('The transaction "0x' + encoded_bytes.hex() + '" will be send to the testnet node now.')
tx_headers = {'Content-Type': 'application/json', 'accept': 'application/json'}tx_data = {'raw': '0x' + encoded_bytes.hex()}send_transaction = requests.post('https://testnet.veblocks.net/transactions', json=tx_data, headers=tx_headers)print('Response from Server: ' + str(send_transaction.content))

This will result in a new transaction with two clauses and two destinations!

Transaction with two clauses on Vechain Testnet

If we open this transaction in the blockexplorer, we can see, that it says “2” on the clauses-row.

Transaction with two clauses on Vechain Testnet

If inspected closer, it shows that VET was transfered to the addresses specified in the transaction body.

Details of two clauses on VeChain Testnet

Are clauses the same as transactions?

Technically, obviously not. It’s just a part of a transaction that can not stand alone. But from a senders side, it pretty much eleminates the need for a second transaction. It’s fair to say that you can refer to the activity of the VeChain blockchain by observing the clauses and not just the transactions.

--

--