DasProblem / API.md
sky-meilin's picture
Upload API.md (#1)
b400271 verified
# **TVM Solidity API**
TVM Solidity compiler expands Solidity language with different API functions to facilitate TVM contract development.
When deploying contracts, you should use the latest released version of Solidity. Apart from exceptional cases, only the latest version receives security fixes. Furthermore, breaking changes, as well as new features, are introduced regularly. We currently use a 0.y.z version number to indicate this fast pace of change.
## Table of Contents
* [Compiler version](#compiler-version)
* [TVM specific types](#tvm-specific-types)
* [TVM units](#tvm-units)
* [TvmCell](#tvmcell)
* [constructing TvmCell](#constructing-tvmcell)
* [\<TvmCell\>.depth()](#tvmcelldepth)
* [\<TvmCell\>.dataSize()](#tvmcelldatasize)
* [\<TvmCell\>.dataSizeQ()](#tvmcelldatasizeq)
* [\<TvmCell\>.toSlice()](#tvmcelltoslice)
* [\<TvmCell\>.exoticToSlice()](#tvmcellexotictoslice)
* [\<TvmCell\>.loadExoticCell() and \<TvmCell\>.loadExoticCellQ()](#tvmcellloadexoticcell-and-tvmcellloadexoticcellq)
* [TvmSlice](#tvmslice)
* [\<TvmSlice\>.empty(), \<TvmSlice\>.bitEmpty() and \<TvmSlice\>.refEmpty()](#tvmsliceempty-tvmslicebitempty-and-tvmslicerefempty)
* [\<TvmSlice\>.size()](#tvmslicesize)
* [\<TvmSlice\>.bits()](#tvmslicebits)
* [\<TvmSlice\>.refs()](#tvmslicerefs)
* [\<TvmSlice\>.dataSize()](#tvmslicedatasize)
* [\<TvmSlice\>.dataSizeQ()](#tvmslicedatasizeq)
* [\<TvmSlice\>.depth()](#tvmslicedepth)
* [\<TvmSlice\>.hasNBits(), \<TvmSlice\>.hasNRefs() and \<TvmSlice\>.hasNBitsAndRefs()](#tvmslicehasnbits-tvmslicehasnrefs-and-tvmslicehasnbitsandrefs)
* [\<TvmSlice\>.compare()](#tvmslicecompare)
* [\<TvmSlice\>.startsWith()](#tvmslicestartswith)
* [\<TvmSlice\>.startsWithOne()](#tvmslicestartswithone)
* [TvmSlice load primitives](#tvmslice-load-primitives)
* [\<TvmSlice\>.load()](#tvmsliceload)
* [\<TvmSlice\>.loadQ()](#tvmsliceloadq)
* [\<TvmSlice\>.loadRef()](#tvmsliceloadref)
* [\<TvmSlice\>.loadRefAsSlice()](#tvmsliceloadrefasslice)
* [\<TvmSlice\>.loadInt() and \<TvmSlice\>.loadIntQ()](#tvmsliceloadint-and-tvmsliceloadintq)
* [\<TvmSlice\>.loadUint() and \<TvmSlice\>.loadUintQ()](#tvmsliceloaduint-and-tvmsliceloaduintq)
* [Load little-endian integers](#load-little-endian-integers)
* [\<TvmSlice\>.loadSlice() and \<TvmSlice\>.loadSliceQ()](#tvmsliceloadslice-and-tvmsliceloadsliceq)
* [\<TvmSlice\>.skip()](#tvmsliceskip)
* [\<TvmSlice\>.loadZeroes(), \<TvmSlice\>.loadOnes() and \<TvmSlice\>.loadSame()](#tvmsliceloadzeroes-tvmsliceloadones-and-tvmsliceloadsame)
* [TvmSlice preload primitives](#tvmslice-preload-primitives)
* [\<TvmSlice\>.preload()](#tvmslicepreload)
* [\<TvmSlice\>.preloadQ()](#tvmslicepreloadq)
* [\<TvmSlice\>.preloadRef()](#tvmslicepreloadref)
* [\<TvmSlice\>.preloadInt() and \<TvmSlice\>.preloadIntQ()](#tvmslicepreloadint-and-tvmslicepreloadintq)
* [\<TvmSlice\>.preloadUint() and \<TvmSlice\>.preloadUintQ()](#tvmslicepreloaduint-and-tvmslicepreloaduintq)
* [Preload little-endian integers](#preload-little-endian-integers)
* [\<TvmSlice\>.preloadSlice() and \<TvmSlice\>.preloadSliceQ()](#tvmslicepreloadslice-and-tvmslicepreloadsliceq)
* [TvmBuilder](#tvmbuilder)
* [\<TvmBuilder\>.toSlice()](#tvmbuildertoslice)
* [\<TvmBuilder\>.toCell()](#tvmbuildertocell)
* [\<TvmBuilder\>.toExoticCell()](#tvmbuildertoexoticcell)
* [\<TvmBuilder\>.size()](#tvmbuildersize)
* [\<TvmBuilder\>.bits()](#tvmbuilderbits)
* [\<TvmBuilder\>.refs()](#tvmbuilderrefs)
* [\<TvmBuilder\>.remBits()](#tvmbuilderrembits)
* [\<TvmBuilder\>.remRefs()](#tvmbuilderremrefs)
* [\<TvmBuilder\>.remBitsAndRefs()](#tvmbuilderrembitsandrefs)
* [\<TvmBuilder\>.depth()](#tvmbuilderdepth)
* [\<TvmBuilder\>.store()](#tvmbuilderstore)
* [\<TvmBuilder\>.storeQ()](#tvmbuilderstoreq)
* [\<TvmBuilder\>.storeZeroes(), \<TvmBuilder\>.storeOnes() and \<TvmBuilder\>.storeSame()](#tvmbuilderstorezeroes-tvmbuilderstoreones-and-tvmbuilderstoresame)
* [\<TvmBuilder\>.storeInt()](#tvmbuilderstoreint)
* [\<TvmBuilder\>.storeUint()](#tvmbuilderstoreuint)
* [Store little-endian integers](#store-little-endian-integers)
* [\<TvmBuilder\>.storeRef()](#tvmbuilderstoreref)
* [StringBuilder](#stringbuilder)
* [\<StringBuilder\>.append()](#stringbuilderappend)
* [\<StringBuilder\>.toString()](#stringbuildertostring)
* [optional(T)](#optionalt)
* [constructing an optional](#constructing-an-optional)
* [\<optional(T)\>.hasValue()](#optionalthasvalue)
* [\<optional(T)\>.get()](#optionaltget)
* [\<optional(T)\>.getOr()](#optionaltgetor)
* [\<optional(T)\>.getOrDefault()](#optionaltgetordefault)
* [\<optional(T)\>.set()](#optionaltset)
* [Keyword `null`](#keyword-null)
* [variant](#variant)
* [variant.isUint()](#variantisuint)
* [variant.toUint()](#varianttouint)
* [vector(T)](#vectort)
* [\<vector(T)\>.push()](#vectortpush)
* [\<vector(T)\>.pop()](#vectortpop)
* [\<vector(T)\>.last()](#vectortlast)
* [\<vector(T)\>.operator[]](#vectortoperator)
* [\<vector(T)\>.length()](#vectortlength)
* [\<vector(T)\>.empty()](#vectortempty)
* [stack(T)](#stackt)
* [\<stack(T)\>.push()](#stacktpush)
* [\<stack(T)\>.pop()](#stacktpop)
* [\<stack(T)\>.top()](#stackttop)
* [\<stack(T)\>.empty()](#stacktempty)
* [\<stack(T)\>.sort()](#stacktsort)
* [\<stack(T)\>.reverse()](#stacktreverse)
* [TVM specific control structures](#tvm-specific-control-structures)
* [Range-based for loop](#range-based-for-loop)
* [repeat](#repeat)
* [try-catch](#try-catch)
* [unchecked block](#unchecked-block)
* [Changes and extensions in Solidity types](#changes-and-extensions-in-solidity-types)
* [Integers](#integers)
* [\<Integer\>.cast()](#integercast)
* [bitSize() and uBitSize()](#bitsize-and-ubitsize)
* [Quiet arithmetic](#quiet-arithmetic)
* [qintN and quintN](#qintn-and-quintn)
* [qbool](#qbool)
* [Keyword NaN](#keyword-nan)
* [\<T\>.isNaN()](#tisnan)
* [\<T\>.get()](#tget)
* [\<T\>.getOr()](#tgetor)
* [\<T\>.getOrDefault()](#tgetordefault)
* [\<T\>.toOptional()](#ttooptional)
* [varint and varuint](#varint-and-varuint)
* [struct](#struct)
* [struct constructor](#struct-constructor)
* [\<struct\>.unpack()](#structunpack)
* [Arrays](#arrays)
* [Array literals](#array-literals)
* [Creating new arrays](#creating-new-arrays)
* [\<array\>.empty()](#arrayempty)
* [bytesN](#bytesn)
* [bytes](#bytes)
* [\<bytes\>.empty()](#bytesempty)
* [\<bytes\>.operator[]](#bytesoperator)
* [\<bytes\> slice](#bytes-slice)
* [\<bytes\>.length](#byteslength)
* [\<bytes\>.dataSize()](#bytesdatasize)
* [\<bytes\>.dataSizeQ()](#bytesdatasizeq)
* [\<bytes\>.append()](#bytesappend)
* [bytes conversion](#bytes-conversion)
* [string](#string)
* [\<string\>.empty()](#stringempty)
* [\<string\>.byteLength()](#stringbytelength)
* [\<string\>.substr()](#stringsubstr)
* [\<string\>.append()](#stringappend)
* [\<string\>.operator+](#stringoperator)
* [\<string\>.find() and \<string\>.findLast()](#stringfind-and-stringfindlast)
* [\<string\>.dataSize()](#stringdatasize)
* [\<string\>.dataSizeQ()](#stringdatasizeq)
* [\<string\>.toUpperCase()` and \<string\>.toLowerCase()](#stringtouppercase-and-stringtolowercase)
* [format()](#format)
* [stoi()](#stoi)
* [string conversion](#string-conversion)
* [address](#address)
* [Object creating](#object-creating)
* [constructor()](#constructor)
* [address.makeAddrStd()](#addressmakeaddrstd)
* [address.addrNone](#addressaddrnone)
* [address.makeAddrExtern()](#addressmakeaddrextern)
* [Members](#members)
* [\<address\>.wid](#addresswid)
* [\<address\>.value](#addressvalue)
* [\<address\>.balance](#addressbalance)
* [\<address\>.currencies](#addresscurrencies)
* [Functions](#functions)
* [\<address\>.getType()](#addressgettype)
* [\<address\>.isStdZero()](#addressisstdzero)
* [\<address\>.isStdAddrWithoutAnyCast()](#addressisstdaddrwithoutanycast)
* [\<address\>.isExternZero()](#addressisexternzero)
* [\<address\>.isNone()](#addressisnone)
* [\<address\>.unpack()](#addressunpack)
* [\<address\>.transfer()](#addresstransfer)
* [mapping](#mapping)
* [Keyword `emptyMap`](#keyword-emptymap)
* [\<mapping\>.operator[]](#mappingoperator)
* [\<mapping\>.at()](#mappingat)
* [\<mapping\>.min() and \<mapping\>.max()](#mappingmin-and-mappingmax)
* [\<mapping\>.next() and \<mapping\>.prev()](#mappingnext-and-mappingprev)
* [\<mapping\>.nextOrEq() and \<mapping\>.prevOrEq()](#mappingnextoreq-and-mappingprevoreq)
* [\<mapping\>.delMin() and \<mapping\>.delMax()](#mappingdelmin-and-mappingdelmax)
* [\<mapping\>.fetch()](#mappingfetch)
* [\<mapping\>.exists()](#mappingexists)
* [\<mapping\>.empty()](#mappingempty)
* [\<mapping\>.replace()](#mappingreplace)
* [\<mapping\>.add()](#mappingadd)
* [\<mapping\>.getSet()](#mappinggetset)
* [\<mapping\>.getAdd()](#mappinggetadd)
* [\<mapping\>.getDel()](#mappinggetdel)
* [\<mapping\>.getReplace()](#mappinggetreplace)
* [\<mapping\>.keys() \<mapping\>.values()](#mappingkeys-mappingvalues)
* [Fixed point number](#fixed-point-number)
* [Function type](#function-type)
* [User-defined type](#user-defined-type)
* [require, revert](#require-revert)
* [require](#require)
* [revert](#revert)
* [Libraries](#libraries)
* [Function call via library name](#function-call-via-library-name)
* [Function call via object](#function-call-via-object)
[Free function call via object](#free-function-call-via-object)
* [Pragmas](#pragmas)
* [pragma tvm-solidity](#pragma-tvm-solidity)
* [pragma copyleft](#pragma-copyleft)
* [pragma ignoreIntOverflow](#pragma-ignoreintoverflow)
* [pragma AbiHeader](#pragma-abiheader)
* [pragma msgValue](#pragma-msgvalue)
* [pragma upgrade func/oldsol](#pragma-upgrade-funcoldsol)
* [State variables](#state-variables)
* [Decoding state variables](#decoding-state-variables)
* [Keyword `constant`](#keyword-constant)
* [Keyword `static`](#keyword-static)
* [Keyword `nostorage`](#keyword-nostorage)
* [Keyword `public`](#keyword-public)
* [Special contract functions](#special-contract-functions)
* [receive](#receive)
* [fallback](#fallback)
* [onBounce](#onbounce)
* [onTickTock](#onticktock)
* [onCodeUpgrade](#oncodeupgrade)
* [afterSignatureCheck](#aftersignaturecheck)
* [Function specifiers](#function-specifiers)
* [Function mutability: pure, view and default](#function-mutability-pure-view-and-default)
* [Keyword inline](#keyword-inline)
* [Assembly](#assembly)
* [functionID()](#functionid)
* [externalMsg and internalMsg](#externalmsg-and-internalmsg)
* [Events and return](#events-and-return)
* [emit](#emit)
* [return](#return)
* [External function calls](#external-function-calls)
* [Delete variables](#delete-variables)
* [API functions and members](#api-functions-and-members)
* [Type information](#type-information)
* [**msg** namespace](#msg-namespace)
* [msg.sender](#msgsender)
* [msg.value](#msgvalue)
* [msg.currencies](#msgcurrencies)
* [msg.pubkey()](#msgpubkey)
* [msg.isInternal, msg.isExternal and msg.isTickTock](#msgisinternal-msgisexternal-and-msgisticktock)
* [msg.createdAt](#msgcreatedat)
* [msg.data](#msgdata)
* [msg.forwardFee](#msgforwardfee)
* [msg.importFee](#msgimportFee)
* [msg.body](#msgbody)
* [msg.hasStateInit](#msghasstateinit)
* [**tvm** namespace](#tvm-namespace)
* [TVM instructions](#tvm-instructions)
* [tvm.accept()](#tvmaccept)
* [tvm.setGasLimit()](#tvmsetgaslimit)
* [tvm.buyGas()](#tvmbuygas)
* [tvm.commit()](#tvmcommit)
* [tvm.rawCommit()](#tvmrawcommit)
* [tvm.getData()](#tvmgetdata)
* [tvm.setData()](#tvmsetdata)
* [tvm.log()](#tvmlog)
* [tvm.hexdump() and tvm.bindump()](#tvmhexdump-and-tvmbindump)
* [tvm.setcode()](#tvmsetcode)
* [tvm.configParam()](#tvmconfigparam)
* [tvm.rawConfigParam()](#tvmrawconfigparam)
* [tvm.rawReserve()](#tvmrawreserve)
* [tvm.initCodeHash()](#tvminitcodehash)
* [Hashing and cryptography](#hashing-and-cryptography)
* [tvm.hash()](#tvmhash)
* [tvm.checkSign()](#tvmchecksign)
* [Deploy contract from contract](#deploy-contract-from-contract)
* [Deploy via new](#deploy-via-new)
* [`stateInit` option usage](#stateinit-option-usage)
* [`code` option usage](#code-option-usage)
* [Other deploy options](#other-deploy-options)
* [Deploy via \<address\>.transfer()](#deploy-via-addresstransfer)
* [Deploy the contract with no constructor](#deploy-the-contract-with-no-constructor)
* [New contract address problem](#new-contract-address-problem)
* [Misc functions from `tvm`](#misc-functions-from-tvm)
* [tvm.code()](#tvmcode)
* [tvm.pubkey()](#tvmpubkey)
* [tvm.setPubkey()](#tvmsetpubkey)
* [tvm.setCurrentCode()](#tvmsetcurrentcode)
* [tvm.resetStorage()](#tvmresetstorage)
* [tvm.exit() and tvm.exit1()](#tvmexit-and-tvmexit1)
* [tvm.sendrawmsg()](#tvmsendrawmsg)
* [**bls** namespace](#bls-namespace)
* [bls.verify()](#blsverify)
* [bls.aggregate()](#blsaggregate)
* [bls.fastAggregateVerify()](#blsfastaggregateverify)
* [bls.aggregateVerify()](#blsaggregateverify)
* [bls.g1Zero() and bls.g2Zero()](#blsg1zero-and-blsg2zero)
* [bls.g1IsZero() and bls.g2IsZero()](#blsg1iszero-and-blsg2iszero)
* [bls.g1Add() and bls.g2Add()](#blsg1add-and-blsg2add)
* [bls.g1Sub() and bls.g2Sub()](#blsg1sub-and-blsg2sub)
* [bls.g1Neg() and bls.g2Neg()](#blsg1neg-and-blsg2neg)
* [bls.g1Mul() and bls.g2Mul()](#blsg1mul-and-blsg2mul)
* [bls.g1InGroup() and bls.g2InGroup()](#blsg1ingroup-and-blsg2ingroup)
* [bls.r()](#blsr)
* [bls.g1MultiExp() and bls.g2MultiExp()](#blsg1multiexp-and-blsg2multiexp)
* [**math** namespace](#math-namespace)
* [math.min() math.max()](#mathmin-mathmax)
* [math.minmax()](#mathminmax)
* [math.abs()](#mathabs)
* [math.modpow2()](#mathmodpow2)
* [math.divr() math.divc()](#mathdivr-mathdivc)
* [math.divmod()](#mathdivmod)
* [math.muldiv() math.muldivr() math.muldivc()](#mathmuldiv-mathmuldivr-mathmuldivc)
* [math.muldivmod()](#mathmuldivmod)
* [math.mulmod()](#mathmulmod)
* [math.sign()](#mathsign)
* [**tx** namespace](#tx-namespace)
* [tx.logicaltime](#txlogicaltime)
* [tx.storageFee](#txstoragefee)
* [**block** namespace](#block-namespace)
* [block.timestamp](#blocktimestamp)
* [block.logicaltime](#blocklogicaltime)
* [**rnd** namespace](#rnd-namespace)
* [rnd.next](#rndnext)
* [rnd.getSeed](#rndgetseed)
* [rnd.setSeed](#rndsetseed)
* [rnd.shuffle](#rndshuffle)
* [**abi** namespace](#abi-namespace)
* [abi.encode(), abi.decode()](#abiencode-abidecode)
* [abi.encodeData()](#abiencodedata)
* [abi.encodeOldDataInit()](#abiencodeolddatainit)
* [abi.decodeData()](#abidecodedata)
* [abi.encodeStateInit()](#abiencodestateinit)
* [abi.stateInitHash()](#abistateinithash)
* [abi.encodeBody()](#abiencodebody)
* [abi.decodeFunctionParams()](#abidecodefunctionparams)
* [abi.codeSalt()](#abicodesalt)
* [abi.setCodeSalt()](#abisetcodesalt)
* [abi.functionId()](#abifunctionid)
* [abi.encodeIntMsg()](#abiencodeintmsg)
* [**gosh** namespace](#gosh-namespace)
* [gosh.diff and gosh.zipDiff](#goshdiff-and-goshzipdiff)
* [gosh.applyPatch, gosh.applyPatchQ, gosh.applyZipPatch, gosh.applyZipPatchQ, gosh.applyZipBinPatch and gosh.applyZipBinPatchQ](#goshapplypatch-goshapplypatchq-goshapplyzippatch-goshapplyzippatchq-goshapplyzipbinpatch-and-goshapplyzipbinpatchq)
* [gosh.zip and gosh.unzip](#goshzip-and-goshunzip)
* [gosh.mintshell and gosh.mintshellq](#goshmintshell-and-goshmintshellq)
* [gosh.sendtodappconfig](#goshsendtodappconfig)
* [gosh.getavailablebalance](#goshgetavailablebalance)
* [gosh.burnecc](#goshburnecc)
* [gosh.cnvrtshellq](#goshcnvrtshellq)
* [gosh.mintecc](#goshmintecc)
* [Exponentiation](#exponentiation)
* [selfdestruct](#selfdestruct)
* [sha256](#sha256)
* [gasToValue](#gastovalue)
* [valueToGas](#valuetogas)
* [gasleft](#gasleft)
* [TVM capabilities](#tvm-capabilities)
* [TVM exception codes](#tvm-exception-codes)
* [Solidity runtime errors](#solidity-runtime-errors)
* [Division and rounding](#division-and-rounding)
* [Contract execution](#contract-execution)
* [Gas optimization hints](#gas-optimization-hints)
## Detailed description
### Compiler version
TVM Solidity compiler adds its current version to the generated code. This version can be obtained:
1) using [tvm_linker](https://github.com/everx-labs/TVM-linker#2-decoding-of-boc-messages-prepared-externally) from a `*.tvc` file:
```bash
tvm_linker decode --tvm <tvc-file>
```
2) using [ever-cli](https://github.com/everx-labs/ever-cli#48-decode-commands) from a `*.boc` file, a `*.tvc` file, or a network account:
```bash
ever-cli decode tvc [--tvc] [--boc] <input>
```
### TVM specific types
TVM Solidity compiler expands functionality of some existing types and adds several new TVM specific types: TvmCell, TvmSlice and TvmBuilder. Full description of these types can be found in [TVM][1] and [Blockchain][2] specifications.
#### TVM units
A literal number can take a suffix to specify a subdenomination of currency, where numbers without a postfix are assumed to be nanoevers.
```TVMSolidity
uint a0 = 1 nano; // a0 == 1 == 1e-9 ever
uint a1 = 1 nanoever; // a1 == 1 == 1e-9 ever
uint a3 = 1 ever; // a3 == 1 000 000 000 (1e9)
uint a4 = 1 Ever; // a4 == 1 000 000 000 (1e9)
uint a5 = 1 micro; // a5 == 1 000 == 1e-6 ever
uint a6 = 1 microever; // a6 == 1 000 == 1e-6 ever
uint a7 = 1 milli; // a7 == 1 000 000 == 1e-3 ever
uint a8 = 1 milliever; // a8 == 1 000 000 == 1e-3 ever
uint a9 = 1 kiloever; // a9 == 1 000 000 000 000 (1e12) == 1e3 ever
uint a10 = 1 kEver; // a10 == 1 000 000 000 000 (1e12) == 1e3 ever
uint a11 = 1 megaever; // a11 == 1 000 000 000 000 000 (1e15) == 1e6 ever
uint a12 = 1 MEver; // a12 == 1 000 000 000 000 000 (1e15) == 1e6 ever
uint a13 = 1 gigaever; // a13 == 1 000 000 000 000 000 000 (1e18) == 1e9 ever
uint a14 = 1 GEver; // a14 == 1 000 000 000 000 000 000 (1e18) == 1e9 ever
```
```TVMSolidity
uint a0 = 1 nano; // a0 == 1 == 1e-9 ever
uint a1 = 1 nanovmshell; // a1 == 1 == 1e-9 ever
uint a3 = 1 vmshell; // a3 == 1 000 000 000 (1e9)
uint a4 = 1 VMShell; // a4 == 1 000 000 000 (1e9)
uint a5 = 1 micro; // a5 == 1 000 == 1e-6 ever
uint a6 = 1 microvmshell; // a6 == 1 000 == 1e-6 ever
uint a7 = 1 milli; // a7 == 1 000 000 == 1e-3 ever
uint a8 = 1 millivmshell; // a8 == 1 000 000 == 1e-3 ever
uint a9 = 1 kilovmshell; // a9 == 1 000 000 000 000 (1e12) == 1e3 ever
uint a10 = 1 kVMShell; // a10 == 1 000 000 000 000 (1e12) == 1e3 ever
uint a11 = 1 megavmshell; // a11 == 1 000 000 000 000 000 (1e15) == 1e6 ever
uint a12 = 1 MVMShell; // a12 == 1 000 000 000 000 000 (1e15) == 1e6 ever
uint a13 = 1 gigavmshell; // a13 == 1 000 000 000 000 000 000 (1e18) == 1e9 ever
uint a14 = 1 GVMShell; // a14 == 1 000 000 000 000 000 000 (1e18) == 1e9 ever
```
```TVMSolidity
uint a0 = 1 nano; // a0 == 1
uint a1 = 1 nanoton; // a1 == 1
uint a2 = 1 nTon; // a2 == 1
uint a3 = 1 ton; // a3 == 1 000 000 000 (1e9)
uint a4 = 1 Ton; // a4 == 1 000 000 000 (1e9)
uint a5 = 1 micro; // a5 == 1 000
uint a6 = 1 microton; // a6 == 1 000
uint a7 = 1 milli; // a7 == 1 000 000
uint a8 = 1 milliton; // a8 == 1 000 000
uint a9 = 1 kiloton; // a9 == 1 000 000 000 000 (1e12)
uint a10 = 1 kTon; // a10 == 1 000 000 000 000 (1e12)
uint a11 = 1 megaton; // a11 == 1 000 000 000 000 000 (1e15)
uint a12 = 1 MTon; // a12 == 1 000 000 000 000 000 (1e15)
uint a13 = 1 gigaton; // a13 == 1 000 000 000 000 000 000 (1e18)
uint a14 = 1 GTon; // a14 == 1 000 000 000 000 000 000 (1e18)
```
#### TvmCell
`TvmCell` represents *TVM cell* ([TVM][1] - 1.1.3). The compiler defines the following
operators and functions to work with this type:
Comparison operators:
`==`, `!=` (evaluate to `bool`)
##### constructing TvmCell
To create empty cell use `TvmCell()`. Example:
```TVMSolidity
TvmCell cell = ...;
if (cell == TvmCell()) { // check whether `cell` is empty
}
```
##### \<TvmCell\>.depth()
```TVMSolidity
<TvmCell>.depth() returns (uint16);
```
Returns the depth **d** of the `TvmCell` **c**. If **c** has no references, then **d** = 0;
otherwise **d** is equal to one plus the maximum of depths of cells referred to from **c**.
If **c** is a Null instead of a Cell, returns zero.
#### \<TvmCell\>.dataSize()
```TVMSolidity
<TvmCell>.dataSize(uint n) returns (uint /*cells*/, uint /*bits*/, uint /*refs*/);
```
Returns the number of distinct cells, data bits in the distinct cells and
cell references in the distinct cells. If number of the distinct cells
exceeds `n+1`, then a cell overflow [exception](#tvm-exception-codes) is thrown.
This function is a wrapper for the `CDATASIZE` opcode ([TVM][1] - A.11.7).
If `CapFastStorageStatBugfix` and `CapFastStorageStat` are set, then calculate number of total (not distinct) cells and bits. For example:
```TVMSolidity
TvmBuilder b2;
b2.storeOnes(5);
TvmBuilder b;
b.storeOnes(10);
b.storeRef(b2);
b.storeRef(b2);
b.storeRef(b2);
TvmCell cell = b.toCell();
(uint cells, uint bits, uint refs) = cell.dataSize(100);
// If `CapFastStorageStatBugfix` and `CapFastStorageStat` are set
// cells == 4
// bits == 10 + 3 * 5
// refs == 3
// Otherwise:
// cells == 2
// bits == 5 + 10
// refs == 3
```
#### \<TvmCell\>.dataSizeQ()
```TVMSolidity
<TvmCell>.dataSizeQ(uint n) returns (optional(uint /*cells*/, uint /*bits*/, uint /*refs*/));
```
Returns the number of distinct cells, data bits in the distinct cells and
cell references in the distinct cells. If number of the distinct cells
exceeds `n+1`, then this function returns an `optional` that has no value.
This function is a wrapper for the `CDATASIZEQ` opcode ([TVM][1] - A.11.7).
##### \<TvmCell\>.toSlice()
```TVMSolidity
<TvmCell>.toSlice() returns (TvmSlice);
```
Converts a `TvmCell` to `TvmSlice`.
If the cell is exotic, then the cell is automatically loaded and converted to `TvmSlice`. For example:
```
TvmCell cellProof = ...;
TvmBuilder b;
b.store(
uint8(3), // type of MerkleProof exotic cell
tvm.hash(cellProof),
cellProof.depth(),
cellProof
);
TvmCell merkleProof = b.toExoticCell();
TvmSlice s = merkleProof.toSlice();
// `s` has the same data and references as `cellProof`
```
If you want load the cell as is, then see [\<TvmCell\>.exoticToSlice()](#tvmcellexotictoslice).
##### \<TvmCell\>.exoticToSlice()
```TVMSolidity
<TvmCell>.exoticToSlice() returns (TvmSlice, bool)
```
Converts an ordinary or exotic cell into a `TvmSlice`, as if it were an ordinary cell. A flag is returned indicating whether
`TvmCell` is exotic. If that be the case, its type can later be deserialized from the first eight bits of `TvmSlice`.
Example:
```TVMSolidity
TvmCell cellProof = ...;
TvmBuilder b;
b.store(
uint8(3), // type of MerkleProof exotic cell
tvm.hash(cellProof),
cellProof.depth(),
cellProof
);
{
// convert builder to exotic cell
TvmCell merkleProof = b.toExoticCell();
(TvmSlice s, bool isExotic) = merkleProof.exoticToSlice();
// isExotic == true
uint8 flag = s.load(uint8); // flag == 3
}
{
// convert builder to ordinary cell
TvmCell cell = b.toCell();
(TvmSlice s, bool isExotic) = cell.exoticToSlice();
// isExotic == false
uint8 flag = s.load(uint8); // flag == 3
}
```
See also:
* [\<TvmBuilder\>.toExoticCell()](#tvmbuildertoexoticcell)
#### \<TvmCell\>.loadExoticCell() and \<TvmCell\>.loadExoticCellQ()
```TVMSolidity
(1)
<TvmCell>.loadExoticCell() returns (TvmCell)
(2)
<TvmCell>.loadExoticCellQ() returns (TvmCell cell, bool ok)
```
(1) Loads an exotic cell and returns an ordinary cell. If the cell is already ordinary, does nothing. If it cannot be loaded, throws an exception. It is wrapper for opcode `XLOAD`.
(2) Same as (1) but if it cannot be loaded, does not throw exception and `ok` is equal to `false`. It is wrapper for opcode `XLOADQ`.
Example:
```TVMSolidity
TvmCell cellProof = ...;
TvmBuilder b;
b.store(
uint8(3), // type of MerkleProof exotic cell
tvm.hash(cellProof),
cellProof.depth(),
cellProof
);
TvmCell cell = merkleProof.loadExoticCell(); // cell == cellProof
(TvmCell cell, bool ok) = merkleProof.loadExoticCellQ();
// cell == cellProof
// ok == true
```
#### TvmSlice
`TvmSlice` represents *TVM cell slice* ([TVM][1] - 1.1.3). The compiler defines the following
operators and functions to work with this type:
Comparison operators:
`<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to bool).
**Note:** only data bits from the root cells are compared. References are ignored.
String literals can be converted to `TvmSlice`:
```TVMSolidity
TvmSlice s = "0189abef_";
```
`TvmSlice` can be converted to `bytes`. It costs at least 500 gas units.
##### \<TvmSlice\>.empty(), \<TvmSlice\>.bitEmpty() and \<TvmSlice\>.refEmpty()
```TVMSolidity
(1)
<TvmSlice>.empty() returns (bool);
(2)
<TvmSlice>.bitEmpty() returns (bool);
3()
<TvmSlice>.refEmpty() returns (bool);
```
(1)
Checks whether the `TvmSlice` contains no data bits and no cell references.
(2)
Checks whether the `TvmSlice` contains no data bits.
(3)
Checks whether the `TvmSlice` contains no cell references.
##### \<TvmSlice\>.size()
```TVMSolidity
<TvmSlice>.size() returns (uint16 /*bits*/, uint8 /*refs*/);
```
Returns the number of data bits and references in the `TvmSlice`.
##### \<TvmSlice\>.bits()
```TVMSolidity
<TvmSlice>.bits() returns (uint16);
```
Returns the number of data bits in the `TvmSlice`.
##### \<TvmSlice\>.refs()
```TVMSolidity
<TvmSlice>.refs() returns (uint8);
```
Returns the number of references in the `TvmSlice`.
#### \<TvmSlice\>.dataSize()
```TVMSolidity
<TvmSlice>.dataSize(uint n) returns (uint /*cells*/, uint /*bits*/, uint /*refs*/);
```
Returns the number of distinct cells, data bits in the distinct cells and
cell references in the distinct cells. If number of the distinct cells
exceeds `n+1`, then a cell overflow [exception](#tvm-exception-codes) is thrown.
Note that the returned `count of distinct cells` does not take into
account the cell that contains the slice itself.
This function is a wrapper for `SDATASIZE` opcode ([TVM][1] - A.11.7).
#### \<TvmSlice\>.dataSizeQ()
```TVMSolidity
<TvmSlice>.dataSizeQ(uint n) returns (optional(uint /*cells*/, uint /*bits*/, uint /*refs*/));
```
Returns the number of distinct cells, data bits in the distinct cells and
cell references in the distinct cells. If number of the distinct cells
exceeds `n+1`, then this function returns an `optional` that has no value.
Note that the returned `count of distinct cells` does not take into
account the cell that contains the slice itself.
This function is a wrapper for `SDATASIZEQ` opcode ([TVM][1] - A.11.7).
##### \<TvmSlice\>.depth()
```TVMSolidity
<TvmSlice>.depth() returns (uint16);
```
Returns the depth of `TvmSlice`. If the `TvmSlice` has no references, then 0 is returned,
otherwise function result is one plus the maximum of depths of the cells referred to from the slice.
##### \<TvmSlice\>.hasNBits(), \<TvmSlice\>.hasNRefs() and \<TvmSlice\>.hasNBitsAndRefs()
```TVMSolidity
<TvmSlice>.hasNBits(uint10 bits) returns (bool);
<TvmSlice>.hasNRefs(uint2 refs) returns (bool);
<TvmSlice>.hasNBitsAndRefs(uint10 bits, uint2 refs) returns (bool);
```
Checks whether the `TvmSlice` contains the specified amount of data bits and references.
##### \<TvmSlice\>.compare()
```TVMSolidity
<TvmSlice>.compare(TvmSlice other) returns (int2);
```
Lexicographically compares the `slice` and `other` data bits of the root slices and returns result as an integer:
* 1 - `slice` > `other`
* 0 - `slice` == `other`
* -1 - `slice` < `other`
##### \<TvmSlice\>.startsWith()
```TVMSolidity
<TvmSlice>.startsWith(TvmSlice prefix) returns (bool);
```
Checks whether `prefix` is a prefix of `TvmSlice`.
##### \<TvmSlice\>.startsWithOne()
```TVMSolidity
<TvmSlice>.startsWithOne() returns (bool);
```
Checks whether the first bit of `TvmSlice` is a one.
##### TvmSlice load primitives
All `load*` functions below modify the `TvmSlice` object. If you wants to load second reference from the `TvmSlice`, you should load the first one with [\<TvmSlice\>.loadRef()](#tvmsliceloadref) and then load the reference you need. The same rule is applied to data bits. To load bits from 2 to 10 positions, you should load or skip first two bits.
###### \<TvmSlice\>.load()
```TVMSolidity
<TvmSlice>.load(TypeA, TypeB, ...) returns (TypeA /*a*/, TypeB /*b*/, ...);
```
Sequentially loads values of the specified types from the `TvmSlice`.
Supported types: `uintN`, `intN`, `bytesN`, `bool`, `ufixedMxN`, `fixedMxN`, `address`, `contract`,
`TvmCell`, `bytes`, `string`, `mapping`, `array`, `optional` and
`struct`. Example:
```TVMSolidity
TvmSlice slice = ...;
(uint8 a, uint16 b) = slice.load(uint8, uint16);
(uint16 num0, uint32 num1, address addr) = slice.load(uint16, uint32, address);
```
See also: [\<TvmBuilder\>.store()](#tvmbuilderstore).
**Note**: if all the argument types can't be loaded from the slice a cell underflow [exception](#tvm-exception-codes) is thrown.
###### \<TvmSlice\>.loadQ()
```TVMSolidity
<TvmSlice>.loadQ(TypeA, TypeB, ...) returns (optional(TypeA, TypeB, ...));
```
Sequentially decodes values of the specified types from the `TvmSlice`
if the `TvmSlice` holds sufficient data for all specified types. Otherwise, returns `null`.
```TVMSolidity
TvmSlice slice = ...;
optional(uint) a = slice.loadQ(uint);
optional(uint8, uint16) b = slice.loadQ(uint8, uint16);
```
See also: [\<TvmBuilder\>.store()](#tvmbuilderstore).
###### \<TvmSlice\>.loadRef()
```TVMSolidity
<TvmSlice>.loadRef() returns (TvmCell);
```
Loads a cell from the `TvmSlice` reference.
###### \<TvmSlice\>.loadRefAsSlice()
```TVMSolidity
<TvmSlice>.loadRefAsSlice() returns (TvmSlice);
```
Loads a cell from the `TvmSlice` reference and converts it into a `TvmSlice`.
###### \<TvmSlice\>.loadInt() and \<TvmSlice\>.loadIntQ()
```TVMSolidity
(1)
<TvmSlice>.loadInt(uint9 bitSize) returns (int);
(2)
<TvmSlice>.loadIntQ(uint9 bitSize) returns (optional(int));
```
(1) Loads a signed integer with the given **bitSize** from the `TvmSlice`.
(2) Loads a signed integer with the given **bitSize** from the `TvmSlice` if `TvmSlice` contains it. Otherwise, returns `null`.
###### \<TvmSlice\>.loadUint() and \<TvmSlice\>.loadUintQ()
```TVMSolidity
(1)
<TvmSlice>.loadUint(uint9 bitSize) returns (uint);
(2)
<TvmSlice>.loadUintQ(uint9 bitSize) returns (optional(uint));
```
(1) Loads an unsigned integer with the given **bitSize** from the `TvmSlice`.
(2) Loads an unsigned integer with the given **bitSize** from the `TvmSlice` if `TvmSlice` contains it. Otherwise, returns `null`.
###### Load little-endian integers
```TVMSolidity
(1)
<TvmSlice>.loadIntLE2() returns (int16)
<TvmSlice>.loadIntLE4() returns (int32)
<TvmSlice>.loadIntLE8() returns (int64)
<TvmSlice>.loadUintLE2() returns (uint16)
<TvmSlice>.loadUintLE4() returns (uint32)
<TvmSlice>.loadUintLE8() returns (uint64)
(2)
<TvmSlice>.loadIntLE4Q() returns (optional(int32))
<TvmSlice>.loadIntLE8Q() returns (optional(int64))
<TvmSlice>.loadUintLE4Q() returns (optional(uint32))
<TvmSlice>.loadUintLE8Q() returns (optional(uint64))
```
(1) Loads the little-endian integer from `TvmSlice`.
(2) Same as (1) but returns `null` if it's impossible to load the integer.
###### \<TvmSlice\>.loadSlice() and \<TvmSlice\>.loadSliceQ()
```TVMSolidity
(1)
<TvmSlice>.loadSlice(uint10 bits) returns (TvmSlice);
(2)
<TvmSlice>.loadSlice(uint10 bits, uint2 refs) returns (TvmSlice);
(3)
<TvmSlice>.loadSliceQ(uint10 bits) returns (optional(TvmSlice));
(4)
<TvmSlice>.loadSliceQ(uint10 bits, uint2 refs) returns (optional(TvmSlice));
```
(1) Loads the first `bits` bits from `TvmSlice`.
(2) Loads the first `bits` bits and `refs` references from `TvmSlice`.
(3) and (4) are same as (1) and (2) but return `optional` type.
###### \<TvmSlice\>.skip()
```TVMSolidity
<TvmSlice>.skip(uint10 bits);
<TvmSlice>.skip(uint10 bits, uint3 refs);
```
Skips the first `bits` bits and `refs` references from the `TvmSlice`.
###### \<TvmSlice\>.loadZeroes(), \<TvmSlice\>.loadOnes() and \<TvmSlice\>.loadSame()
```TVMSolidity
(1)
<TvmSlice>.loadZeroes() returns (uint10 n);
(2)
<TvmSlice>.loadOnes() returns (uint10 n);
(3)
<TvmSlice>.loadSame(uint1 value) returns (uint10 n);
```
(1) Returns the count `n` of leading zero bits in `TvmSlice`, and removes these bits from `TvmSlice`.
(2) Returns the count `n` of leading one bits in `TvmSlice`, and removes these bits from `TvmSlice`.
(3) Returns the count `n` of leading bits equal to `0 ≤ value ≤ 1` in `TvmSlice`, and removes these bits from `TvmSlice`.
See also: [\<TvmBuilder\>.storeZeroes(), \<TvmBuilder\>.storeOnes() and \<TvmBuilder\>.storeSame()](#tvmbuilderstorezeroes-tvmbuilderstoreones-and-tvmbuilderstoresame).
##### TvmSlice preload primitives
All `preload*` functions below don't modify the `TvmSlice` object.
###### \<TvmSlice\>.preload()
```TVMSolidity
<TvmSlice>.preload(TypeA, TypeB, ...) returns (TypeA /*a*/, TypeB /*b*/, ...);
```
Same as [\<TvmSlice\>.load()](#tvmsliceload) but doesn't modify `TvmSlice`.
###### \<TvmSlice\>.preloadQ()
```TVMSolidity
<TvmSlice>.preloadQ(TypeA, TypeB, ...) returns (optional(TypeA, TypeB, ...));
```
Same as [\<TvmSlice\>.loadQ()](#tvmsliceloadq) but doesn't modify `TvmSlice`.
###### \<TvmSlice\>.preloadRef()
```TVMSolidity
(1)
<TvmSlice>.preloadRef() returns (TvmCell);
(2)
<TvmSlice>.preloadRef(uint2 index) returns (TvmCell);
```
(1) Returns the first cell reference of `TvmSlice`.
(2) Returns the `index` cell reference of `TvmSlice`, where `0 ≤ index ≤ 3`.
###### \<TvmSlice\>.preloadInt() and \<TvmSlice\>.preloadIntQ()
```TVMSolidity
(1)
<TvmSlice>.preloadInt(uint9 bitSize) returns (int);
(2)
<TvmSlice>.preloadIntQ(uint9 bitSize) returns (optional(int));
```
Same as [\<TvmSlice\>.loadInt() and \<TvmSlice\>.loadIntQ()](#tvmsliceloadint-and-tvmsliceloadintq) but doesn't modify `TvmSlice`.
###### \<TvmSlice\>.preloadUint() and \<TvmSlice\>.preloadUintQ()
```TVMSolidity
(1)
<TvmSlice>.preloadUint(uint9 bitSize) returns (uint);
(2)
<TvmSlice>.preloadUintQ(uint9 bitSize) returns (optional(uint));
```
Same as [\<TvmSlice\>.loadUint() and \<TvmSlice\>.loadUintQ()](#tvmsliceloaduint-and-tvmsliceloaduintq) but doesn't modify `TvmSlice`.
###### Preload little-endian integers
```TVMSolidity
<TvmSlice>.preloadIntLE4() returns (int32)
<TvmSlice>.preloadIntLE8() returns (int64)
<TvmSlice>.preloadUintLE4() returns (uint32)
<TvmSlice>.preloadUintLE8() returns (uint64)
<TvmSlice>.preloadIntLE4Q() returns (optional(int32))
<TvmSlice>.preloadIntLE8Q() returns (optional(int64))
<TvmSlice>.preloadUintLE4Q() returns (optional(uint32))
<TvmSlice>.preloadUintLE8Q() returns (optional(uint64))
```
Same as [Load little-endian integers](#load-little-endian-integers) but doesn't modify `TvmSlice`.
###### \<TvmSlice\>.preloadSlice() and \<TvmSlice\>.preloadSliceQ()
```TVMSolidity
(1)
<TvmSlice>.preloadSlice(uint10 bits) returns (TvmSlice);
(2)
<TvmSlice>.preloadSlice(uint10 bits, uint refs) returns (TvmSlice);
(3)
<TvmSlice>.preloadSliceQ(uint10 bits) returns (optional(TvmSlice));
(4)
<TvmSlice>.preloadSliceQ(uint10 bits, uint4 refs) returns (optional(TvmSlice));
```
Same as [\<TvmSlice\>.loadSlice() and \<TvmSlice\>.loadSliceQ()](#tvmsliceloadslice-and-tvmsliceloadsliceq) but doesn't modify `TvmSlice`.
#### TvmBuilder
`TvmBuilder` represents *TVM cell builder* ([TVM][1] - 1.1.3). TVM Solidity compiler defines the following
functions to work with this type:
##### \<TvmBuilder\>.toSlice()
```TVMSolidity
<TvmBuilder>.toSlice() returns (TvmSlice);
```
Converts a `TvmBuilder` into `TvmSlice`.
##### \<TvmBuilder\>.toCell()
```TVMSolidity
<TvmBuilder>.toCell() returns (TvmCell);
```
Converts a `TvmBuilder` into `TvmCell`.
##### \<TvmBuilder\>.toExoticCell()
```TVMSolidity
<TvmBuilder>.toExoticCell() returns (TvmCell);
```
Creates an exotic cell from `TvmBuilder`. It is wrapper for opcodes `TRUE ENDXC`.
Examples:
```TVMSolidity
TvmCell cellProof = getCell();
TvmBuilder b;
b.store(
uint8(3), // type of MerkleProof exotic cell
tvm.hash(cellProof),
cellProof.depth(),
cellProof
);
TvmCell merkleProof = b.toExoticCell();
```
##### \<TvmBuilder\>.size()
```TVMSolidity
<TvmBuilder>.size() returns (uint16 /*bits*/, uint8 /*refs*/);
```
Returns the number of data bits and references already stored in the `TvmBuilder`.
##### \<TvmBuilder\>.bits()
```TVMSolidity
<TvmBuilder>.bits() returns (uint16);
```
Returns the number of data bits already stored in the `TvmBuilder`.
##### \<TvmBuilder\>.refs()
```TVMSolidity
<TvmBuilder>.refs() returns (uint8);
```
Returns the number of references already stored in the `TvmBuilder`.
##### \<TvmBuilder\>.remBits()
```TVMSolidity
<TvmBuilder>.remBits() returns (uint16);
```
Returns the number of data bits that can still be stored in the `TvmBuilder`.
##### \<TvmBuilder\>.remRefs()
```TVMSolidity
<TvmBuilder>.remRefs() returns (uint8);
```
Returns the number of references that can still be stored in the `TvmBuilder`.
##### \<TvmBuilder\>.remBitsAndRefs()
```TVMSolidity
<TvmBuilder>.remBitsAndRefs() returns (uint16 /*bits*/, uint8 /*refs*/);
```
Returns the number of data bits and references that can still be stored in the `TvmBuilder`.
##### \<TvmBuilder\>.depth()
```TVMSolidity
<TvmBuilder>.depth() returns (uint16);
```
Returns the depth of `TvmBuilder`. If no cell references are stored
in the builder, then 0 is returned; otherwise function result is one plus the maximum of
depths of cells referred to from the builder.
##### \<TvmBuilder\>.store()
```TVMSolidity
<TvmBuilder>.store(/*list_of_values*/);
```
Stores the list of values into the `TvmBuilder`.
Internal representation of the stored data:
* `uintN`/`intN`/`bytesN` - stored as an N-bit string.
For example, `uint8(100), int16(-3), bytes2(0xaabb)` stored as `0x64fffdaabb`.
* `bool` - stored as a binary zero for `false` or a binary one for `true`. For example,
`true, false, true` stored as `0xb_`.
* `ufixedMxN`/`fixedMxN` - stored as an M-bit string.
* `address`/`contract` - stored according to the [TL-B scheme][3] of `MsgAddress`.
* `TvmCell`/`bytes`/`string` - stored as a cell in reference.
* `TvmSlice`/`TvmBuilder` - all data bits and references of the `TvmSlice` or the `TvmBuilder`
are appended to the `TvmBuilder`, not in a reference as `TvmCell`. To store `TvmSlice`/`TvmBuilder` in
the references use [\<TvmBuilder\>.storeRef()](#tvmbuilderstoreref).
* `mapping` - stored according to the [TL-B scheme][3] of `HashmapE`: if map is
empty, then stored as a binary zero, otherwise as a binary one and the dictionary `Hashmap` in a reference.
* `array` - stored as a 32 bit value - size of the array and a `HashmapE` that contains all values of
the array.
* `optional` - stored as a binary zero if the `optional` doesn't contain value. Otherwise, stored as
a binary one and the cell with serialized value in a reference.
* `struct` - stored in the order of its members in the builder. Make sure the entire struct fits into the
builder.
**Note:** there is no gap or offset between two consecutive data assets stored in the `TvmBuilder`.
See [TVM][1] to read about notation for bit strings.
Example:
```TVMSolidity
uint8 a = 11;
int16 b = 22;
TvmBuilder builder;
builder.store(a, b, uint(33));
```
See also: [\<TvmSlice\>.load()](#tvmsliceload).
##### \<TvmBuilder\>.storeQ()
```TVMSolidity
<TvmBuilder>.storeQ(T value) returns (bool ok);
```
Same as [\<TvmBuilder\>.store()](#tvmbuilderstore) but returns the success flag. It does not throw exceptions.
Supported types:
* `uintN`/`intN`/`bytesN`
* `bool`
* `ufixedMxN`/`fixedMxN`
* `address`/`contract`
* `TvmCell`/`bytes`/`string`
* `TvmSlice`/`TvmBuilder`
##### \<TvmBuilder\>.storeZeroes(), \<TvmBuilder\>.storeOnes() and \<TvmBuilder\>.storeSame()
```TVMSolidity
(1)
<TvmBuilder>.storeZeroes(uint10 n);
(2)
<TvmBuilder>.storeOnes(uint10 n);
(3)
<TvmBuilder>.storeSame(uint10 n, uint1 value);
```
(1) Stores `n` binary zeroes into the `TvmBuilder`.
(2) Stores `n` binary ones into the `TvmBuilder`.
(3) Stores `n` binary `value`s (0 ≤ value ≤ 1) into the `TvmBuilder`.
See also: [\<TvmSlice\>.loadZeroes(), \<TvmSlice\>.loadOnes() and \<TvmSlice\>.loadSame()](#tvmsliceloadzeroes-tvmsliceloadones-and-tvmsliceloadsame).
##### \<TvmBuilder\>.storeInt()
```TVMSolidity
<TvmBuilder>.storeInt(int257 value, uint9 bitSize);
```
Stores a signed integer **value** with given **bitSize** in the `TvmBuilder`.
##### \<TvmBuilder\>.storeUint()
```TVMSolidity
<TvmBuilder>.storeUint(uint256 value, uint9 bitSize);
```
Stores an unsigned integer **value** with given **bitSize** in the `TvmBuilder`.
##### Store little-endian integers
```TVMSolidity
<TvmBuilder>.storeIntLE2(int16)
<TvmBuilder>.storeIntLE4(int32)
<TvmBuilder>.storeIntLE8(int64)
<TvmBuilder>.storeUintLE2(uint16)
<TvmBuilder>.storeUintLE4(uint32)
<TvmBuilder>.storeUintLE8(uint64)
```
Stores the little-endian integer.
##### \<TvmBuilder\>.storeRef()
```TVMSolidity
<TvmBuilder>.storeRef(TvmBuilder b);
<TvmBuilder>.storeRef(TvmCell c);
<TvmBuilder>.storeRef(TvmSlice s);
```
Stores `TvmBuilder b`/`TvmCell c`/`TvmSlice s` in the reference of the `TvmBuilder`.
#### StringBuilder
A mutable sequence of characters. `StringBuilder` allows creating a string from `bytes1` and `string` in a gas-efficient way. Example:
```TVMSolidity
StringBuilder b;
b.append(bytes1("-"));
b.append(bytes1("0"), 10);
b.append("1234");
string s = b.toString(); // s == "-00000000001234"
```
##### \<StringBuilder\>.append()
```TVMSolidity
(1)
<StringBuilder>.append(bytes1);
(2)
<StringBuilder>.append(bytes1, uint31 n);
(3)
<StringBuilder>.append(string);
```
(1) Appends `bytes1` to the sequence.
(2) Appends `bytes1` `n` times to the sequence.
(3) Appends `string` to the sequence.
##### \<StringBuilder\>.toString()
```TVMSolidity
<StringBuilder>.toString();
```
Returns a string representing the data in this sequence.
#### optional(T)
The template optional type manages an optional contained value, i.e. a value that may or may not be present.
##### constructing an optional
There are many ways to set a value:
```TVMSolidity
optional(uint) opt;
opt.set(11); // just sets value
opt = 22; // just sets value, too
opt.get() = 33; // if 'opt' has value, then set value. Otherwise throws an exception.
optional(uint) another = 44;
opt = another;
```
##### \<optional(T)\>.hasValue()
```TVMSolidity
<optional(T)>.hasValue() returns (bool);
```
Checks whether the `optional` contains a value.
##### \<optional(T)\>.get()
```TVMSolidity
<optional(T)>.get() returns (T);
```
Returns the contained value, if the `optional` contains one. Otherwise, throws an exception.
##### \<optional(T)\>.getOr()
```TVMSolidity
<optional(T)>.getOr(T default) returns (T);
```
Returns the contained value, if the `optional` contains one. Otherwise, returns `default`.
##### \<optional(T)\>.getOrDefault()
```TVMSolidity
<optional(T)>.getOrDefault() returns (T);
```
Returns the contained value, if the `optional` contains one. Otherwise, returns the default value for `T` type.
##### \<optional(T)\>.set()
```TVMSolidity
<optional(T)>.set(Type value);
```
Replaces content of the `optional` with **value**.
##### Keyword `null`
Keyword `null` is a constant that is used to indicate an optional type with uninitialized state.
Example:
```TVMSolidity
optional(uint) x = 123;
x = null; // reset value
```
#### variant
The `variant` type acts like a union for the most common solidity data types. Supported only `uint` so far.
#### variant.isUint()
```TVMSolidity
<variant>.isUint() returns (bool)
```
Checks whether `<variant>` holds `uint` type.
#### variant.toUint()
Converts `<variant>` to `uint` type if it's possible. Otherwise, throws an exception with code `77`.
#### vector(T)
`vector(T)` is a template container type for storing values of a same type, pretty much like [dynamic-sized array](#arrays).
Two major differences are that `vector(T)`:
1. is much more efficient than a [dynamic-sized array](#arrays);
2. has a lifespan of a smart-contract execution, so it can't be neither passed nor returned as an external function call parameter, nor stored in a state variable.
**Note:** `vector` implementation based on `TVM Tuple` type, and it has a limited length of 255 values.
Example:
```TVMSolidity
vector(int) arr;
arr.push(100); // arr == [100]
arr.push(200); // arr == [100, 200]
arr.push(300); // arr == [100, 200, 300]
uint8 len = arr.length(); // len == 3
int value1 = arr[1]; // value1 == 200
arr[1] = 222; // arr == [100, 222, 300]
int last = arr.last(); // last == 300, arr == [100, 222, 300]
last = arr.pop(); // last == 300, arr == [100, 222]
last = arr.pop(); // last == 222, arr == [100]
last = arr.pop(); // last == 100, arr == []
bool isEmpty = arr.empty(); // isEmpty == true
```
##### \<vector(T)\>.push()
```TVMSolidity
<vector(T)>.push(T element);
```
Appends **element** to the `vector`.
##### \<vector(T)\>.pop()
```TVMSolidity
<vector(T)>.pop() returns (T);
```
Pops the last value from the `vector` and returns it.
##### \<vector(T)\>.last()
```TVMSolidity
<vector(T)>.last() returns (T);
```
Returns the last value from the `vector`.
##### \<vector(T)\>.operator[]
```TVMSolidity
<vector(T)>.operator[](uint index) returns (T);
```
Returns the value located at the `index` position. If `index` is not within the range of the container, an exception is thrown.
##### \<vector(T)\>.length()
```TVMSolidity
<vector(T)>.length() returns (uint8);
```
Returns length of the `vector`.
##### \<vector(T)\>.empty()
```TVMSolidity
<vector(T)>.empty() returns (bool);
```
Checks whether the `vector` is empty.
##### stack(T)
`stack` represents a last-in-first-out (LIFO) stack of items. The usual push and pop operations are provided, as well as a method to peek at the top item on the stack, a method to test for whether the stack is empty.
```TVMSolidity
stack(int) st;
st.push(100);
st.push(200);
bool isEmpty = st.empty(); // isEmpty == false
int item = st.top(); // item == 200, st == [100, 200]
st.top() += 25; // st == [100, 225]
item = st.top(); // item == 225, st == [100, 225]
item = st.pop(); // item == 225, st == [100]
item = st.pop(); // item == 100, st == []
isEmpty = st.empty(); // isEmpty == true
```
##### \<stack(T)\>.push()
```TVMSolidity
<stack(T)>.push(T item)
```
Pushes an item onto the top of this stack.
##### \<stack(T)\>.pop()
```TVMSolidity
<stack(T)>.pop() returns (T)
```
Removes the item at the top of this stack and returns that item as the value of this function.
##### \<stack(T)\>.top()
```TVMSolidity
<stack(T)>.top() returns (ref T)
```
Returns reference at the item at the top of this stack without removing it from the stack. Example:
```TVMSolidity
stack(int) st;
st.push(200);
st.top() += 25; // st == [225]
int item = st.top(); // item = 225, st == [225]
```
##### \<stack(T)\>.empty()
```TVMSolidity
<stack(T)>.empty() returns (bool)
```
Checks whether the `stack` is empty.
##### \<stack(T)\>.sort()
```TVMSolidity
<stack(T)>.sort(function(Type, Type) internal pure returns(bool) isLess)
```
Sorts the specified stack into ascending order. Example:
```TVMSolidity
struct Point {
int x;
int y;
}
function less(Point a, Point b) private pure returns(bool) {
return a.x < b.x || a.x == b.x && a.y < b.y;
}
function testPoints() public pure {
stack(Point) st;
st.push(Point(20, 40));
st.push(Point(10, 10));
st.push(Point(20, 30));
st.sort(less);
Point p;
p = st.pop(); // p == Point(10, 10)
p = st.pop(); // p == Point(20, 30)
p = st.pop(); // p == Point(20, 40)
}
```
##### \<stack(T)\>.reverse()
```TVMSolidity
<stack(T)>.reverse()
```
Reverses the order of the elements in the specified stack. Example:
```TVMSolidity
stack(int) st;
st.push(100);
st.push(200);
st.push(300);
int value = st.top(); // value == 300
st.reverse();
value = st.pop(); // value == 100
value = st.pop(); // value == 200
value = st.pop(); // value == 300
```
### TVM specific control structures
### Range-based for loop
Executes a `for` loop over a range. Used as a more readable equivalent to the traditional `for` loop
operating over a range of values, such as all elements in an array or mapping.
```TVMSolidity
for ( range_declaration : range_expression ) loop_statement
```
`range_expression` is calculated only once, and the result is copied. Then iteration goes over the copy of
the array or mapping.
```TVMSolidity
uint[] arr = ...;
uint sum = 0;
for (uint val : arr) { // iteration over the array
sum += val;
}
bytes byteArray = "Hello!";
for (byte b : byteArray) { // iteration over the byte array
}
mapping(uint32 => uint) map = ...;
uint keySum = 0;
uint valueSum = 0;
for ((uint32 key, uint value) : map) { // iteration over the mapping
keySum += key;
valueSum += value;
}
```
Key or value can be omitted if you iterate over a mapping:
```TVMSolidity
mapping(uint32 => uint) map = ...;
uint keySum = 0;
for ((uint32 key, ) : map) { // value is omitted
keySum += key;
}
uint valueSum = 0;
for ((, uint value) : map) { // key is omitted
valueSum += value;
}
```
#### repeat
```TVMSolidity
repeat (exression) statement
```
Allows repeating the block of code several times. `exression` evaluates only one time.
```TVMSolidity
uint a = 0;
repeat(10) {
++a;
}
// a == 10
```
#### try-catch
[Capabilities](#tvm-capabilities) required: `CapsTvmBugfixes2022`.
The `try` statement allows you to define a block of code to be tested for errors while it is executed. The
`catch` statement allows you to define a block of code to be executed, if an error occurs in the try block.
`catch` block gets two parameters of type variant and uint16, which contain exception argument and code respectively.
Example:
```TVMSolidity
TvmBuilder builder;
uint c = 0;
try {
c = a + b;
require(c != 42, 100, 22);
require(c != 43, 100, 33);
builder.store(c);
} catch (variant value, uint16 errorCode) {
uint errorValue;
if (value.isUint()) {
errorValue = value.toUint();
}
if (errorCode == 100) {
if (errorValue == 22) {
// it was line: `require(c != 42, 100, 22);`
} else if (errorValue == 33) {
// it was line: `require(c != 43, 100, 33);`
}
} else if (errorCode == 8) {
// Cell overflow
// It was line: `builder.store(c);`
} else if (errorCode == 4) {
// Integer overflow
// It was line: `c = a + b;`
}
}
```
You can pass either of the parameters:
```TVMSolidity
uint c;
try {
c = a + b;
} catch (variant , uint16 errorCode) {
if (errorCode == 4) {
}
}
```
Or you can pass all parameters:
```TVMSolidity
uint c;
try {
c = a + b;
} catch {
}
```
#### unchecked block
```TVMSolidity
unchecked {
/* */
}
```
Turns off reverting on over- and underflow for arithmetic operations in `unchecked` block. It is up to programmer to control range of integer types if they use `unchecked` blocks. For example:
```TVMSolidity
function f(uint8 a, uint8 b) pure private returns (uint8) {
unchecked {
uint8 c = a - b;
return c;
}
}
function g(uint8 a, uint8 b) pure private returns (uint8) {
uint8 c = a - b;
return c;
}
```
The call to `f(2, 3)` will return `-1`, while `g(2, 3)` will cause a failing assertion.
See also: [pragma ignoreIntOverflow](#pragma-ignoreintoverflow).
### Changes and extensions in Solidity types
#### Integers
`int` / `uint`: Signed and unsigned integers of various sizes.
Keywords `uint1` to `uint256` in steps of 1 (unsigned of 1 up to 256 bits) and `int1` to `int257`. `uint` and `int` are aliases for `uint256` and `int257`, respectively.
Operators:
* Comparison: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation)
* Shift operators: `<<` (left shift), `>>` (right shift)
* Arithmetic operators: `+`, `-`, unary `-`, `*`, `/`, `%` (modulo), `**` (exponentiation)
##### \<Integer\>.cast()
```TVMSolidity
<Integer>.cast(T) returns (T)
```
Convert `<Integer>` to T type. `T` is integer type. Type of `<Integer>` and `T` must have same sign or bit-size. Never throws an exception. For example:
```TVMSolidity
uint8 a = 255;
uint4 b = a.cast(uint4); // b == 15
uint8 a = 255;
int8 b = a.cast(int8); // b == -1
uint8 a = 255;
int4 b = a.cast(uint4).cast(int4); // b == -1
uint8 a = 255;
// int4 b = a.cast(int4); // compilation fail
```
**Note:** conversion via `T(x)` throws an exception if `x` does not fit into `T` type. For example:
```TVMSolidity
uint8 a = 10;
uint4 b = uint4(a); // OK, a == 10
uint8 a = 100;
uint4 b = uint4(a); // throws an exception because type(uint4).max == 15
int8 a = -1;
uint8 b = uint8(a); // throws an exception because type(uint8).min == 0
```
##### bitSize() and uBitSize()
```TVMSolidity
bitSize(int x) returns (uint16)
uBitSize(uint x) returns (uint16)
```
`bitSize` computes the smallest `c` ≥ 0 such that `x` fits into a `c`-bit signed integer
(−2<sup>c−1</sup> ≤ x < 2<sup>c−1</sup>).
`uBitSize` computes the smallest `c` ≥ 0 such that `x` fits into a `c`-bit unsigned integer
(0 ≤ x < 2<sup>c</sup>).
Example:
```TVMSolidity
uint16 s = bitSize(12); // s == 5
uint16 s = bitSize(1); // s == 2
uint16 s = bitSize(-1); // s == 1
uint16 s = bitSize(0); // s == 0
uint16 s = uBitSize(10); // s == 4
uint16 s = uBitSize(1); // s == 1
uint16 s = uBitSize(0); // s == 0
```
#### Quiet arithmetic
Operations with `qintN` / `quintN` return `NaN` instead of throwing integer overflow exceptions if the results do not fit in type, or if one of their arguments is a `NaN`. Default value for `qintN` / `quintN` is `0`, for `qbool` - `false`.
##### qintN and quintN
`qint` / `quint`: Signed and unsigned integers of various sizes.
Keywords `quint1` to `quint256` in steps of 1 (unsigned of 1 up to 256 bits) and `qint1` to `qint257`. `quint` and `qint` are aliases for `quint256` and `qint257`, respectively.
Operators:
* Comparison: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to [qbool](#qbool))
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation)
* Shift operators: `<<` (left shift), `>>` (right shift)
* Arithmetic operators: `+`, `-`, unary `-`, `*`, `/`, `%` (modulo), `**` (exponentiation)
If one operand of bitwise “or” (`|`) is equal to −1, the result
is always −1, even if the other argument is a `NaN`;
If one operand of bitwise “and” (`&`) is equal to 0, the result
is always 0, even if the other argument is a `NaN`;
If one operand of `==` (`!=`) is equal to `NaN`, the result
is always `NaN`.
All [math namespace](#math-namespace) functions support quiet arithmetic.
##### qbool
`qbool` can have 3 values: `true`, `false` and `NaN`.
Operators:
* `!` (logical negation)
* `&&` (logical conjunction, “and”)
* `||` (logical disjunction, “or”)
* `==` (equality)
* `!=` (inequality)
The operators `||` and `&&` apply the common short-circuiting rules. This means that in the expression `f(x) || g(y)`, if `f(x)` evaluates to true, `g(y)` will not be evaluated even if it may have side-effects.
If one operand of logical “or” (`|`) is equal to `true` , the result
is always `true`, even if the other argument is a `NaN`;
If one operand of logical “and” (`&`) is equal to `false`, the result
is always `false`, even if the other argument is a `NaN`;
If one operand of `==` (`!=`) is equal to `NaN`, the result
is always `NaN`.
```TVMSolidity
function f(quint32 a, quint32 b, quint32 c, quint32 d) private {
qbool less = a * b < c * d;
if (less.isNaN()) {
// ...
} else {
bool l = less.get();
// ...
}
}
```
##### Keyword NaN
The `NaN` constant returns a nan (Not a Number) value. This value is not a legal number. Example:
```TVMSolidity
qint32 x = NaN;
qbool y = NaN;
```
##### \<T\>.isNaN()
```TVMSolidity
<T>.isNaN() returns (bool)
```
Checks whether `<T>` is `NaN`. `T` is `qintN`, `quintN` or `qbool`. Example:
```TVMSolidity
function checkOverflow(quint32 a, quint32 b) private pure returns(bool) {
quint32 s = a + b;
return s.isNaN();
}
```
##### \<T\>.get()
```TVMSolidity
<T>.get() returns (T2)
```
Returns "non-quiet" integer. If `<T>` is `NaN`, then throws an exception. `T` is `qintN`, `quintN` or `qbool`. Example:
```TVMSolidity
function f(quint32 a, quint32 b) private pure {
quint32 s = a + b;
if (!s.isNaN()) {
uint32 ss = s.get();
// ...
}
}
```
##### \<T\>.getOr()
```TVMSolidity
<T>.getOr(T2 default) returns (T2)
```
Returns "non-quiet" integer. If `<T>` is `NaN`, then returns `default`. `T` is `qintN`, `quintN` or `qbool`. Example:
```TVMSolidity
function f(quint32 a, quint32 b) private pure {
quint32 s = a + b;
uint32 ss = s.getOr(42); // ss is equal to `a + b` or 42
// ...
}
```
##### \<T\>.getOrDefault()
```TVMSolidity
<T>.getOrDefault() returns (T2)
```
Returns "non-quiet" integer. If `<T>` is `NaN`, then returns default value. `T` is `qintN`, `quintN` or `qbool`. Example:
```TVMSolidity
function f(quint32 a, quint32 b) private pure {
quint32 s = a + b;
uint32 ss = s.getOrDefault(); // ss is equal to `a + b` or 0
// ...
}
```
##### \<T\>.toOptional()
```TVMSolidity
<T>.toOptional() returns (optional(T2))
```
Returns optional integer. If `<T>` is `NaN`, then returns [null](#keyword-null). `T` is `qintN`, `quintN` or `qbool`. Example:
```TVMSolidity
function f(quint32 a, quint32 b) private pure {
quint32 s = a + b;
optional(uint32) ss = s.toOptional(); // ss is equal to `a + b` or null
// ...
}
```
#### varint and varuint
`varint`/`varint16`/`varint32`/`varuint`/`varuint16`/`coins`/`varuint32` are kinds of [Integer](#integers)
types. But they are serialized/deserialized according to [their TLB schemes](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L112).
These schemes are effective if you want to store or send integers, and they usually have small size.
Use these types only if you are sure.
`varint` is equal to `varint32`, `varint32` - `int248` , `varint16` - `int120`.
`varuint` is equal to `varuint32`, `varuint32` - `uint248` , `varuint16` - `uint120`.
`coins` is an alias for `varuint16`.
Example:
```TVMSolidity
mapping(uint => varint) m_map; // use `varint` as mapping value only if values have small size
m_map[10] = 15;
```
Operators:
* Comparison: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation)
* Shift operators: `<<` (left shift), `>>` (right shift)
* Arithmetic operators: `+`, `-`, unary `-`, `*`, `/`, `%` (modulo), `**` (exponentiation)
#### struct
Structs are custom defined types that can group several variables.
##### struct constructor
```TVMSolidity
struct Stakes {
uint total;
mapping(uint => uint) stakes;
}
// create struct with default values of its members
Stakes stakes;
// create struct using parameters
mapping(uint => uint) values;
values[100] = 200;
Stakes stakes = Stakes(200, values);
// create struct using named parameters
Stakes stakes = Stakes({stakes: values, total: 200});
```
##### \<struct\>.unpack()
```TVMSolidity
<struct>.unpack() returns (TypeA /*a*/, TypeB /*b*/, ...);
```
Unpacks all members stored in the `struct`.
Example:
```TVMSolidity
struct MyStruct {
uint a;
int b;
address c;
}
function f() pure public {
MyStruct s = MyStruct(1, -1, address(2));
(uint a, int b, address c) = s.unpack();
}
```
#### Arrays
##### Array literals
An array literal is a comma-separated list of one or more expressions, enclosed in square brackets.
For example: `[100, 200, 300]`.
Initializing constant state variable:
`uint[] constant fib = [uint(2), 3, 5, 8, 12, 20, 32];`
##### Creating new arrays
```TVMSolidity
uint[] arr; // create 0-length array
uint[] arr = new uint[](0); // create 0-length array
uint constant N = 5;
uint[] arr = new uint[](N); // create 5-length array
uint[] arr = new uint[](10); // create 10-length array
```
Note: If `N` is constant expression or integer literal, then the complexity of array creation -
`O(1)`. Otherwise, `O(N)`.
##### \<array\>.empty()
```TVMSolidity
<array>.empty() returns (bool);
```
Returns status flag whether the `array` is empty (its length is 0).
Example:
```TVMSolidity
uint[] arr;
bool b = arr.empty(); // b == true
arr.push(...);
bool b = arr.empty(); // b == false
```
#### bytesN
Variables of the `bytesN` types can be explicitly converted to `bytes`. Note: it costs ~500 gas.
```TVMSolidity
bytes3 b3 = 0x112233;
bytes b = bytes(b3);
```
#### bytes
`bytes` is an array of `byte`. It is similar to `byte[]`, but they are encoded in different ways.
Example of `bytes` initialization:
```TVMSolidity
// initialised with string
bytes a = "abzABZ0129";
// initialised with hex data
bytes b = hex"01239abf";
```
`bytes` can be converted to `TvmSlice`. Warning: if length of the array is greater than 127, then extra bytes are stored in the first reference of the slice. Use [\<TvmSlice\>.loadRef()](#tvmsliceloadref) to load that extra bytes.
##### \<bytes\>.empty()
```TVMSolidity
<bytes>.empty() returns (bool);
```
Returns status flag whether the `bytes` is empty (its length is 0).
##### \<bytes\>.operator[]
```TVMSolidity
<bytes>.operator[](uint index) returns (byte);
```
Returns the byte located at the **index** position.
Example:
```TVMSolidity
bytes byteArray = "abba";
int index = 0;
byte a0 = byteArray[index]; // a0 = 0x61
```
##### \<bytes\> slice
```TVMSolidity
<bytes>.operator[](uint from, uint to) returns (bytes);
```
Returns the slice of `bytes` [**from**, **to**), including **from** byte and
excluding **to**.
Example:
```TVMSolidity
bytes byteArray = "01234567890123456789";
bytes slice = byteArray[5:10]; // slice == "56789"
slice = byteArray[10:]; // slice == "0123456789"
slice = byteArray[:10]; // slice == "0123456789"
slice = byteArray[:]; // slice == "01234567890123456789"
```
##### \<bytes\>.length
```TVMSolidity
<bytes>.length returns (uint)
```
Returns length of the `bytes` array.
##### \<bytes\>.dataSize()
```TVMSolidity
<bytes>.dataSize(uint n) returns (uint /*cells*/, uint /*bits*/, uint /*refs*/);
```
Same as [\<TvmCell\>.dataSize()](#tvmcelldatasize).
##### \<bytes\>.dataSizeQ()
```TVMSolidity
<bytes>.dataSizeQ(uint n) returns (optional(uint /*cells*/, uint /*bits*/, uint /*refs*/));
```
Same as [\<TvmCell\>.dataSizeQ()](#tvmcelldatasizeq).
##### \<bytes\>.append()
```TVMSolidity
<bytes>.append(bytes tail);
```
Modifies the `bytes` by concatenating **tail** data to the end of the `bytes`.
##### bytes conversion
```TVMSolidity
bytes byteArray = "1234";
bytes4 bb = byteArray;
```
`bytes` can be converted to `bytesN`.
If `bytes` object has less than **N** bytes, extra bytes are padded with zero bits.
#### string
TVM Solidity compiler expands `string` type with the following functions:
**Note**: Due to VM restrictions string length can't exceed `1024 * 127 = 130048` bytes.
`string` can be converted to `TvmSlice`.
##### \<string\>.empty()
```TVMSolidity
<string>.empty() returns (bool);
```
Returns status flag whether the `string` is empty (its length is 0).
##### \<string\>.byteLength()
```TVMSolidity
<string>.byteLength() returns (uint32);
```
Returns byte length of the `string` data.
##### \<string\>.substr()
```TVMSolidity
(1)
<string>.substr(uint pos) returns (string);
(2)
<string>.substr(uint pos, uint count) returns (string);
```
(1) Returns a string that is a substring of this string. The substring begins with the character at the specified `pos` and extends to the end of this string.
(2) Returns a string that is a substring of this string. The substring begins with the character at the specified `pos` and copies at most `count` characters from the source string. If the string is shorter, as many characters as possible are used.
Throws an exception if `pos > string.byteLength()`.
```TVMSolidity
string text = "0123456789";
string a = text.substr(1, 2); // a = "12"
string b = text.substr(6); // b = "6789"
string c = text.substr(6, 100); // c = "6789"
string d = text.substr(777); // throws an exception
```
**Note:** if [Array Slices](https://docs.soliditylang.org/en/latest/types.html#array-slices) are used (they are written as `x[start:end]`), then `0 <= start <= end <= byteLength()`.
```TVMSolidity
string str = "01234567890";
string c = text.substr(6, 100); // c = "6789"
string d = text[6:106]; // throws an exception
```
##### \<string\>.append()
```TVMSolidity
<string>.append(string tail);
```
Appends the tail `string` to the `string`.
##### \<string\>.operator+
```TVMSolidity
<string>.operator+(string) returns (string);
<string>.operator+(bytesN) returns (string);
```
Creates new `string` as a concatenation of left and right arguments of the operator +. Example:
```TVMSolidity
string a = "abc";
bytes2 b = "12";
string c = a + b; // "abc12"
```
##### \<string\>.find() and \<string\>.findLast()
```TVMSolidity
<string>.find(bytes1 symbol) returns (optional(uint32));
<string>.find(string substr) returns (optional(uint32));
<string>.findLast(bytes1 symbol) returns (optional(uint32));
```
Looks for **symbol** (or substring) in the `string` and returns index of the first (`find`) or the
last (`findLast`) occurrence. If there is no such symbol in the `string`, an empty optional is returned.
Example:
```TVMSolidity
string str = "01234567890";
optional(uint32) a = str.find(byte('0'));
bool s = a.hasValue(); // s == true
uint32 n = a.get(); // n == 0
byte symbol = 'a';
optional(uint32) b = str.findLast(symbol);
bool s = b.hasValue(); // s == false
string sub = "111";
optional(uint32) c = str.find(sub);
bool s = c.hasValue(); // s == false
```
##### \<string\>.dataSize()
```TVMSolidity
<string>.dataSize(uint n) returns (uint /*cells*/, uint /*bits*/, uint /*refs*/);
```
Same as [\<TvmCell\>.dataSize()](#tvmcelldatasize).
##### \<string\>.dataSizeQ()
```TVMSolidity
<string>.dataSizeQ(uint n) returns (optional(uint /*cells*/, uint /*bits*/, uint /*refs*/));
```
Same as [\<TvmCell\>.dataSizeQ()](#tvmcelldatasizeq).
##### \<string\>.toUpperCase()` and \<string\>.toLowerCase()
```TVMSolidity
<string>.toUpperCase() returns (string)
<string>.toLowerCase() returns (string)
```
Converts `string` to upper/lower case. It treats `string` as ASCII string and converts only 'A'..'Z'
and 'a'..'z' symbols. Example:
```TVMSolidity
string s = "Hello";
string a = s.toUpperCase(); // a == "HELLO"
string b = s.toLowerCase(); // b == "hello"
```
##### format()
```TvmSolidity
format(string template, TypeA a, TypeB b, ...) returns (string);
```
Builds a `string` with arbitrary parameters. Empty placeholder `{}` can be filled with integer
(in decimal view), address, string or fixed point number. Fixed point number is printed
based on its type (`fixedMxN` is printed with `N` digits after dot).
Placeholder should be specified in such formats:
* `"{}"` - empty placeholder
* `"{:[0]<width>{"x","d","X","t"}}"` - placeholder for integers. Fills num with 0 if format starts with "0".
Formats integer to have specified `width`. Can format integers in decimal ("d" postfix), lower hex ("x")
or upper hex ("X") form. Format "t" prints number (in nanoevers) as a fixed point sum.
Warning: this function consumes too much gas, that's why it's better not to use it onchain.
Example:
```TVMSolidity
string str = format("Hello {} 0x{:X} {} {}.{} evers", 123, 255, address.makeAddrStd(-33,0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF123456789ABCDE), 100500, 32);
// str == "Hello 123 0xFF -21:7fffffffffffffffffffffffffffffffffffffffffffffffff123456789abcde 100500.32 evers"
str = format("Hello {}", 123); // str == "Hello 123"
str = format("Hello 0x{:X}", 123); // str == "Hello 0x7B"
str = format("{}", -123); // str == "-123"
str = format("{}", address.makeAddrStd(127,0)); // str == "7f:0000000000000000000000000000000000000000000000000000000000000000"
str = format("{}", address.makeAddrStd(-128,0)); // str == "-80:0000000000000000000000000000000000000000000000000000000000000000"
str = format("{:6}", 123); // str == " 123"
str = format("{:06}", 123); // str == "000123"
str = format("{:06d}", 123); // str == "000123"
str = format("{:06X}", 123); // str == "00007B"
str = format("{:6x}", 123); // str == " 7b"
uint128 a = 1 ever;
str = format("{:t}", a); // str == "1.000000000"
a = 123;
str = format("{:t}", a); // str == "0.000000123"
fixed32x3 v = 1.5;
str = format("{}", v); // str == "1.500"
fixed256x10 vv = -987123.4567890321;
str = format("{}", vv); // str == "-987123.4567890321"
bool flag = true;
str = format("Hello, {}!", flag); // str == "Hello, true!"
```
##### stoi()
```TvmSolidity
stoi(string inputStr) returns (optional(int) /*result*/);
```
Converts a `string` into an integer. If `string` starts with '0x' it will be converted from a hexadecimal format,
otherwise it is meant to be number in decimal format. Function returns the integer in case of success.
Otherwise, returns `null`.
Warning: this function consumes too much gas, that's why it's better not to use it onchain.
Example:
```TVMSolidity
optional(int) res;
res = stoi("123"); // res ==123
string hexstr = "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF123456789ABCDE";
res = stoi(hexstr); // res == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF123456789ABCDE
res = stoi("0xag"); // res == null
res = stoi(""); // res == null
```
##### string conversion
```TVMSolidity
string s = "1";
bytes2 b = bytes2(s); // b == 0x3100
string s = "11";
bytes2 b = bytes2(s); // b = 0x3131
```
`string` can be converted to `bytesN` which causes **N** * 8 bits being loaded from the cell and saved to variable.
If `string` object has less than **N** bytes, extra bytes are padded with zero bits.
#### address
`address` represents different types of TVM addresses: **addr_none**, **addr_extern**,
**addr_std** and **addr_var**. TVM Solidity compiler expands `address` type with the following
members and functions:
##### Object creating
##### constructor()
```TVMSolidity
uint address_value;
address addrStd = address(address_value);
```
Constructs `address` of type **addr_std** with zero workchain id and given address value.
##### address.makeAddrStd()
```TVMSolidity
int8 wid;
uint address;
address addrStd = address.makeAddrStd(wid, address);
```
Constructs `address` of type **addr_std** with given workchain id **wid** and value **address_value**.
##### address.addrNone
```TVMSolidity
address addrNone = address.addrNone;
```
Constructs `address` of type **addr_none**.
##### address.makeAddrExtern()
```TVMSolidity
uint addrNumber;
uint bitCnt;
address addrExtern = address.makeAddrExtern(addrNumber, bitCnt);
```
Constructs `address` of type **addr_extern** with given **value** with **bitCnt** bit-length.
##### Members
##### \<address\>.wid
```TVMSolidity
<address>.wid returns (int8);
```
Returns the workchain id of **addr_std** or **addr_var**. Throws "range check error" [exception](#tvm-exception-codes) for other `address` types.
##### \<address\>.value
```TVMSolidity
<address>.value returns (uint);
```
Returns the `address` value of **addr_std** or **addr_var** if **addr_var** has 256-bit `address` value. Throws "range check error" [exception](#tvm-exception-codes) for other `address` types.
##### \<address\>.balance
```TVMSolidity
address(this).balance returns (varuint16);
```
Returns balance of the current contract account in nanoevers.
##### \<address\>.currencies
```TVMSolidity
address(this).currencies returns (mapping(uint32 => varuint32));
```
Returns currencies on the balance of the current contract account.
##### Functions
##### \<address\>.getType()
```TVMSolidity
<address>.getType() returns (uint8);
```
Returns type of the `address`:
0 - **addr_none**
1 - **addr_extern**
2 - **addr_std**
##### \<address\>.isStdZero()
```TVMSolidity
<address>.isStdZero() returns (bool);
```
Returns the result of comparison between this `address` with zero `address` of type **addr_std**.
##### \<address\>.isStdAddrWithoutAnyCast()
```TVMSolidity
<address>.isStdAddrWithoutAnyCast() returns (bool);
```
Checks whether this `address` is of type **addr_std** without any cast.
##### \<address\>.isExternZero()
```TVMSolidity
<address>.isExternZero() returns (bool);
```
Returns the result of comparison between this `address` with zero `address` of type **addr_extern**.
##### \<address\>.isNone()
```TVMSolidity
<address>.isNone() returns (bool);
```
Checks whether this `address` is of type **addr_none**.
##### \<address\>.unpack()
```TVMSolidity
<address>.unpack() returns (int32 /*wid*/, uint256 /*value*/);
```
Parses `address` containing a valid `MsgAddressInt` (`addr_std`), applies rewriting
from the anycast (if exists) to the same-length prefix of the address, and returns both the
workchain `wid` and the 256-bit address `value`. If the address `value` is not 256-bit, or if
`address` is not a valid serialization of `MsgAddressInt`, throws a cell deserialization
[exception](#tvm-exception-codes).
It is wrapper for opcode `REWRITESTDADDR`.
Example:
```TVMSolidity
(int32 wid, uint addr) = address(this).unpack();
```
##### \<address\>.transfer()
```TVMSolidity
<address>.transfer(varuint16 value, bool bounce, uint16 flag, TvmCell body, mapping(uint32 => varuint32) currencies, TvmCell stateInit);
```
Sends an internal outbound message to the `address`. Function parameters:
* `value` (`varuint16`) - amount of nanoevers sent attached to the message. Note: the sent value is
withdrawn from the contract's balance even if the contract has been called by internal inbound message.
* `currencies` (`mapping(uint32 => varuint32)`) - additional currencies attached to the message. Defaults to
an empty set.
* `bounce` (`bool`) - if it's set and transaction (generated by the internal outbound message) falls
(only at the computing phase, not at the action phase!), then funds will be returned. Otherwise, (flag isn't
set or transaction terminated successfully) the address accepts the funds even if the account
doesn't exist or is frozen. Defaults to `true`.
* `flag` (`uint16`) - flag that used to send the internal outbound message. Defaults to `0`.
* `body` (`TvmCell`) - body (payload) attached to the internal message. Defaults to an empty
TvmCell.
* `stateInit` (`TvmCell`) - represents field `init` of `Message X`. If `stateInit` has a wrong
format, a cell underflow [exception](#tvm-exception-codes) at the computing phase is thrown.
See [here](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L148).
Normally, `stateInit` is used in 2 cases: to deploy the contract or to unfreeze the contract.
All parameters can be omitted, except `value`.
Possible values of parameter `flag`:
* `0` - message carries funds equal to the `value` parameter. Forward fee is subtracted from
the `value`.
* `128` - message carries all the remaining balance of the current smart contract. Parameter `value` is
ignored. The contract's balance will be equal to zero after the message processing.
Parameter `flag` can also be modified:
* `flag + 1` - means that the sender wants to pay transfer fees separately from contract's balance.
* `flag + 32` - means that the current account must be destroyed if its resulting balance is zero.
For example, `flag: 128 + 32` is used to send all balance and destroy the contract.
In order to clarify flags usage see [this sample](https://github.com/everx-labs/samples/blob/master/solidity/20_bomber.sol).
```TVMSolidity
address dest = ...;
uint128 value = ...;
bool bounce = ...;
uint16 flag = ...;
TvmCell body = ...;
mapping(uint32 => varuint32) c = ...;
TvmCell stateInit = ...;
// sequential order of parameters
addr.transfer(value);
addr.transfer(value, bounce);
addr.transfer(value, bounce, flag);
addr.transfer(value, bounce, flag, body);
addr.transfer(value, bounce, flag, body, c);
// using named parameters
destination.transfer({value: 1 ever, bounce: false, flag: 128, body: cell, currencies: c});
destination.transfer({bounce: false, value: 1 ever, flag: 128, body: cell});
destination.transfer({value: 1 ever, bounce: false, stateInit: stateInit});
```
See example of `address.transfer()` usage:
* [giver](https://github.com/everx-labs/samples/blob/master/solidity/7_Giver.sol)
#### mapping
TVM Solidity compiler expands `mapping` type with the following functions. In examples
below `\<map\>` defines the object of `mapping(KeyType => ValueType)` type.
Address, bytes, string, bool, contract, enum, fixed bytes, integer and struct types can
be used as a `KeyType`. Struct type can be used as `KeyType` only if it contains only
integer, boolean, fixed bytes or enum types and fits ~1023 bit. Example of mapping that
has a struct as a `KeyType`:
```TVMSolidity
struct Point {
uint x;
uint y;
uint z;
}
mapping(Point => address) map;
function test(uint x, uint y, uint z, address addr) public {
Point p = Point(x, y, z);
map[p] = addr;
}
```
If you use `mapping(KeyType => TvmSlice) map;` be sure that sum of bit-length of `KeyType`
and bit-length of `TvmSlice` is less than 1023 bit.
Struct `KeyType` can be used to sort keys of the mapping in ascending order. In the example
above addresses in the mapping are sorted by their keys. `x` field of the Point struct
is used in comparison first, second is `y` and the last is `z`.
If `bytes`, `string` or `TvmCell` types are used as `KeyType`, then `mapping` stores
only hashes of mapping keys. That's why for these types the `delMin`/`min`/`next` and
another mapping methods return `uint256` as key (not `bytes`/`string`/`TvmCell`).
If you use mapping as an input or output param for public/external functions,
`KeyType` of the mapping can only be of type `address` or of `int<M>`/`uint<M>` types with M from 8 to 256.
See example of how to work with mappings:
* [database](https://github.com/everx-labs/samples/blob/master/solidity/13_BankCollector.sol)
* [client](https://github.com/everx-labs/samples/blob/master/solidity/13_BankCollectorClient.sol)
##### Keyword `emptyMap`
Keyword `emptyMap` is a constant that is used to indicate a mapping of arbitrary type without values.
Example:
```TVMSolidity
struct Stakes {
uint total;
mapping(uint => uint) stakes;
}
// create struct with empty mapping `stakes`
Stakes stakes = Stakes({stakes: emptyMap, total: 200});
```
##### \<mapping\>.operator[]
```TVMSolidity
<map>.operator[](KeyType index) returns (ValueType);
```
Returns the item of `ValueType` with **index** key or returns the default value
if key is not in the mapping.
##### \<mapping\>.at()
```TVMSolidity
<map>.operator[](KeyType index) returns (ValueType);
```
Returns the item of `ValueType` with **index** key. Throws an [exception](#tvm-exception-codes) if key
is not in the mapping.
##### \<mapping\>.min() and \<mapping\>.max()
```TVMSolidity
<map>.min() returns (optional(KeyType, ValueType));
<map>.max() returns (optional(KeyType, ValueType));
```
Computes the minimal (maximal) key in the `mapping` and returns an `optional`
value containing that key and the associated value. If `mapping` is empty,
this function returns an empty `optional`.
##### \<mapping\>.next() and \<mapping\>.prev()
```TVMSolidity
<map>.next(KeyType key) returns (optional(KeyType, ValueType));
<map>.prev(KeyType key) returns (optional(KeyType, ValueType));
```
Computes the minimal (maximal) key in the `mapping` that is lexicographically
greater (less) than **key** and returns an `optional` value containing that
key and the associated value. Returns an empty `optional` if there is no such key.
If KeyType is an integer type, argument for this functions can not possibly fit `KeyType`.
Example:
```TVMSolidity
KeyType key;
// init key
optional(KeyType, ValueType) nextPair = map.next(key);
optional(KeyType, ValueType) prevPair = map.prev(key);
if (nextPair.hasValue()) {
(KeyType nextKey, ValueType nextValue) = nextPair.get(); // unpack optional value
// using nextKey and nextValue
}
mapping(uint8 => uint) m;
optional(uint8, uint) = m.next(-1); // ok, param for next/prev can be negative
optional(uint8, uint) = m.prev(65537); // ok, param for next/prev can not possibly fit to KeyType (uint8 in this case)
```
##### \<mapping\>.nextOrEq() and \<mapping\>.prevOrEq()
```TVMSolidity
<map>.nextOrEq(KeyType key) returns (optional(KeyType, ValueType));
<map>.prevOrEq(KeyType key) returns (optional(KeyType, ValueType));
```
Computes the minimal (maximal) key in the `mapping` that is lexicographically greater than
or equal to (less than or equal to) **key** and returns an `optional` value containing that
key and the associated value. Returns an empty `optional` if there is no such key.
If KeyType is an integer type, argument for this functions can not possibly fit `KeyType`.
##### \<mapping\>.delMin() and \<mapping\>.delMax()
```TVMSolidity
<map>.delMin() returns (optional(KeyType, ValueType));
<map>.delMax() returns (optional(KeyType, ValueType));
```
If mapping is not empty, then this function computes the minimal (maximum) key of the `mapping`,
deletes that key and the associated value from the `mapping` and returns an `optional` value
containing that key and the associated value. Returns an empty `optional` if there is no such key.
##### \<mapping\>.fetch()
```TVMSolidity
<map>.fetch(KeyType key) returns (optional(ValueType));
```
Checks whether **key** exists in the `mapping` and returns an `optional` with the associated value.
Returns an empty `optional` if there is no such key.
##### \<mapping\>.exists()
```TVMSolidity
<map>.exists(KeyType key) returns (bool);
```
Returns whether **key** exists in the `mapping`.
##### \<mapping\>.empty()
```TVMSolidity
<map>.empty() returns (bool);
```
Returns whether the `mapping` is empty.
##### \<mapping\>.replace()
```TVMSolidity
<map>.replace(KeyType key, ValueType value) returns (bool);
```
Sets the value associated with **key** only if **key** exists in the `mapping` and
returns the success flag.
##### \<mapping\>.add()
```TVMSolidity
<map>.add(KeyType key, ValueType value) returns (bool);
```
Sets the value associated with **key** only if **key** does not exist in the `mapping`.
##### \<mapping\>.getSet()
```TVMSolidity
<map>.getSet(KeyType key, ValueType value) returns (optional(ValueType));
```
Sets the value associated with **key**, but also returns an `optional` with the
previous value associated with the **key**, if any. Otherwise, returns an empty `optional`.
##### \<mapping\>.getAdd()
```TVMSolidity
<map>.getAdd(KeyType key, ValueType value) returns (optional(ValueType));
```
Sets the value associated with **key**, but only if **key** does not exist in the `mapping`.
Returns an `optional` with the old value without changing the dictionary if that value exists
in the `mapping`, otherwise returns an empty `optional`.
##### \<mapping\>.getDel()
```TVMSolidity
<map>.getDel(KeyType key) returns (optional(ValueType));
```
Deletes the **key** from the `mapping` **map** and returns an `optional`
with the corresponding value. Returns an empty optional if the key does not exist.
##### \<mapping\>.getReplace()
```TVMSolidity
<map>.getReplace(KeyType key, ValueType value) returns (optional(ValueType));
```
Sets the value associated with **key**, but only if **key** exists in the `mapping`.
On success, returns an `optional` with the old value associated with the **key**.
Otherwise, returns an empty `optional`.
#### Fixed point number
`fixed` / `ufixed`: Signed and unsigned fixed point number of various sizes. Keywords `ufixedMxN`
and `fixedMxN`, where `M` represents the number of bits taken by the type and `N` represents how
many decimal points are available. `M` must be divisible by 8 and goes from 8 to 256 bits. `N` must
be between 0 and 80, inclusive. `ufixed` and `fixed` are aliases for `ufixed128x18` and
`fixed128x18`, respectively.
Operators:
* Comparison: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Arithmetic operators: `+`, `-`, unary `-`, `*`, `/`, `%` (modulo)
* Math operations: [math.min(), math.max()](#mathmin-mathmax), [math.minmax()](#mathminmax),
[math.abs()](#mathabs), [math.divr(), math.divc()](#mathdivr-mathdivc)
#### \<mapping\>.keys() \<mapping\>.values()
```TVMSolidity
(1)
<map>.keys() returns (KeyType[]);
(2)
<map>.values() returns (ValueType[]);
```
(1) Returns all mapping's keys/values.
(2) Returns all values of the mapping as an array.
**Note:** these functions iterate over the whole mapping, thus the cost is proportional to the
mapping's size.
```TVMSolidity
mapping(uint16 => uint8) map;
map[11] = 10;
map[22] = 20;
map[33] = 30;
uint16[] keys = map.keys(); // keys == [11, 22, 33]
uint8[] values = map.values(); // values == [10, 20, 30]
```
#### Function type
Function types are the types of functions. Variables of function type can be assigned from functions
and function parameters of function type can be used to pass functions to and return functions from
function calls.
If unassigned variable of function type is called, then exception with code 65 is thrown.
```TVMSolidity
function getSum(int a, int b) internal pure returns (int) {
return a + b;
}
function getSub(int a, int b) internal pure returns (int) {
return a - b;
}
function process(int a, int b, uint8 mode) public returns (int) {
function (int, int) returns (int) fun;
if (mode == 0) {
fun = getSum;
} else if (mode == 1) {
fun = getSub;
}
return fun(a, b); // if `fun` isn't initialized, then exception is thrown
}
```
#### User-defined type
A user-defined value type allows creating a zero cost abstraction over an elementary value type. This is similar to an alias, but with stricter type requirements.
More information can be found [here](https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types).
You can define an operator for user-defined type. See [here](https://docs.soliditylang.org/en/latest/contracts.html#using-for).
#### require, revert
In case of exception state variables of the contract are reverted to the state before
[tvm.commit()](#tvmcommit) or to the state of the contract before it was called.
Use error codes that are greater than 100 because other error codes can be
[reserved](#solidity-runtime-errors).
**Note**: if a nonconstant error code is passed as the function argument and the error code
is less than 2, then the error code will be set to 100.
##### require
```TVMSolidity
(1)
require(bool condition, [uint errorCode = 100, [Type exceptionArgument]]);
(2)
require(bool condition, string text);
```
`require` function can be used to check the condition and throw an exception if the condition
is not met.
(1) Takes condition and optional parameters: error code and the object of any type.
(2) Takes condition and error text. Error code will be equal to 100.
Example:
```TVMSolidity
uint a = 5;
require(a == 5); // ok
require(a == 6); // throws an exception with code 100
require(a == 6, 101); // throws an exception with code 101
require(a == 6, 101, "a is not equal to six"); // throws an exception with code 101 and string
require(a == 6, 101, a); // throws an exception with code 101 and number a
require(a == 6, "a is not equal to six"); // throws an exception with code 100 and string
```
##### revert
```TVMSolidity
revert(uint errorCode = 100, [Type exceptionArgument]);
```
**revert** function can be used to throw exceptions. The function takes an optional error code
(unsigned integer) and the object of any type.
Example:
```TVMSolidity
uint a = 5;
revert(); // throw exception 100
revert(101); // throw exception 101
revert(102, "We have a some problem"); // throw exception 102 and string
revert(101, a); // throw exception 101 and number a
```
#### Libraries
Libraries are similar to contracts, but they can't have state variables
and can't inherit nor be inherited. Libraries can be seen as implicit
base contracts of the contracts that use them. They will not be
explicitly visible in the inheritance hierarchy, but calls of library
functions look just like calls of functions of explicit base contracts
(using qualified access like `LibName.func(a, b, c)`). There is also
another way to call library function: `obj.func(b, c)`.
For now libraries are stored as a part of the code of the contact that
uses libraries. In the future, it can be changed.
##### Function call via library name
Example of using library in the manner `LibName.func(a, b, c)`:
```TVMSolidity
// file MathHelper.sol
pragma solidity >= 0.72.0;
// Library declaration
library MathHelper {
// State variables are forbidden in library but constants are not
uint constant MAX_VALUE = 300;
// Library function
function sum(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
require(c < MAX_VALUE);
return c;
}
}
// file MyContract.sol
pragma solidity >= 0.72.0;
import "MathHelper.sol";
contract MyContract {
uint s;
function addValue(uint value) public returns (uint) {
s = MathHelper.sum(s, value);
return s;
}
}
```
##### Function call via object
In TVM Solidity **arguments of a function call passed by value not by
reference**. It's effective for numbers and even for huge arrays.
See ([TVM][1] - A.2.3.2).
**But if a library function is called like `obj.func(b, c)`, then the
first argument `obj` is passed by reference.** It's similar to
the `self` variable in Python.
The directive [using A for B;](https://docs.soliditylang.org/en/latest/contracts.html#using-for) can be used to attach library functions
(from the library `A`) to any type (`B`) in the context of the contract.
These functions will receive the object they were called for as their
first parameter.
The effect of `using A for *;` is that the functions from the library
`A` are attached to all types.
Example of using library in the manner `obj.func(b, c)`:
```TVMSolidity
// file ArrayHelper.sol
pragma solidity >= 0.72.0;
library ArrayHelper {
// Delete value from the `array` at `index` position
function del(uint[] array, uint index) internal pure {
for (uint i = index; i + 1 < array.length; ++i){
array[i] = array[i + 1];
}
array.pop();
}
}
// file MyContract.sol
pragma solidity >= 0.72.0;
import "ArrayHelper.sol";
contract MyContract {
// Attach library function `del` to the type `uint[]`
using ArrayHelper for uint[];
uint[] array;
constructor() {
array = [uint(100), 200, 300];
}
function deleteElement(uint index) public {
// Library function call via object.
// Note: library function `del` has 2 arguments:
// array is passed by reference and index is passed by value
array.del(index);
}
}
```
#### Free function call via object
Free functions can be called via object as well as library functions. Use directive [using A for B;](https://docs.soliditylang.org/en/latest/contracts.html#using-for). Example:
```TVMSolidity
pragma tvm-solidity >= 0.72.0;
// Delete value from the `array` at `index` position
function del(uint[] array, uint index) {
for (uint i = index; i + 1 < array.length; ++i){
array[i] = array[i + 1];
}
array.pop();
}
contract MyContract {
// Attach function `del` to the type `uint[]`
using {del} for uint[];
uint[] public array;
constructor() {
array = [uint(100), 200, 300];
}
function deleteElement(uint index) public {
// Free function call via object.
// Note: free function `del` has 2 arguments:
// array is passed by reference and index is passed by value
array.del(index);
}
}
```
### Pragmas
`pragma` keyword is used to enable certain compiler features or checks.
A pragma directive is always local to a source file, so you have to add
the pragma to all your files if you want to enable it in your whole project.
If you import another file, the pragma from that file is not
automatically applied to the importing file.
#### pragma tvm-solidity
```TVMSolidity
pragma tvm-solidity >= 0.35.5; // Check if the compiler version is greater or equal than 0.35.5
pragma tvm-solidity ^ 0.35.5; // Check if the compiler version is greater or equal than 0.35.5 and less than 0.36.0
pragma tvm-solidity < 0.35.5; // Check if the compiler version is less than 0.35.5
pragma tvm-solidity >= 0.35.5 < 0.35.7; // Check if the compiler version is equal to either 0.35.5 or 0.35.6
```
Used to restrict source file compilation to the particular compiler versions.
#### pragma-copyleft
```TVMSolidity
pragma copyleft <type>, <wallet_address>;
```
[Capabilities](#tvm-capabilities) required: `CapCopyleft`.
Parameters:
* `<type>` (`uint8`) - copyleft type.
* `<wallet_address>` (`uint256`) - author's wallet address in masterchain.
If contract has the `copyleft` pragma, it means that after each transaction some part of validator's fee
is transferred to `<wallet_address>` according to the `<type>` rule.
For example:
```TVMSolidity
pragma copyleft 0, 0x2cfbdc31c9c4478b61472c72615182e9567595b857b1bba9e0c31cd9942f6ca41;
```
#### pragma ignoreIntOverflow
```TVMSolidity
pragma ignoreIntOverflow;
```
All arithmetic operations revert on over- and underflow by default. This pragma turns off such behavior. It is up to programmer to control range of integer types if they use the pragma.
For example:
```TVMSolidity
pragma ignoreIntOverflow;
uint8 a = 2;
uint8 b = 3;
uint8 c = a - b; // c == -1, no exception thrown
```
See also: [unchecked block](#unchecked-block).
#### pragma AbiHeader
```TVMSolidity
pragma AbiHeader notime;
pragma AbiHeader pubkey;
pragma AbiHeader expire;
```
Defines headers that are used in external messages:
* `notime` - disables `time` abi header, which is enabled by default. Abi header `time``uint64` local time when message was created, used for replay protection
* `pubkey` (`uint256`) - optional public key that the message can be signed with.
* `expire` (`uint32`) - time when the message should be meant as expired.
**Note:**
Defined headers are listed in `*.abi.json` file in `header` section.
See also: [Contract execution](#contract-execution), [afterSignatureCheck](#aftersignaturecheck),
[msg.pubkey()](#msgpubkey) and [tvm.pubkey()](#tvmpubkey).
To read more about these fields and ABI follow this [link](https://docs.ton.dev/86757ecb2/p/40ba94-abi-specification-v2).
Here is example of [message expiration time](https://docs.ton.dev/86757ecb2/p/88321a-message-expiration-time) usage.
#### pragma msgValue
```TVMSolidity
pragma msgValue <value>;
```
Allows specifying default value in nanoevers attached to the
internal outbound messages used to call another contract. If it's not
specified, this value is set to 10 000 000 nanoevers.
Example:
```TVMSolidity
pragma msgValue 123456789;
pragma msgValue 1e8;
pragma msgValue 10 ever;
pragma msgValue 10_000_000_123;
```
#### pragma upgrade func/oldsol
```TVMSolidity
pragma upgrade func;
pragma upgrade oldsol;
```
Defines that code is compiled with special selector that is needed to upgrade FunC/Solidity contracts.
### State variables
#### Decoding state variables
You can decode state variables using ever-cli. See `ever-cli decode account --help`.
See also: [abi.decodeData()](#abidecodedata).
#### Keyword `constant`
For `constant` variables, the value has to be a compile time constant and this value is
substituted where the variable is used. The value has to be assigned where the variable is declared.
Example:
```TVMSolidity
contract MyContract {
uint constant cost = 100;
uint constant cost2 = cost + 200;
address constant dest = address.makeAddrStd(-1, 0x89abcde);
}
```
#### Keyword `static`
Static state variables are used in the contract initial state generation.
Such variables can be set while deploying contract from contract
(onchain) or by tvm-linker (offchain). Example:
```TVMSolidity
contract C {
uint static a; // ok
uint static b = 123; // error
}
```
See also:
* [`code` option usage](#code-option-usage)
* [New contract address problem](#new-contract-address-problem)
#### Keyword `nostorage`
`nostorage` state variables are not saved in the contract's storage. They have default values at the
beginning of each transaction.
```TVMSolidity
contract C {
uint nostorage m_value;
function f() public {
// here m_value == 0
++m_value;
// here m_value == 1
}
}
```
#### Keyword `public`
For each public state variable, a getter function is generated. Generated
function has the same name and return type as the public variable. This
function can be called only locally. Public state variables are useful,
because you don't need to write functions that return a particular state variable manually.
Example:
```TVMSolidity
contract C {
uint public a;
uint public static b; // it's ok. Variable is both public and static.
}
```
### Special contract functions
#### receive
`receive` function is called in two cases:
1. [msg.body](#msgbody) (or message body) is empty.
2. [msg.body](#msgbody) starts with 32-bit zero. Then message body may contain data,
for example [string](#string) with comment.
If in the contract there is no `receive` function, then the contract has an implicit empty `receive`
function.
```TVMSolidity
// file sink.sol
contract Sink {
uint public counter = 0;
uint public msgWithPayload = 0;
receive() external {
++counter;
// if the inbound internal message has payload, then we can get it using `msg.body`
TvmSlice s = msg.body;
if (!s.empty()) {
++msgWithPayload;
}
}
}
// file bomber.sol
contract Bomber {
// This function send evers 3 times to the Sink contract. Sink's function receive will handle
// that messages.
function f(address addr) pure public {
tvm.accept();
addr.transfer({value: 1 ever}); // message's body is empty
TvmBuilder b;
addr.transfer({value: 1 ever, body: b.toCell()}); // message's body is empty, too
b.store(uint32(0), "Thank you for the coffee!");
// body of the message contains 32-bit zero number and the string
addr.transfer({value: 20 ever, body: b.toCell()});
}
}
```
##### fallback
`fallback` function is called on receiving an inbound internal/external message in such cases:
1. The message contains a function id that the contract doesn't contain.
2. Bit-length of the message is from 1 to 31 (including).
3. Bit-length of the message is equal to zero, but the message contains reference(s).
**Note**: if the message has correct function id but invalid encoded function parameters, then
the transaction fail with an exception (e.g. [cell underflow exception](#tvm-exception-codes)).
If in the contract there is no fallback function, then contract has implicit fallback function
that throws [exception](#solidity-runtime-errors).
Example:
```TVMSolidity
// file ContractA.sol
contract ContractA {
uint public counter = 0;
function f(uint a, uint b) public pure { /*...*/ }
fallback() external {
++counter;
}
}
// file ContractB.sol
import "ContractA.sol";
import "ContractAnother.sol";
contract ContractB {
// Let's condider that `addr` is ContractA's address. 4 messages are send. ContractA's fallback
// function will handle that messages except the last one.
function g(address addr) public pure {
tvm.accept();
// The message contains a function id that the contract doesn't contain.
// There is wrong casting to ContractAnother. `addr` is ContractA's address.
ContractAnother(addr).sum{value: 1 ever}(2, 2);
{
TvmBuilder b;
b.storeUnsigned(1, 1);
// Bit-length of the message is equal to 20 bits.
addr.transfer({value: 2 ever, body: b.toCell()});
}
{
TvmBuilder b;
b.storeRef(b);
// Bit-length of the message is equal to zero but the message contains one reference.
addr.transfer({value: 1 ever, body: b.toCell()});
}
TvmBuilder b;
uint32 id = abi.functionId(ContractA.f);
b.store(id, uint(2));
// ContractA's fallback function won't be called because the message body doesn't contain
// the second ContractA.f's parameter. It will cause cell underflow exception in ContractA.
addr.transfer({value: 1 ever, body: b.toCell()});
}
}
```
#### onBounce
```TVMSolidity
onBounce(TvmSlice body) external {
/*...*/
}
```
`onBounce` function is executed when contract receives a bounced inbound internal message.
The message is generated by the network if the contract sends an internal message with `bounce: true` and either
* called contract doesn't exist;
* called contract fails at the storage/credit/computing phase (not at the action phase!)
The message is generated only if the remaining message value is enough for sending one back.
`body` depends on TVM realisation and settings:
1. `body` can be empty.
2. If `CapBounceMsgBody` [capability](#tvm-capabilities) is set, then `body` contains at most 256 data bits of the original message (without references). Note: the function id takes `32` bits and the function's parameters can take at most `224` bits.
3. If `CapBounceMsgBody` and `CapFullBodyInBounced` [capabilities](#tvm-capabilities) are set, then `body` is the same as in the second option, but `body` contains the full original message in the first reference.
If `onBounce` function is not defined, then the contract does
nothing on receiving a bounced message.
If the `onBounce` function throws an exception, then another bounced messages are not generated.
Example of how to use `onBounce` function for option 2:
* [onBounceHandler](https://github.com/everx-labs/samples/blob/master/solidity/16_onBounceHandler.sol)
Example of getting function ID if `CapBounceMsgBody` and `CapFullBodyInBounced` [capabilities](#tvm-capabilities) are set:
```TVMSolidity
onBounce(TvmSlice body) external {
TvmSlice fullBody = body.loadRef().toSlice();
uint32 functionId = fullBody.load(uint32);
}
```
#### onTickTock
`onTickTock` function is executed on tick/tock transaction.
These transactions are automatically generated for certain special accounts.
See ([TBLKCH][2] - 4.2.4.)
For tick transactions **isTock** is false, for tock transactions - true.
Prototype:
```TVMSolidity
onTickTock(bool isTock) external {
/*...*/
}
```
#### onCodeUpgrade
`onCodeUpgrade` function can have an arbitrary set of arguments and should be
executed after [tvm.setcode()](#tvmsetcode) function call. In this function
[tvm.resetStorage()](#tvmresetstorage) should be called if the set of state
variables is changed in the new version of the contract. This function implicitly
calls [tvm.commit()](#tvmcommit). `onCodeUpgrade` function does not return value. `onCodeUpgrade` function
finishes TVM execution with exit code 0.
Prototype:
```TVMSolidity
function onCodeUpgrade(...) private {
/*...*/
}
```
Function `onCodeUpgrade` had function id = 2 (for compiler <= 0.65.0). Now, it has another id, but you can set
`functionID(2)` in new contracts for the `onCodeUpgrade` to upgrade old ones.
See example of how to upgrade code of the contract:
* [old contract](https://github.com/everx-labs/samples/blob/master/solidity/12_BadContract.sol)
* [new contract](https://github.com/everx-labs/samples/blob/master/solidity/12_NewVersion.sol)
It's good to pass `TvmCell cell` to the public function that calls `onCodeUpgrade(TvmCell cell, ...)`
function. `TvmCell cell` may contain some data that may be useful for the new contract.
```TVMSolidity
// old contract
// Public function that changes the code and takes some cell
function updateCode(TvmCell newcode, TvmCell cell) public pure checkPubkeyAndAccept {
tvm.setcode(newcode);
tvm.setCurrentCode(newcode);
// pass cell to new contract
onCodeUpgrade(cell);
}
function onCodeUpgrade(TvmCell cell) private pure {
}
// new contract
function onCodeUpgrade(TvmCell cell) private pure {
// new code can use cell that was passed from the old version of the contract
}
```
#### afterSignatureCheck
```TVMSolidity
function afterSignatureCheck(TvmSlice body, TvmCell message) private inline returns (TvmSlice) {
/*...*/
}
```
`afterSignatureCheck` function is used to define custom replay protection function instead of the
default one.
NB: Do not use [tvm.commit()](#tvmcommit) or [tvm.accept()](#tvmaccept) in this function as it called before the constructor call.
**time** and **expire** header fields can be used for replay protection and, if set, they should be read in `afterSignatureCheck`.
See also: [Contract execution](#contract-execution).
See an example of how to define this function:
* [Custom replay protection](https://github.com/everx-labs/samples/blob/master/solidity/14_CustomReplayProtection.sol)
### Function specifiers
#### Function mutability: pure, view and default
Function mutability shows how this function treats state variables.
Possible values of the function mutability:
* `pure` - function neither reads nor assigns state variables;
* `view` - function may read but doesn't assign state variables;
* default - function may read and/or assign state variables.
Example:
```TVMSolidity
contract Test {
uint a;
event MyEvent(uint val);
// pure mutability
function f() public pure {
emit MyEvent(123);
}
// view mutability
function g() public view {
emit MyEvent(a);
}
// default mutability (not set)
function e(uint newA) public {
a = newA;
}
}
```
#### Keyword inline
`inline` specifier instructs the compiler to insert a copy of the private function
body into each place where the function is called.
Keyword can be used only for private and internal functions.
Example:
```TVMSolidity
// This function is called as a usual function.
function getSum(uint a, uint b) public returns (uint) {
return sum(a, b);
}
// Code of this function is inserted in place of the call site.
function sum(uint a, uint b) private inline returns (uint) {
return a + b;
}
```
#### Assembly
To make inline assembler you should mark [free function](https://docs.soliditylang.org/en/latest/contracts.html#functions) as `assembly`. Function body must contain lines of assembler code separated by commas.
It is up to user to set correct mutability (`pure`, `view` or default), return parameters of the function and so on.
```TVMSolidity
function checkOverflow(uint a, uint b) assembly pure returns (bool) {
"QADD",
"ISNAN",
"NOT",
}
contract Contract {
function f(uint a, uint b) private {
bool ok = checkOverflow(a, b);
if (ok) {
uint c = a + b;
}
}
}
```
You can use inline assembler to support new opcodes in experimental or another implementations of TVM.
```TVMSolidity
function incomingValue() assembly pure returns (uint) {
".blob xF82B", // it's opcode INCOMINGVALUE
}
```
#### functionID()
`functionID` keyword allows assigning function identifier explicitly.
Each public function has a unique 32-bit identifier (id). id 0 is reserved for [receive](#receive) function. id 1 is reserved for Constructor function.
In case `functionID` is not defined explicitly, it is calculated as a hash of the function signature.
In general, there is no purpose to set the function id manually.
Example:
```TVMSolidity
function f() public pure functionID(123) {
/*...*/
}
```
#### externalMsg and internalMsg
Keywords `externalMsg` and `internalMsg` specify which messages the function can handle.
If the function marked by keyword `externalMsg` is called by internal message, the function throws an
exception with code 71.
If the function marked by keyword `internalMsg` is called by external message, the function throws
an exception with code 72.
Example:
```TVMSolidity
function f() public externalMsg { // this function receives only external messages
/*...*/
}
// Note: keyword `external` specifies function visibility
function ff() external externalMsg { // this function also receives only external messages
/*...*/
}
function g() public internalMsg { // this function receives only internal messages
/*...*/
}
// These function receives both internal and external messages.
function fun() public { /*...*/ }
```
### Events and return
#### emit
`emit` statement sends an external outbound message. Use `{dest: ...}`to set destination address.
The address must be of **addr_extern** type.
If option `dest` is not used, the destination address is set to **addr_none**.
**Note:** fee for creating the external outbound message is withdrawn from the contract's
balance even if the contract has been called by internal inbound message.
Example:
```TVMSolidity
event SomethingIsReceived(uint a, uint b, uint sum);
...
address addr = address.makeAddrExtern(...);
emit SomethingIsReceived{dest: addr}(2, 8, 10); // dest address is set
emit SomethingIsReceived(10, 15, 25); // dest address == addr_none
```
#### return
`return` statement has different effects depending on:
* visibility of the function;
* type of the inbound message;
* presence of the `responsible` modifier.
In `private` or `internal` visible functions, `return` assigns the return variables to the specified parameters;
In `public` or `external` visible functions, `return` statement:
* on an external inbound message, generates an external outbound message with a destination address set to
the source address of the inbound (external) message. All arguments of the return statement are ignored.
* on an external inbound message:
* if the function is marked as `responsible`, generates an internal outbound message;
* otherwise has no effect.
`value`, `bounce`, `flag` and `currencies` options are used to create the message. Some options can
be omitted. See [\<address\>.transfer()](#addresstransfer) where these options and their default
values are described.
**Note**: if the function `f` below is called with `n = 5` and internal/external message must be
generated, then only one message is sent with result `120` (120 = 5 * 4 * 3 * 2 * 1).
**Hint:** Use `{value: 0, bounce: false, flag: 64}` for `responsible` function.
Because `flag: 0` is used by default.
See also: [External function calls](#external-function-calls).
```TVMSolidity
function f(uint n) public pure {
return n <= 1 ? 1 : n * f(n - 1);
}
function f(uint n) public responsible pure {
return{value: 0, bounce: false, flag: 64} n <= 1 ? 1 : n * f(n - 1);
}
```
### External function calls
TVM Solidity compiler allows specifying different parameters of the outbound internal message that
is sent via external function call. Note, all external function calls are asynchronous, so
callee function will be called after termination of the current transaction.
`value`, `currencies`, `bounce`, `flag` and `stateInit` options can be set. See [\<address\>.transfer()](#addresstransfer)
where these options are described.
**Note:** if `value` isn't set, then the default value is equal to 0.01 ever, or 10^7 nanoever. It's equal
to 10_000 units of gas in workchain.
If the callee function returns some value and marked as `responsible`, then `callback` option must be set.
This callback function will be called by another contract. Remote function will pass its return
values as function arguments for the callback function. That's why types of return values of the
callee function must be equal to function arguments of the callback function.
If the function marked as `responsible`, then field `answerId` appears in the list of input parameters of the
function in `*abi.json` file. `answerId` is function id that will be called.
Example of the external call of the function that returns nothing:
```TVMSolidity
interface IContract {
function f(uint a) external;
}
contract Caller {
function callExt(address addr) public {
IContract(addr).f(123); // attached default value: 0.01 ever
IContract(addr).f{value: 10 ever}(123);
IContract(addr).f{value: 10 ever, flag: 3}(123);
IContract(addr).f{value: 10 ever, bounce: true}(123);
IContract(addr).f{value: 1 micro, bounce: false, flag: 128}(123);
mapping(uint32 => varuint32) cc;
cc[12] = 1000;
IContract(addr).f{value: 10 ever, currencies:cc}(123);
}
}
```
Example of the external call of the function that returns some values:
```TVMSolidity
contract RemoteContract {
// Note this function is marked as responsible to call callback function
function getCost(uint x) public pure responsible returns (uint) {
uint cost = x == 0 ? 111 : 222;
// return cost and set option for outbound internal message.
return{value: 0, bounce: false, flag: 64} cost;
}
}
contract Caller {
function test(address addr, uint x) public pure {
// `getCost` returns result to `onGetCost`
RemoteContract(addr).getCost{value: 1 ever, callback: Caller.onGetCost}(x);
}
function onGetCost(uint cost) public {
// Check if msg.sender is expected address
// we get cost value, we can handle this value
}
}
```
`*.abi.json` for `responsible` function `getCost`:
```json
{
"name": "getCost",
"inputs": [
{"name":"answerId","type":"uint32"},
{"name":"x","type":"uint256"}
],
"outputs": [
{"name":"value0","type":"uint256"}
]
}
```
See also:
* Example of callback usage: [24_SquareProvider](https://github.com/everx-labs/samples/blob/master/solidity/24_SquareProvider.sol)
* Example of callback usage: [4.1_CentralBank](https://github.com/everx-labs/samples/blob/master/solidity/4.1_CentralBank.sol)
and [4.1_CurrencyExchange.sol](https://github.com/everx-labs/samples/blob/master/solidity/4.1_CurrencyExchange.sol)
* [return](#return)
### Delete variables
As in classic Solidity `delete` operation assigns the initial value for the type to a variable.
Delete operation can be applied not only to variables itself, but to its fields or index values.
Example:
```TVMSolidity
int a = 5;
delete a; // a == 0
uint[] arr;
arr.push(11);
arr.push(22);
arr.push(33);
delete arr[1];
// arr[0] == 11
// arr[1] == 0
// arr[2] == 33
delete arr; // arr.length == 0
mapping(uint => uint) l_map;
l_map[1] = 2;
delete l_map[1];
bool e = l_map.exists(1); // e == false
l_map[1] = 2;
delete l_map;
bool e = l_map.exists(1); // e == false
struct DataStruct {
uint m_uint;
bool m_bool;
}
DataStruct l_struct;
l_struct.m_uint = 1;
delete l_struct; // l_struct.m_uint == 0
TvmBuilder b;
uint i = 0x54321;
b.store(i);
TvmCell c = b.toCell();
delete c;
TvmCell empty; // tvm.hash(empty) == tvm.hash(c)
b.store(c);
TvmSlice slice = b.toSlice();
uint16 bits = slice.bits(); // bits == 256
uint8 refs = slice.refs(); // refs == 1
delete slice;
uint16 bits = slice.bits(); // bits == 256
uint8 refs = slice.refs(); // refs == 1
uint16 bits = b.bits(); // bits == 256
uint8 refs = b.refs(); // refs == 1
delete b;
uint16 bits = b.bits(); // bits == 256
uint8 refs = b.refs(); // refs == 1
```
### API functions and members
#### Type information
The expression `type(T)` can be used to retrieve information about the type T.
The following properties are available for an integer, [variable integer](#varint-and-varuint) and enum type `T`:
* `type(T).min` - the smallest value representable by type `T`.
* `type(T).max` - the largest value representable by type `T`.
#### **msg** namespace
##### msg.sender
```TVMSolidity
msg.sender (address)
```
Returns:
* sender of the message for internal message.
* address(0) for external message.
* address(0) for tick/tock transaction.
##### msg.value
```TVMSolidity
msg.value (varuint16)
```
Returns:
* Balance of the inbound message in nanoevers for internal message.
* 0 for external message.
* Undefined value for tick/tock transaction.
##### msg.currencies
```TVMSolidity
msg.currencies (mapping(uint32 => varuint32))
```
Collections of arbitrary currencies contained in the balance of
the inbound message.
##### msg.pubkey()
```TVMSolidity
msg.pubkey() returns (uint256);
```
Returns public key that is used to check the message signature. If the message isn't signed, then it's equal to `0`.
See also: [Contract execution](#contract-execution), [pragma AbiHeader](#pragma-abiheader).
##### msg.isInternal, msg.isExternal and msg.isTickTock
Returns flag whether the contract is called by internal message, external message or by tick/tock transactions.
##### msg.createdAt
```TVMSolidity
msg.createdAt (uint32)
```
Returns the field **created_at** of the external inbound message.
##### msg.data
```TVMSolidity
msg.data (TvmCell)
```
Returns [the whole message](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L155).
##### msg.forwardFee
```TVMSolidity
msg.forwardFee (varuint16)
```
Returns:
* the [forward fee](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L126) for the internal inbound message.
* `0` for the external inbound message.
##### msg.importFee
```TVMSolidity
msg.importFee (varuint16)
```
Returns:
* the field [import_fee](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L130) for external inbound message. **Note:** field `import_fee` is set offchain by user as they want and does not reflect the real import fee of the message.
* `0` for the internal inbound message.
##### msg.body
```TVMSolidity
msg.body (TvmSlice)
```
Returns the payload (message body) of an inbound message.
##### msg.hasStateInit
```TVMSolidity
msg.hasStateInit (bool)
```
Whether the internal/external inbound message contains field `stateInit`.
Returns undefined value for tick/tock transaction. See [TL-B scheme][3] of `Message X`.
#### **tvm** namespace
##### TVM instructions
##### tvm.accept()
```TVMSolidity
tvm.accept();
```
Executes TVM instruction "ACCEPT" ([TVM][1] - A.11.2).
This instruction sets current gas limit to its maximal allowed value.
This action is required to process external messages that bring no value.
See example of how to use this function:
* [accumulator](https://github.com/everx-labs/samples/blob/master/solidity/1_Accumulator.sol)
##### tvm.setGasLimit()
```TVMSolidity
tvm.setGasLimit(uint g);
```
Executes TVM instruction "SETGASLIMIT" ([TVM][1] - A.11.2).
Sets current gas limit **g<sub>l</sub>** to the minimum of **g** and **g<sub>m</sub>**, and resets the gas
credit **g<sub>c</sub>** to zero. If the gas consumed so far (including the present instruction) exceeds
the resulting value of **g<sub>l</sub>**, an (unhandled) out of gas exception is thrown before setting
new gas limits. Notice that `tvm.setGasLimit(...)` with an argument **g** ≥ 2<sup>63</sup> - 1 is
equivalent to `tvm.accept()`.
`tvm.setGasLimit()` is similar to `tvm.accept()`. `tvm.accept()` sets gas limit **g<sub>l</sub>** to
the maximum possible value (depends on the network configuration parameters, usually is equal to
1_000_000 units of gas). `tvm.setGasLimit()` is generally used for accepting external messages and restricting
max possible gas consumption. It may be used to protect from flood by "bad" owner
in a contract that is used by multiple users. Let's consider some scenario:
1. Check whether msg.pubkey() != 0 and msg.pubkey() belongs to the list of trusted public keys;
2. Check whether `m_floodCounter[msg.pubkey()] < 5` where **m_floodCounter** is count of pending
operations of `msg.pubkey()` user.
3. `tvm.setGasLimit(75_000);` accept external message and set gas limit to 75_000.
4. `++m_floodCounter[msg.pubkey()];` increase count of pending operations for current users.
5. `tvm.commit();` save current state if it needs
6. Do other things.
So if some user's public key will be stolen, then a hacker can spam with external messages and
burn at most `5 * 75_000` units of gas instead of `5 * 1_000_000`, because we use `tvm.setGasLimit()` instead
of `tvm.accept()`.
##### tvm.buyGas()
```TVMSolidity
tvm.buyGas(uint value);
```
Computes the amount of gas that can be bought for `value` nanoevers, and sets **g<sub>l</sub>**
accordingly in the same way as [tvm.setGasLimit()](#tvmsetgaslimit).
##### tvm.commit()
```TVMSolidity
tvm.commit();
```
Creates a "check point" of the state variables (by copying them from c7 to c4) and register c5.
If the contract throws an exception at the computing phase, then the state variables and register c5
will roll back to the "check point", and the computing phase will be considered "successful".
If contract doesn't throw an exception, it has no effect.
##### tvm.rawCommit()
```TVMSolidity
tvm.rawCommit();
```
Same as [tvm.commit()](#tvmcommit) but doesn't copy the state variables from c7 to c4. It's a wrapper
for opcode `COMMIT`. See [TVM][1].
**Note**: Don't use `tvm.rawCommit()` after `tvm.accept()` in processing external messages because
you don't save from c7 to c4 the hidden state variable `timestamp` that is used for replay protection.
##### tvm.getData()
```TVMSolidity
tvm.getData() returns (TvmCell);
```
**Note:** Function is experimental.
A dual of the `tvm.setData()`function. It returns value of the `c4` register. Obtaining a raw storage
cell can be useful when upgrading a new version of the contract that introduces an altered data layout.
Manipulation with a raw storage cell requires understanding of the way the compiler stores the data.
Refer to the description of `tvm.setData()` below to get more details.
**Note:** state variables and replay protection timestamp stored in the data cell have the same values
that were before the transaction. See [tvm.commit()](#tvmcommit) to learn about register `c4` update.
##### tvm.setData()
```TVMSolidity
tvm.setData(TvmCell data);
```
**Note:** Function is experimental.
Stores cell `data` in the register `c4`. Mind that after returning from a public function all state variables
from `c7` are copied to `c4` and `tvm.setData` will have no effect. Example hint, how to set `c4`:
```TVMSolidity
TvmCell data = ...;
tvm.setData(data); // set register c4
tvm.rawCommit(); // save register c4 and c5
revert(200); // throw the exception to terminate the transaction
```
Be careful with the hidden state variable `timestamp` and think about possibility of external
messages replaying.
##### tvm.log()
```TVMSolidity
tvm.log(string log);
logtvm(string log);
```
Dumps `log` string. This function is a wrapper for TVM instructions
`PRINTSTR` (for constant literal strings shorter than 16 symbols) and
`STRDUMP` (for other strings). `logtvm` is an alias for `tvm.log(string)`. Example:
```TVMSolidity
tvm.log("Hello, world!");
logtvm("99_Bottles");
string s = "Some_text";
tvm.log(s);
```
**Note:** For long strings dumps only the first 127 symbols.
##### tvm.hexdump() and tvm.bindump()
```TVMSolidity
tvm.hexdump(T a);
tvm.bindump(T a);
```
Dumps cell data or integer. Note that for cells this function dumps data only
from the first cell. `T` must be an integer type or TvmCell.
Example:
```TVMSolidity
TvmBuilder b;
b.storeUnsigned(0x9876543210, 40);
TvmCell c = b.toCell();
tvm.hexdump(c);
tvm.bindump(c);
uint a = 123;
tvm.hexdump(a);
tvm.bindump(a);
int b = -333;
tvm.hexdump(b);
tvm.bindump(b);
```
Expected output for the example:
```TVMLog
CS<9876543210>(0..40)
CS<10011000011101100101010000110010000100001>(0..40)
7B
1111011
-14D
-101001101
```
##### tvm.setcode()
```TVMSolidity
tvm.setcode(TvmCell newCode);
```
This command creates an output action that would change this smart contract
code to that given by the `TvmCell` **newCode** (this change will take effect only
after the successful termination of the current run of the smart contract).
See example of how to use this function:
* [old contract](https://github.com/everx-labs/samples/blob/master/solidity/12_BadContract.sol)
* [new contract](https://github.com/everx-labs/samples/blob/master/solidity/12_NewVersion.sol)
##### tvm.configParam()
```TVMSolidity
tvm.configParam(uint8 paramNumber) returns (TypeA a, TypeB b, ...);
```
Executes TVM instruction "CONFIGPARAM" ([TVM][1] - A.11.4. - F832).
This command returns the value of the global configuration parameter with
integer index **paramNumber**. Argument should be an integer literal.
Supported **paramNumbers**: 1, 15, 17, 34.
##### tvm.rawConfigParam()
```TVMSolidity
tvm.rawConfigParam(uint8 paramNumber) returns (TvmCell cell, bool status);
```
Executes TVM instruction "CONFIGPARAM" ([TVM][1] - A.11.4. - F832).
Returns the value of the global configuration parameter with
integer index **paramNumber** as a `TvmCell` and a boolean status.
##### tvm.rawReserve()
```TVMSolidity
tvm.rawReserve(uint value, uint8 flag);
tvm.rawReserve(uint value, mapping(uint32 => varuint32) currency, uint8 flag);
```
Creates an output action that reserves **reserve** nanoevers. It is roughly equivalent to
create an outbound message carrying **reserve** nanoevers to oneself, so that the subsequent output
actions would not be able to spend more money than the remainder. It's a wrapper for opcodes
"RAWRESERVE" and "RAWRESERVEX". See [TVM][1].
Let's denote:
* `original_balance` is balance of the contract before the computing phase that is equal to balance
of the contract before the transaction minus storage fee. Note: `original_balance` doesn't include
`msg.value` and `original_balance` is not equal to `address(this).balance`.
* `remaining_balance` is contract's current remaining balance at the action phase after some handled
actions and before handing the "rawReserve" action.
Let's consider how much nanoevers (**reserve**) are reserved in all cases of **flag**:
* 0 -> `reserve = value` nanoevers.
* 1 -> `reserve = remaining_balance - value` nanoevers.
All other values of `flag` are invalid.
To make it clear, let's consider the order of `reserve` calculation:
1. if `flag` has bit `+8`, then `value = -value`.
2. if `flag` has bit `+4`, then `value += original_balance`.
3. Check `value >= 0`.
4. if `flag` has bit `+2`, then `value = min(value, remaining_balance)`.
5. if `flag` has bit `+1`, then `value = remaining_balance - value`.
6. `reserve = value`.
7. Check `0 <= reserve <= remaining_balance`.
Example:
```TVMSolidity
tvm.rawReserve(1 ever, 4 + 8);
```
See also: [23_rawReserve.sol](https://github.com/everx-labs/samples/blob/master/solidity/23_rawReserve.sol)
##### tvm.initCodeHash()
```TVMSolidity
tvm.initCodeHash() returns (uint256 hash)
```
Returns the initial code hash that contract had when it was deployed.
[Capabilities](#tvm-capabilities) required: `CapInitCodeHash`.
##### Hashing and cryptography
##### tvm.hash()
```TVMSolidity
tvm.hash(TvmCell cellTree) returns (uint256);
tvm.hash(string data) returns (uint256);
tvm.hash(bytes data) returns (uint256);
tvm.hash(TvmSlice data) returns (uint256);
```
Executes TVM instruction "HASHCU" or "HASHSU" ([TVM][1] - A.11.6. - F900).
It computes the representation hash of a given argument and returns
it as a 256-bit unsigned integer. For `string` and `bytes` it computes
hash of the tree of cells that contains data but not data itself.
See [sha256](#sha256) to count hash of data.
Example:
```TVMSolidity
uint256 hash = tvm.hash(TvmCell cellTree);
uint256 hash = tvm.hash(string);
uint256 hash = tvm.hash(bytes);
```
##### tvm.checkSign()
```TVMSolidity
(1)
tvm.checkSign(uint256 dataHash, uint256 SignHighPart, uint256 SignLowPart, uint256 pubkey) returns (bool);
(2)
tvm.checkSign(uint256 dataHash, TvmSlice signature, uint256 pubkey) returns (bool);
(3)
tvm.checkSign(TvmSlice data, TvmSlice signature, uint256 pubkey) returns (bool);
```
Executes TVM instruction "CHKSIGNU" ([TVM][1] - A.11.6. - F910) for options 1 and 2.
This command checks the Ed25519-signature of the **dataHash** using public key **pubkey**.
Signature is represented by two uint256 **SignHighPart** and **SignLowPart** in the
first option and by the slice **signature** in the second option.
In the third option executes TVM instruction "CHKSIGNS" ([TVM][1] - A.11.6. - F911).
This command checks Ed25519-signature of the **data** using public key **pubkey**.
Signature is represented by the slice **signature**.
If `CapSignatureWithId` [capability](#tvm-capabilities) is set, then TVM use some predefined ID during signature check. Usually ID is `global_id` that can be found in the last block for example.
Example:
```TVMSolidity
// option 1
uint256 dataHash;
uint256 SignHighPart;
uint256 SignLowPart;
uint256 pubkey;
bool signatureIsValid = tvm.checkSign(dataHash, SignHighPart, SignLowPart, pubkey);
// option 2
uint256 dataHash;
TvmSlice signature;
uint256 pubkey;
bool signatureIsValid = tvm.checkSign(dataHash, signature, pubkey);
// option 3
TvmSlice data;
TvmSlice signature;
uint256 pubkey;
bool signatureIsValid = tvm.checkSign(data, signature, pubkey);
```
##### Deploy contract from contract
##### Deploy via new
Either `code` or `stateInit` option must be set when you deploy a contract
from contract via keyword `new`. `stateInit` is a tree of cells that contains
original state of the contract. `stateInit` contains `data`, `code` and another members.
See also ([TBLKCH][2] - A.2.3.2) to read about `stateInit`.
Use `stateInit` option if you have the created account state (maybe offchain or
onchain) and use `code` if you want to create account state in the `new` expression.
**Note**: Address of the new account is calculated as a hash of the `stateInit`.
Constructor function parameters don't influence the address. See
[New contract address problem](#new-contract-address-problem).
[Step-by-step description how to deploy contracts from the contract here](https://github.com/everx-labs/samples/blob/master/solidity/17_ContractProducer.md).
Examples:
* [WalletProducer](https://github.com/everx-labs/samples/blob/master/solidity/17_ContractProducer.sol).
* [SelfDeployer](https://github.com/everx-labs/samples/blob/master/solidity/21_self_deploy.sol).
##### `stateInit` option usage
`stateInit` defines the origin state of the new account.
```TVMSolidity
TvmCell stateInit = ...;
address newWallet = new SimpleWallet{value: 1 ever, stateInit: stateInit}(arg0, arg1, ...);
```
##### `code` option usage
`code` option defines the code of the new contract.
```TVMSolidity
TvmCell code = ...;
address newWallet = new SimpleWallet{value: 1 ever, code: code}(arg0, arg1, ...);
```
The following options can only be used with the `code` option:
* `pubkey` (`uint256`) - defines the public key of the new contract.
* `varInit` (`initializer list`) - used to set [static](#keyword-static) variables of the new contract.
* `splitDepth` (`uint8`) - splitting depth. `0 <= splitDepth <= 31`. By default, it has no value.
Example of usage of these options:
```TVMSolidity
// file SimpleWallet.sol
...
contract SimpleWallet {
address static m_owner;
uint static m_value;
...
}
// file containing a contract that deploys a SimpleWallet
TvmCell code = ...;
address newWallet = new SimpleWallet{
value: 1 ever,
code: code,
pubkey: 0xe8b1d839abe27b2abb9d4a2943a9143a9c7e2ae06799bd24dec1d7a8891ae5dd,
splitDepth: 15,
varInit: {m_owner: address(this), m_value: 15}
}(arg0, arg1, ...);
```
##### Other deploy options
The following options can be used with both `stateInit` and `code`:
* `value` (`varuint16`) - funds attached to the outbound internal message, that creates new account.
This value must be set.
* `currencies` (`mapping(uint32 => varuint32)`) - currencies attached to the outbound internal message.
Defaults to an empty set.
* `bounce` (`bool`) - if it's set and deploy falls (only at the computing phase, not at the action
phase!), then funds will be returned. Otherwise, (flag isn't set or deploying terminated successfully)
the address accepts the funds. Defaults to `true`.
* `wid` (`uint8`) - workchain id of the new account address. Defaults to `0`.
* `flag` (`uint16`) - flag used to send the outbound internal message. Defaults to `0`.
Possible values of the `flag` are described here: [\<address\>.transfer()](#addresstransfer).
```TVMSolidity
TvmCell stateInit = ...;
address newWallet = new SimpleWallet{
stateInit: stateInit,
value: 1 ever,
wid: -1,
flag: 0
}(arg0, arg1, ...);
```
##### Deploy via \<address\>.transfer()
You can also deploy the contract via [\<address\>.transfer()](#addresstransfer).
Just set the option `stateInit`.
* [Example of usage](https://github.com/everx-labs/samples/blob/master/solidity/11_ContractDeployer.sol)
* [Step-by-step description how to deploy contracts from the contract here](https://github.com/everx-labs/samples/blob/master/solidity/17_ContractProducer.md).
##### Deploy the contract with no constructor
If the contract does not have constructor explicitly and does not have state variables with initialisation, then in `*.abi.json` file there is no `constructor` function and no `_constructorFlag` field.
For example: [1_Accumulator_no_ctor.sol](https://github.com/everx-labs/samples/blob/master/solidity/1_Accumulator_no_ctor.sol) and [1_Accumulator_no_ctor.abi.json](https://github.com/everx-labs/samples/blob/master/solidity/1_Accumulator_no_ctor.abi.json). To deploy this contractor by external message with help `ever-cli`, use parameter `method` for `deploy` and `deployx` commands:
```bash
ever-cli deploy --method add '{"delta": 123}' ...
```
To deploy a contractor by internal message, use option `stateInit` for [External function calls](#external-function-calls). See `deployNoConstructor` and `deployNoConstructor2` functions [11_ContractDeployer.sol](https://github.com/everx-labs/samples/blob/master/solidity/11_ContractDeployer.sol) as samples of deploying [11_Waller_no_constructor.sol](https://github.com/everx-labs/samples/blob/master/solidity/11_Waller_no_constructor.sol).
##### New contract address problem
Address of the new account is calculated as a hash of the `stateInit`.
Parameters of the constructor don't influence the address. The problem
is that hacker can deploy the contract with your `stateInit` before you
with malicious constructor parameters.
Let's consider how to protect against this problem:
1. Constructor is called by external message.
We must Check if we didn't forget to set the public key in the contract and the
inbound message is signed by that key. If hacker doesn't have your private
key, then he can't sign message to call the constructor.
See [constructor of WalletProducer](https://github.com/everx-labs/samples/blob/master/solidity/17_ContractProducer.sol).
2. Constructor is called by internal message.
We should define static variable in the new contract that will contain
address of the creator. Address of the creator will be a part of the `stateInit`.
And in the constructor we must check address of the message sender.
See [function `deployWallet` how to deploy contract](https://github.com/everx-labs/samples/blob/master/solidity/17_ContractProducer.sol).
See [constructor of SimpleWallet](https://github.com/everx-labs/samples/blob/master/solidity/17_SimpleWallet.sol).
If some contract should deploy plenty of contracts (with some contract's
public key), then it's a good idea to declare static variable in the deployed
contract. This variable can contain some sequence number. It will allow
each new contact to have unique `stateInit`.
See [SimpleWallet](https://github.com/everx-labs/samples/blob/master/solidity/17_SimpleWallet.sol).
**Note**: contract's public key (`tvm.pubkey()`) is a part of `stateInit`.
##### Misc functions from `tvm`
##### tvm.code()
```TVMSolidity
tvm.code() returns (TvmCell);
```
Returns contract's code. [Capabilities](#tvm-capabilities) required: `CapMycode`.
See [SelfDeployer](https://github.com/everx-labs/samples/blob/master/solidity/21_self_deploy.sol).
##### tvm.pubkey()
```TVMSolidity
tvm.pubkey() returns (uint256);
```
Returns contract's public key, stored in contract data. If key is not set, function returns 0.
##### tvm.setPubkey()
```TVMSolidity
tvm.setPubkey(uint256 newPubkey);
```
Set new contract's public key. Contract's public key can be obtained from `tvm.pubkey`.
##### tvm.setCurrentCode()
```TVMSolidity
tvm.setCurrentCode(TvmCell newCode);
```
Changes this smart contract current code to that given by Cell **newCode**. Unlike [tvm.setcode()](#tvmsetcode)
this function changes code of the smart contract only for current TVM execution, but has no effect
after termination of the current run of the smart contract.
See example of how to use this function:
* [old contract](https://github.com/everx-labs/samples/blob/master/solidity/12_BadContract.sol)
* [new contract](https://github.com/everx-labs/samples/blob/master/solidity/12_NewVersion.sol)
##### tvm.resetStorage()
```TVMSolidity
tvm.resetStorage();
```
Resets all state variables to their default values.
##### tvm.exit() and tvm.exit1()
```TVMSolidity
tvm.exit();
tvm.exit1();
```
Functions are used to save state variables and quickly terminate execution of the smart contract.
Exit code of the compute phase is equal to zero/one for `tvm.exit`/`tvm.exit1`.
Example:
```TVMSolidity
function g0(uint a) private {
if (a == 0) {
tvm.exit();
}
//...
}
function g1(uint a) private {
if (a == 0) {
tvm.exit1();
}
//...
}
```
#### tvm.sendrawmsg()
```TVMSolidity
tvm.sendrawmsg(TvmCell msg, uint8 flag);
```
Send the internal/external message `msg` with `flag`. It's a wrapper for opcode
`SENDRAWMSG` ([TVM][1] - A.11.10).
Internal message `msg` can be generated by [abi.encodeIntMsg()](#abiencodeintmsg).
Possible values of `flag` are described here: [\<address\>.transfer()](#addresstransfer).
**Note:** make sure that `msg` has a correct format and follows the [TL-B scheme][3] of `Message X`.
For example:
```TVMSolidity
TvmCell msg = ...
tvm.sendrawmsg(msg, 2);
```
If the function is called by external message and `msg` has a wrong format (for example, the field
`init` of `Message X` is not valid), then the transaction will be replayed despite the usage of flag 2.
It will happen because the transaction will fail at the action phase.
#### **bls** namespace
Operations on a pairing friendly BLS12-381 curve. BLS values are represented in TVM in the following way:
* G1-points and public keys: 48-byte slice.
* G2-points and signatures: 96-byte slice.
* Elements of field FP: 48-byte slice.
* Elements of field FP2: 96-byte slice.
* Messages: slice. Number of bits should be divisible by 8.
When input value is a point or a field element, the slice may have more than 48/96 bytes. In this case only the first 48/96 bytes are taken. If the slice has less bytes (or if message size is not divisible by 8), cell underflow exception is thrown.
[Capabilities](#tvm-capabilities) required: `CapTvmV20`.
#### bls.verify
```TVMSolidity
bls.verify(TvmSlice pubkey, TvmSlice message, TvmSlice sign) returns (bool)
```
Checks BLS signature. Returns `true` on success, `false` otherwise. Example:
```TVMSolidity
TvmSlice pubkey = "b65cfaf56cebd6083320bf9a1c2010d4775310c5e7b348546dce0f62aa1ad0c29e15a58e251582faa7879d74e9d4034b";
TvmSlice message = TvmSlice(bytes("Hello, BLS verify!"));
TvmSlice sign = "aa652737cad33a9b332300ecd53f1995e5d6c6ff5eb233c04b2e32ca1169524fee64d58575cb42a1a34e1bf3a61c550814d0147b2b82a668ef7c917c756e489e8ff57d64efbbf533d7995db28377d6442ec952268a2bf30d5770d4e8a9d56f9c";
bool ok = bls.verify(pubkey, message, sign);
```
#### bls.aggregate
```TVMSolidity
(1)
bls.aggregate(vector(TvmSlice) signs) returns (TvmSlice sign)
(2)
bls.aggregate(TvmSlice sign0, TvmSlice sign1, ...) returns (TvmSlice sign)
```
(1) Aggregates signatures if `signs.length() > 0`. Throw exception if `signs.empty()` or if some `signs[i]` is not a valid signature.
(2) Same as (1) but takes `TvmSlice`'s.
Example:
```TVMSolidity
vector(TvmSlice) signs;
signs.push("8b1eac18b6e7a38f2b2763c9a03c3b6cff4110f18c4d363eec455463bd5c8671fb81204c4732406d72468a1474df6133147a2240f4073a472ef419f23011ee4d6cf02fceb844398e33e2e331635dace3b26464a6851e10f6895923c568582fbd");
signs.push("94ec60eb8d2b657dead5e1232b8f9cc0162467b08f02e252e97622297787a74b6496607036089837fe5b52244bbbb6d00d3d7cc43812688451229d9e96f704401db053956c588203ba7638e8882746c16e701557f34b0c08bbe097483aec161e");
signs.push("8cdbeadb3ee574a4f796f10d656885f143f454cc6a2d42cf8cabcd592d577c5108e4258a7b14f0aafe6c86927b3e70030432a2e5aafa97ee1587bbdd8b69af044734defcf3c391515ab26616e15f5825b4b022a7df7b44f65a8792c54762e579");
TvmSlice sign = bls.aggregate(signs);
```
```TVMSolidity
TvmSlice sign0 = "8b1eac18b6e7a38f2b2763c9a03c3b6cff4110f18c4d363eec455463bd5c8671fb81204c4732406d72468a1474df6133147a2240f4073a472ef419f23011ee4d6cf02fceb844398e33e2e331635dace3b26464a6851e10f6895923c568582fbd";
TvmSlice sign1 = "94ec60eb8d2b657dead5e1232b8f9cc0162467b08f02e252e97622297787a74b6496607036089837fe5b52244bbbb6d00d3d7cc43812688451229d9e96f704401db053956c588203ba7638e8882746c16e701557f34b0c08bbe097483aec161e";
TvmSlice sign2 = "8cdbeadb3ee574a4f796f10d656885f143f454cc6a2d42cf8cabcd592d577c5108e4258a7b14f0aafe6c86927b3e70030432a2e5aafa97ee1587bbdd8b69af044734defcf3c391515ab26616e15f5825b4b022a7df7b44f65a8792c54762e579";
TvmSlice sign = bls.aggregate(sign0, sign1, sign2);
```
#### bls.fastAggregateVerify
```TVMSolidity
(1)
bls.fastAggregateVerify(vector(TvmSlice) pubkeys, TvmSlice message, TvmSlice singature) returns (bool ok)
(2)
bls.fastAggregateVerify(TvmSlice pubkey0, TvmSlice pubkey1, ..., TvmSlice message, TvmSlice singature) returns (bool ok)
```
(1) Checks aggregated BLS signature for `pubkeys` and `message`. Returns `true` on success, `false` otherwise. Return `false` if `pubkeys.empty()`.
(2) Same as (1) but takes `TvmSlice`'s.
Example:
```TVMSolidity
vector(TvmSlice) pubkeys;
pubkeys.push("a44184a47ad3fc0069cf7a95650a28af2ed715beab28651a7ff433e26c0fff714d21cc5657367bc563c6df28fb446d8f");
pubkeys.push("832c0eca9f8cae87a1c6362838b34723cf63a1f69e366d64f3c61fc237217c4bea601cfbf4d6c18849ed4f9487b4a20c");
pubkeys.push("9595aa3c5cb3d7c763fa6b52294ebde264bdf49748efbbe7737c35532db8fabc666bb0d186f329c8bdafddfbdcbc3ca6");
TvmSlice message = TvmSlice(bytes("Hello, BLS fast aggregate and verify!"));
TvmSlice singature = "8420b1944c64f74dd67dc9f5ab210bab928e2edd4ce7e40c6ec3f5422c99322a5a8f3a8527eb31366c9a74752d1dce340d5a98fbc7a04738c956e74e7ba77b278cbc52afc63460c127998aae5aa1c3c49e8c48c30cc92451a0a275a47f219602";
bool ok = bls.fastAggregateVerify(pubkeys, message, singature);
```
```TVMSolidity
TvmSlice pk0 = "a44184a47ad3fc0069cf7a95650a28af2ed715beab28651a7ff433e26c0fff714d21cc5657367bc563c6df28fb446d8f";
TvmSlice pk1 = "832c0eca9f8cae87a1c6362838b34723cf63a1f69e366d64f3c61fc237217c4bea601cfbf4d6c18849ed4f9487b4a20c";
TvmSlice pk2 = "9595aa3c5cb3d7c763fa6b52294ebde264bdf49748efbbe7737c35532db8fabc666bb0d186f329c8bdafddfbdcbc3ca6";
TvmSlice message = TvmSlice(bytes("Hello, BLS fast aggregate and verify!"));
TvmSlice singature = "8420b1944c64f74dd67dc9f5ab210bab928e2edd4ce7e40c6ec3f5422c99322a5a8f3a8527eb31366c9a74752d1dce340d5a98fbc7a04738c956e74e7ba77b278cbc52afc63460c127998aae5aa1c3c49e8c48c30cc92451a0a275a47f219602";
bool ok = bls.fastAggregateVerify(pk0, pk1, pk2, message, singature);
```
#### bls.aggregateVerify()
```TVMSolidity
(1)
bls.aggregateVerify(vector(TvmSlice, TvmSlice) pubkeysMessages, TvmSlice singature) returns (bool ok)
(2)
bls.aggregateVerify(TvmSlice pubkey0, TvmSlice pubkey1, ..., TvmSlice message0, TvmSlice message1, ..., TvmSlice singature) returns (bool ok)
```
(1) Checks aggregated BLS signature for key-message pairs `pubkeysMessages`. Returns `true` on success, `false` otherwise. Returns `false` if `pubkeysMessages.empty()`.
(2) Same as (1) but takes `TvmSlice`'s.
```TVMSolidity
vector(TvmSlice, TvmSlice) pubkeysMessages;
TvmSlice pubkey0 = "b75f0360095de73c4790f803153ded0f3e6aefa6f0aac8bfd344a44a3de361e3f6f111c0cf0ad0c4a0861492f9f1aeb1";
TvmSlice message0 = TvmSlice(bytes("Hello, BLS fast aggregate and verify 0!"));
pubkeysMessages.push(pubkey0, message0);
TvmSlice pubkey1 = "a31e12bb4ffa75aabbae8ec2367015ba3fc749ac3826539e7d0665c285397d02b48414a23f8b33ecccc750b3afffacf6";
TvmSlice message1 = TvmSlice(bytes("Hello, BLS fast aggregate and verify 1!"));
pubkeysMessages.push(pubkey1, message1);
TvmSlice pubkey2 = "8de5f18ca5938efa896fbc4894c6044cdf89e778bf88584be48d6a6235c504cd45a44a68620f763aea043b6381add1f7";
TvmSlice message2 = TvmSlice(bytes("Hello, BLS fast aggregate and verify 2!"));
pubkeysMessages.push(pubkey2, message2);
TvmSlice singature = "8b8238896dfe3b02dc463c6e645e36fb78add51dc8ce32f40ecf60a418e92762856c3427b672be67278b5c4946b8c5a30fee60e5c38fdb644036a4f29ac9a039ed4e3b64cb7fef303052f33ac4391f95d482a27c8341246516a13cb72e58097b";
bool ok = bls.aggregateVerify(pubkeysMessages, singature);
```
```TVMSolidity
TvmSlice pubkey0 = "b75f0360095de73c4790f803153ded0f3e6aefa6f0aac8bfd344a44a3de361e3f6f111c0cf0ad0c4a0861492f9f1aeb1";
TvmSlice message0 = TvmSlice(bytes("Hello, BLS fast aggregate and verify 0!"));
TvmSlice pubkey1 = "a31e12bb4ffa75aabbae8ec2367015ba3fc749ac3826539e7d0665c285397d02b48414a23f8b33ecccc750b3afffacf6";
TvmSlice message1 = TvmSlice(bytes("Hello, BLS fast aggregate and verify 1!"));
TvmSlice pubkey2 = "8de5f18ca5938efa896fbc4894c6044cdf89e778bf88584be48d6a6235c504cd45a44a68620f763aea043b6381add1f7";
TvmSlice message2 = TvmSlice(bytes("Hello, BLS fast aggregate and verify 2!"));
TvmSlice singature = "8b8238896dfe3b02dc463c6e645e36fb78add51dc8ce32f40ecf60a418e92762856c3427b672be67278b5c4946b8c5a30fee60e5c38fdb644036a4f29ac9a039ed4e3b64cb7fef303052f33ac4391f95d482a27c8341246516a13cb72e58097b";
bool ok = bls.aggregateVerify(pubkey0, message0, pubkey1, message1, pubkey2, message2, singature);
```
#### bls.g1Zero() and bls.g2Zero()
```TVMSolidity
bls.g1Zero() returns (TvmSlice)
bls.g2Zero() returns (TvmSlice)
```
Returns zero point in G1/G2.
#### bls.g1IsZero() and bls.g2IsZero()
```TVMSolidity
bls.g1Zero(TvmSlice x) returns (bool isZero)
bls.g2Zero(TvmSlice x) returns (bool isZero)
```
Checks that G1/G2 point `x` is equal to zero.
#### bls.g1Add() and bls.g2Add()
```TVMSolidity
bls.g1Add(TvmSlice a, TvmSlice b) returns (TvmSlice res)
bls.g2Add(TvmSlice a, TvmSlice b) returns (TvmSlice res)
```
Addition on G1/G2.
#### bls.g1Sub() and bls.g2Sub()
```TVMSolidity
bls.g1Sub(TvmSlice a, TvmSlice b) returns (TvmSlice res)
bls.g2Sub(TvmSlice a, TvmSlice b) returns (TvmSlice res)
```
Subtraction on G1/G2.
#### bls.g1Neg() and bls.g2Neg()
```TVMSolidity
bls.g1Neg(TvmSlice x) returns (TvmSlice res)
bls.g2Neg(TvmSlice x) returns (TvmSlice res)
```
Negation on G1/G2.
#### bls.g1Mul() and bls.g2Mul()
```TVMSolidity
bls.g1Mul(TvmSlice x, int s) returns (TvmSlice res)
bls.g2Mul(TvmSlice x, int s) returns (TvmSlice res)
```
Multiplies G1/G2 point `x` by scalar `s`. Any `s` is valid, including negative.
#### bls.g1InGroup() and bls.g2InGroup()
```TVMSolidity
bls.g1Mul(TvmSlice x) returns (bool ok)
bls.g2Mul(TvmSlice x) returns (bool ok)
```
Checks that slice `x` represents a valid element of G1/G2.
#### bls.r()
```TVMSolidity
bls.r() returns (uint255)
```
Pushes the order of G1 and G2 (approx. 2^255). It's 52435875175126190479447740508185965837690552500527637822603658699938581184513.
#### bls.g1MultiExp() and bls.g2MultiExp()
```TVMSolidity
(1)
bls.g1MultiExp(vector(TvmSlice, int) x_s) returns (TvmSlice)
bls.g2MultiExp(vector(TvmSlice, int) x_s) returns (TvmSlice)
(2)
bls.g1MultiExp(TvmSlice x0, int s0, TvmSlice x1, int s1, ...) returns (TvmSlice)
bls.g2MultiExp(TvmSlice x0, int s0, TvmSlice x1, int s1, ...) returns (TvmSlice)
```
(1) Calculates `x_1*s_1+...+x_n*s_n` for G1/G2 points `x_i` and scalars `s_i`. Returns zero point if `n==0`. Any `s_i` is valid, including negative.
(2) Same as (1) but takes `TvmSlice`'s and `int`'s.
```TVMSolidity
TvmSlice a = bls.mapToG1("7abd13983c76661a98659da83066c71bd6581baf20c82c825b007bf8057a258dc53f7a6d44fb6fdecb63d9586e845d92");
TvmSlice b = bls.mapToG1("7abd13983c76661118659da83066c71bd6581baf20c82c825b007bf8057a258dc53f7a6d44fb6fdecb63d9586e845d92");
TvmSlice c = bls.mapToG1("7abd13983c76661118659da83066c71bd658100020c82c825b007bf8057a258dc53f7a6d44fb6fdecb63d9586e845d92");
vector(TvmSlice, int) values;
values.push(a, 2);
values.push(b, 5);
values.push(c, 13537812947843);
TvmSlice res = bls.g1MultiExp(values);
TvmSlice aa = bls.g1Mul(a, 2);
TvmSlice bb = bls.g1Mul(b, 5);
TvmSlice cc = bls.g1Mul(c, 13537812947843);
TvmSlice res2 = bls.g1Add(bls.g1Add(aa, bb), cc);
require(res == res2);
```
```TVMSolidity
TvmSlice a = bls.mapToG1("7abd13983c76661a98659da83066c71bd6581baf20c82c825b007bf8057a258dc53f7a6d44fb6fdecb63d9586e845d92");
TvmSlice b = bls.mapToG1("7abd13983c76661118659da83066c71bd6581baf20c82c825b007bf8057a258dc53f7a6d44fb6fdecb63d9586e845d92");
TvmSlice c = bls.mapToG1("7abd13983c76661118659da83066c71bd658100020c82c825b007bf8057a258dc53f7a6d44fb6fdecb63d9586e845d92");
TvmSlice res = bls.g1MultiExp(a, 2, b, 5, c, 13537812947843);
TvmSlice aa = bls.g1Mul(a, 2);
TvmSlice bb = bls.g1Mul(b, 5);
TvmSlice cc = bls.g1Mul(c, 13537812947843);
TvmSlice res2 = bls.g1Add(bls.g1Add(aa, bb), cc);
require(res == res2);
```
#### **math** namespace
`T` is an integer, [variable integer](#varint-and-varuint), [qintN and quintN](#qintn-and-quintn) or fixed point type in the `math.*` functions where applicable.
Fixed point type is not applicable for `math.modpow2()`, `math.muldiv[r|c]()`, `math.muldivmod()` and `math.divmod()`.
##### math.min() math.max()
```TVMSolidity
math.min(T a, T b, ...) returns (T);
math.max(T a, T b, ...) returns (T);
```
Returns the minimal (maximal) value of the passed arguments.
##### math.minmax()
```TVMSolidity
math.minmax(T a, T b) returns (T /*min*/, T /*max*/);
```
Returns minimal and maximal values of the passed arguments.
Example:
```TVMSolidity
(uint a, uint b) = math.minmax(20, 10); // (a, b) == (10, 20)
```
##### math.abs()
```TVMSolidity
math.abs(T1 val) returns (T2);
```
Computes the absolute value of the given integer. Throws an exception if absolute value of `val` does not fit into T2.
Example:
```TVMSolidity
int256 a = -100;
uint255 b = math.abs(a); // b == 100
int256 a = type(int256).min;
uint255 b = math.abs(a); // throws an exception
```
##### math.modpow2()
```TVMSolidity
math.modpow2(T value, uint power) returns (T);
```
Computes the `value mod 2^power`. Note: `power` should be a constant integer.
Example:
```TVMSolidity
uint a = math.modpow2(21, 4); // a == 5 because 21 % (2**4) == 21 % 16 == 5
uint constant pow = 10;
uint val = 1026;
uint b = math.modpow2(val, pow); // b == 2 because 1026 % (2**10) == 1026 % 1024 == 2
```
##### math.divr() math.divc()
```TVMSolidity
math.divc(T a, T b) returns (T);
math.divr(T a, T b) returns (T);
```
Returns result of the division of two integers. The return value is rounded. **ceiling** and **nearest** modes are used for `divc` and `divr`
respectively. See also: [Division and rounding](#division-and-rounding).
Example:
```TVMSolidity
int c = math.divc(10, 3); // c == 4
int c = math.divr(10, 3); // c == 3
fixed32x2 a = 0.25;
fixed32x2 res = math.divc(a, 2); // res == 0.13
```
##### math.divmod()
```TVMSolidity
math.divmod(T a, T b) returns (T /*result*/, T /*remainder*/);
```
This function divides the first number by the second and returns the result and the
remainder. Result is rounded to the floor.
Example:
```TVMSolidity
uint a = 11;
uint b = 3;
(uint d, uint r) = math.divmod(a, b); // (d, r) == (3, 2)
int e = -11;
int f = 3;
(int h, int p) = math.divmod(e, f); // (h, p) == (-3, 2)
```
##### math.muldiv() math.muldivr() math.muldivc()
```TVMSolidity
math.muldiv(T a, T b, T c) returns (T);
math.muldivr(T a, T b, T c) returns (T);
math.muldivc(T a, T b, T c) returns (T);
```
Multiplies two values and then divides the result by a third value. The return value is rounded. **floor**, **ceiling** and **nearest** modes are used for `muldiv`,
`muldivc` and `muldivr` respectively. See also: [Division and rounding](#division-and-rounding).
Example:
```TVMSolidity
uint res = math.muldiv(3, 7, 2); // res == 10
uint res = math.muldivr(3, 7, 2); // res == 11
uint res = math.muldivc(3, 7, 2); // res == 11
```
##### math.muldivmod()
```TVMSolidity
math.muldivmod(T a, T b, T c) returns (T /*quotient*/, T /*remainder*/);
```
This instruction multiplies first two arguments, divides the result by third argument and returns
the result and the remainder. Intermediate result is stored in the 514 bit buffer, and the final
result is rounded to the floor.
Example:
```TVMSolidity
uint a = 3;
uint b = 2;
uint c = 5;
(uint d, uint r) = math.muldivmod(a, b, c); // (d, r) == (1, 1)
int e = -1;
int f = 3;
int g = 2;
(int h, int p) = math.muldivmod(e, f, g); // (h, p) == (-2, 1)
```
##### math.mulmod()
```TVMSolidity
math.mulmod(T a, T b, T c) returns (T /*remainder*/);
```
Same as [math.muldivmod()](#mathmuldivmod) but returns only remainder. Example:
```TVMSolidity
uint constant P = 2**255 - 19;
function f() public pure {
uint a = rnd.next(P);
uint b = rnd.next(P);
uint c = math.mulmod(a, b, P);
//...
}
```
##### math.sign()
```TVMSolidity
math.sign(T val) returns (int2);
```
Returns:
* -1 if `val` is negative;
* 0 if `val` is zero;
* 1 if `val` is positive.
Example:
```TVMSolidity
int8 sign = math.sign(-100); // sign == -1
int8 sign = math.sign(100); // sign == 1
int8 sign = math.sign(0); // sign == 0
```
##### **tx** namespace
##### tx.logicaltime
```TVMSolidity
tx.logicaltime (uint64);
```
Returns the logical time of the current transaction.
##### tx.storageFee
```TVMSolidity
tx.storageFee (varuint16);
```
Returns the storage fee paid in the current transaction. [Capabilities](#tvm-capabilities) required: `CapStorageFeeToTvm`.
##### **block** namespace
##### block.timestamp
```TVMSolidity
block.timestamp (uint32);
```
Returns the current Unix time. Unix time is the same for the all transactions from one block.
##### block.seqno
```TVMSolidity
block.seqno returns (uint32);
```
Returns the seq no of the current block.
##### block.logicaltime
```TVMSolidity
block.logicaltime (uint64);
```
Returns the starting logical time of the current block.
##### **rnd** namespace
The pseudorandom number generator uses the random seed. The
initial value of the random seed before a smart contract execution in
TVM compatible blockchains is a hash of the smart contract address and the global
block random seed. If there are several runs of the same smart contract
inside a block, then all of these runs will have the same random seed.
This can be fixed, for example, by running `rnd.shuffle()` (without
parameters) each time before using the pseudorandom number generator.
##### rnd.next
```TVMSolidity
(1)
rnd.next() returns (uint);
(2)
rnd.next(T limit) returns (T);
```
Generates a new pseudo-random number.
(1) Returns `uint256` number.
(2) If the first argument `limit > 0`, then function returns the value in the
range `0..limit-1`. Else if `limit < 0`, then the returned value lies in range
`limit..-1`. Else if `limit == 0`, then it returns `0`.
Example:
```TVMSolidity
// (1)
uint256 r0 = rnd.next(); // 0..2^256-1
// (2)
uint8 r1 = rnd.next(100); // 0..99
int8 r2 = rnd.next(int8(100)); // 0..99
int8 r3 = rnd.next(int8(-100)); // -100..-1
```
##### rnd.getSeed
```TVMSolidity
rnd.getSeed() returns (uint256);
```
Returns the current random seed.
##### rnd.setSeed
```TVMSolidity
rnd.setSeed(uint256 x);
```
Sets the random seed to `x`.
##### rnd.shuffle
```TVMSolidity
(1)
rnd.shuffle(uint someNumber);
(2)
rnd.shuffle();
```
Randomizes the random seed.
(1) Mixes the random seed and `someNumber`. The result is set as the random seed.
(2) Mixes the random seed and the logical time of the current transaction.
The result is set as the random seed.
Example:
```TVMSolidity
(1)
uint256 someNumber = ...;
rnd.shuffle(someNumber);
(2)
rnd.shuffle();
```
#### abi namespace
##### abi.encode(), abi.decode()
```TVMSolidity
(1)
abi.encode(TypeA a, TypeB b, ...) returns (TvmCell /*cell*/);
(2)
abi.decode(TvmCell cell, (TypeA, TypeB, ...)) returns (TypeA /*a*/, TypeB /*b*/, ...);
```
`abi.encode` creates `cell` from the values.
`abi.decode` decodes the `cell` and returns the values. Note: all types must be set in `abi.decode`.
Otherwise, `abi.decode` throws an exception.
Example:
```TVMSolidity
// pack the values to the cell
TvmCell cell = abi.encode(uint(1), uint(2), uint(3), uint(4));
// unpack the cell
(uint a, uint b, uint c, uint d) = abi.decode(cell, (uint, uint, uint, uint));
// a == 1
// b == 2
// c == 3
// d == 4
```
##### abi.encodeData()
```TVMSolidity
abi.encodeData({uint256 pubkey, contract Contract, varInit: {VarName0: varValue0, ...}});
```
Generates `data` field of the `StateInit` ([TBLKCH][2] - 3.1.7.). Parameters are the same as in
[abi.encodeStateInit()](#abiencodestateinit).
```TVMSolidity
// SimpleWallet.sol
contract SimpleWallet {
uint static m_id;
address static m_creator;
// ...
}
// Usage
TvmCell data = abi.encodeData({
contr: SimpleWallet,
varInit: {m_id: 1, m_creator: address(this)},
pubkey: 0x3f82435f2bd40915c28f56d3c2f07af4108931ae8bf1ca9403dcf77d96250827
});
TvmCell code = ...;
TvmCell stateInit = abi.encodeStateInit({code: code, data: data});
// Note, the code above can be simplified to:
TvmCell stateInit = abi.encodeStateInit({
code: code,
contr: SimpleWallet,
varInit: {m_id: 1, m_creator: address(this)},
pubkey: 0x3f82435f2bd40915c28f56d3c2f07af4108931ae8bf1ca9403dcf77d96250827
});
```
##### abi.encodeOldDataInit()
```TVMSolidity
abi.encodeOldDataInit() returns (TvmCell);
```
Same as [abi.encodeData()](#abiencodedata) but generate data in the format that was used in the compiler < 0.72.0. This function can be used to deploy old contracts (that was compiled < 0.72.0) from new ones. Example:
File with old contracts that was compiled by compiler < 0.72.0:
```TVMSolidity
pragma tvm-solidity >= 0.72.0; // set new version
contract SimpleContractA {
uint static m_x0;
uint static m_x1;
}
// Remove all code from old contracts but state variables and contructor declaration
contract SimpleContractB is SimpleContractA {
uint static m_x2;
constructor(string name) {
}
}
```
File with new contracts:
```TVMSolidity
pragma tvm-solidity >= 0.72.0;
contract ContractCreator {
function deploy(uint pubkey, TvmCell code) public pure returns (address) {
TvmCell data = abi.encodeOldDataInit({
pubkey: pubkey,
varInit: {
m_x0: 100,
m_x1: 200,
m_x2: 300
},
contr: SimpleContractB
});
TvmCell stateInit = abi.encodeStateInit({
code: code,
data: data
});
SimpleContractB addr = new SimpleContractB{
wid: 0,
value: 1 ever,
stateInit: stateInit,
flag: 1
}("Hello, world!");
return addr;
}
}
```
##### abi.decodeData()
```TVMSolidity
abi.decodeData(ContractName, TvmSlice) returns (uint256 /*pubkey*/, uint64 /*timestamp*/, bool /*constructorFlag*/, Type1 /*var1*/, Type2 /*var2*/, ...);
```
Loads state variables from `TvmSlice` that is obtained from the field `data` of `stateInit`.
Example:
```
contract A {
uint a = 111;
uint b = 22;
uint c = 3;
uint d = 44;
address e = address(12);
address f;
}
contract B {
function f(TvmCell data) public pure {
TvmSlice s = data.toSlice();
(uint256 pubkey, uint64 timestamp, bool flag,
uint a, uint b, uint c, uint d, address e, address f) = abi.decodeData(A, s);
// pubkey - pubkey of the contract A
// timestamp - timestamp that used for replay protection
// flag - always is equal to true
// a == 111
// b == 22
// c == 3
// d == 44
// e == address(12)
// f == address.addrNone
// s.empty()
}
}
```
##### abi.encodeStateInit()
```TVMSolidity
// 1)
abi.encodeStateInit(TvmCell code, TvmCell data) returns (TvmCell stateInit);
// 2)
abi.encodeStateInit(TvmCell code, TvmCell data, uint8 splitDepth) returns (TvmCell stateInit);
// 3)
abi.encodeStateInit({TvmCell code, TvmCell data, uint8 splitDepth,
uint256 pubkey, Contract contr, varInit: {VarName0: varValue0, ...}});
```
Generates a `StateInit` ([TBLKCH][2] - 3.1.7.) from `code` and `data` `TvmCell`s.
Member `splitDepth` of the tree of cell `StateInit`:
1) is not set. Has no value.
2) is set. `0 <= splitDepth <= 31`
3) Arguments can also be set with names.
List of possible names:
* `code` (`TvmCell`) - defines the code field of the `StateInit`. Must be specified.
* `data` (`TvmCell`) - defines the data field of the `StateInit`. Conflicts with `pubkey` and
`varInit`. Can be omitted, in this case data field would be built from `pubkey` and `varInit`.
* `splitDepth` (`uint8`) - splitting depth. `0 <= splitDepth <= 31`. Can be omitted. By default,
it has no value.
* `pubkey` (`uint256`) - defines the public key of the new contract. Conflicts with `data`.
Can be omitted, default value is 0.
* `varInit` (`initializer list`) - used to set [static](#keyword-static) variables of the contract.
Conflicts with `data` and requires `contr` to be set. Can be omitted.
* `contr` (`contract`) - defines the contract whose `StateInit` is being built. Mandatory to be set if the
option `varInit` is specified.
Examples of this function usage:
```TvmSolidity
contract A {
uint static var0;
address static var1;
}
contract C {
function f() public pure {
TvmCell code;
TvmCell data;
uint8 depth;
TvmCell stateInit = abi.encodeStateInit(code, data);
stateInit = abi.encodeStateInit(code, data, depth);
}
function f1() public pure {
TvmCell code;
TvmCell data;
uint8 depth;
uint pubkey;
uint var0;
address var1;
TvmCell stateInit1 = abi.encodeStateInit({code: code, data: data, splitDepth: depth});
stateInit1 = abi.encodeStateInit({code: code, splitDepth: depth, varInit: {var0: var0, var1: var1}, pubkey: pubkey, contr: A});
stateInit1 = abi.encodeStateInit({varInit: {var0: var0, var1: var1}, pubkey: pubkey, contr: A, code: code, splitDepth: depth});
stateInit1 = abi.encodeStateInit({contr: A, varInit: {var0: var0, var1: var1}, pubkey: pubkey, code: code, splitDepth: depth});
stateInit1 = abi.encodeStateInit({contr: A, varInit: {var0: var0, var1: var1}, pubkey: pubkey, code: code});
stateInit1 = abi.encodeStateInit({contr: A, varInit: {var0: var0, var1: var1}, code: code, splitDepth: depth});
}
}
```
##### abi.stateInitHash()
```TVMSolidity
abi.stateInitHash(uint256 codeHash, uint256 dataHash, uint16 codeDepth, uint16 dataDepth) returns (uint256);
```
Calculates hash of the stateInit for given code and data specifications.
Example:
```TVMSolidity
TvmCell code = ...;
TvmCell data = ...;
uint codeHash = tvm.hash(code);
uint dataHash = tvm.hash(data);
uint16 codeDepth = code.depth();
uint16 dataDepth = data.depth();
uint256 hash = abi.stateInitHash(codeHash, dataHash, codeDepth, dataDepth);
```
See also [internal doc](https://github.com/everx-labs/TVM-Solidity-Compiler/blob/master/docs/internal/stateInit_hash.md) to read more about this
function mechanics.
##### abi.encodeBody()
```TVMSolidity
abi.encodeBody(function, arg0, arg1, arg2, ...) returns (TvmCell);
abi.encodeBody(function, callbackFunction, arg0, arg1, arg2, ...) returns (TvmCell);
abi.encodeBody(contract, arg0, arg1, arg2, ...) returns (TvmCell);
```
Constructs a message body for the function call. Body can be used as a payload for [\<address\>.transfer()](#addresstransfer).
If the **function** is `responsible`, **callbackFunction** must be set.
Example:
```TVMSolidity
contract Remote {
constructor(uint x, uint y, uint z) public { /* */ }
function func(uint256 num, int64 num2) public pure { /* */ }
function getCost(uint256 num) public responsible pure returns (uint128) { /* */ }
}
// deploy the contract
TvmCell body = abi.encodeBody(Remote, 100, 200, 300);
addr.transfer({value: 10 ever, body: body, stateInit: stateInit });
// call the function
TvmCell body = abi.encodeBody(Remote.func, 123, -654);
addr.transfer({value: 10 ever, body: body});
// call the responsible function
TvmCell body = abi.encodeBody(Remote.getCost, onGetCost, 105);
addr.transfer({value: 10 ever, body: body});
```
See also:
* [External function calls](#external-function-calls)
* [abi.loadFunctionParams()](#abidecodefunctionparams)
* [abi.encodeIntMsg()](#abiencodeintmsg)
##### abi.decodeFunctionParams()
```TVMSolidity
// Loads parameters of the public/external function without "responsible" attribute
abi.decodeFunctionParams(functionName) returns (TypeA /*a*/, TypeB /*b*/, ...);
// Loads parameters of the public/external function with "responsible" attribute
abi.decodeFunctionParams(functionName) returns (uint32 callbackFunctionId, TypeA /*a*/, TypeB /*b*/, ...);
// Loads constructor parameters
abi.decodeFunctionParams(ContractName) returns (TypeA /*a*/, TypeB /*b*/, ...);
```
Loads parameters of the function or constructor (if contract type is provided). This function is usually used in
**[onBounce](#onbounce)** function.
See example of how to use **onBounce** function:
* [onBounceHandler](https://github.com/everx-labs/samples/blob/master/solidity/16_onBounceHandler.sol)
##### abi.codeSalt()
```TVMSolidity
abi.codeSalt(TvmCell code) returns (optional(TvmCell) optSalt);
```
If **code** contains salt, then **optSalt** contains one. Otherwise, **optSalt** doesn't contain any value.
##### abi.setCodeSalt()
```TVMSolidity
abi.setCodeSalt(TvmCell code, TvmCell salt) returns (TvmCell newCode);
```
Inserts **salt** into **code** and returns new code **newCode**.
##### abi.functionId()
```TVMSolidity
// id of public function
abi.functionId(functionName) returns (uint32);
// id of public constructor
abi.functionId(ContractName) returns (uint32);
```
Returns the function id (uint32) of a public/external function or constructor.
Example:
```TVMSolidity
contract MyContract {
constructor(uint a) public {
}
/*...*/
}
function f() public pure returns (uint) {
/*...*/
}
function getConstructorID() public pure returns (uint32) {
uint32 functionId = abi.functionId(MyContract);
return functionId;
}
function getFuncID() public pure returns (uint32) {
uint32 functionId = abi.functionId(f);
return functionId;
}
}
```
See example of how to use this function:
* [onBounceHandler](https://github.com/everx-labs/samples/blob/master/solidity/16_onBounceHandler.sol)
##### abi.encodeIntMsg()
```TVMSolidity
abi.encodeIntMsg({
dest: address,
value: uint128,
call: {function, [callbackFunction,] arg0, arg1, arg2, ...},
bounce: bool,
currencies: mapping(uint32 => varuint32),
stateInit: TvmCell
})
returns (TvmCell);
```
Generates an internal outbound message that contains a function call. The result `TvmCell` can be used to send a
message using [tvm.sendrawmsg()](#tvmsendrawmsg). If the `function` is `responsible`, then
`callbackFunction` parameter must be set.
`dest`, `value` and `call` parameters are mandatory. Another parameters can be omitted. See
[\<address\>.transfer()](#addresstransfer) where these options and their default values are
described.
See also:
* sample [22_sender.sol](https://github.com/everx-labs/samples/blob/master/solidity/22_sender.sol)
* [abi.encodeBody()](#abiencodebody)
### **gosh** namespace
All `gosh.*` functions are experimental features and are available only in certain blockchain
networks in which `CapDiff` [capability](#tvm-capabilities) is set.
#### gosh.diff and gosh.zipDiff
```TVMSolidity
(1)
gosh.diff(string oldText, string newText) returns (string patch)
(2)
gosh.zipDiff(bytes oldText, bytes newText) returns (bytes patch)
```
(1) Calculates [patch](https://en.wikipedia.org/wiki/Diff) between `oldText` and `newText`.
(2) It's the same as `gosh.diff` but it calculates `patch` between compressed strings.
```TVMSolidity
string oldText = ...;
string newText = ...;
string patch = gosh.diff(oldText, newText);
```
#### gosh.applyPatch, gosh.applyPatchQ, gosh.applyZipPatch, gosh.applyZipPatchQ, gosh.applyZipBinPatch and gosh.applyZipBinPatchQ
```TVMSolidity
(1)
gosh.applyPatch(string oldText, string patch) returns (string newText)
gosh.applyPatchQ(string oldText, string patch) returns (optional(string) newText)
(2)
gosh.applyBinPatch(bytes oldText, bytes patch) returns (bytes newText)
gosh.applyBinPatchQ(bytes oldText, bytes patch) returns (optional(bytes) newText)
(3)
gosh.applyZipPatch(bytes oldText, bytes patch) returns (bytes newText)
gosh.applyZipPatchQ(bytes oldText, bytes patch) returns (optional(bytes) newText)
(4)
gosh.applyZipBinPatch(bytes oldText, bytes patch) returns (bytes newText)
gosh.applyZipBinPatchQ(bytes oldText, bytes patch) returns (optional(bytes) newText)
```
(1) Applies `patch` to the `oldText`. If it's impossible (bad patch), `gosh.applyPatch` throws an exception with type check
error code (-8) but`gosh.applyPatchQ` returns `null`.
(2) These are the same as `gosh.applyPatch`/`gosh.applyPatchQ` but these functions are applied to binary arrays.
(3) These are the same as `gosh.applyPatch`/`gosh.applyPatchQ` but these functions are applied to compressed strings.
(4) These are the same as `gosh.applyPatch`/`gosh.applyPatchQ` but these functions are applied to compressed binary arrays.
```TVMSolidity
string oldText = ...;
string patch = ...;
string newText = gosh.applyPatch(oldText, patch);
```
#### gosh.zip and gosh.unzip
```TVMSolidity
gosh.zip(string text) returns (bytes zip)
gosh.unzip(bytes zip) returns (optional(string) text)
```
`gosh.zip` converts the `text` to compressed `bytes`. `gosh.unzip` reverts such compression.
#### gosh.mintshell and gosh.mintshellq
```TVMSolidity
gosh.mintshell(uint64)
gosh.mintshellq(uint64)
```
`gosh.mintshell` ints vmshell tokens from the dApp configuration.
Succeeds if dApp config balance ≥ amount and mint rest of config balance in quiet version
```TVMSolidity
gosh.mintshell(1_000_000); // Mint 1M nanovmshell
```
#### gosh.sendtodappconfig
```TVMSolidity
gosh.sendtodappconfig(uint64)
```
`gosh.sendtodappconfig` deposits vmshell to dApp configuration.
```TVMSolidity
gosh.sendtodappconfig(1_000_000); // Deposit 1M nanovmshell
```
#### gosh.getavailablebalance
```TVMSolidity
gosh.getavailablebalance() returns (uint128)
```
`gosh.getavailablebalance` gets available vmshell balance in dApp config.
```TVMSolidity
gosh.getavailablebalance();
```
#### gosh.burnecc
```TVMSolidity
gosh.burnecc(uint64 amount, uint32 currency_id)
```
`gosh.burnecc` burns ECC tokens. If amount == 0, burn all ecc balance with this currency_id.
```TVMSolidity
gosh.burnecc(100, 2); // Burn 100 ecc-shell tokens
```
#### gosh.cnvrtshellq
```TVMSolidity
gosh.cnvrtshellq(uint64 amount)
```
`gosh.cnvrtshellq` converts ECC (currency_id=2) to vmshell. If balance of ECC <= amount, instruction convert all balance.
```TVMSolidity
gosh.cnvrtshellq(300); // Convert 300 ecc-shell tokens
```
#### gosh.mintecc
```TVMSolidity
gosh.mintecc(uint64 amount, uint32 currency_id)
```
`gosh.mintecc` mints ECC tokens (special contracts only).
```TVMSolidity
gosh.mintecc(300, 2); // Mint 300 ecc-shell tokens
```
#### Exponentiation
Exponentiation `**` is only available for unsigned types in the exponent. The resulting type of an
exponentiation is always equal to the type of the base. Please take care that it is large enough to
hold the result and prepare for potential assertion failures or wrapping behaviour.
Note that `0**0` throws an exception.
Example:
```TVMSolidity
uint b = 3;
uint32 p = 4;
uint res = b ** p; // res == 81
```
#### selfdestruct
```TVMSolidity
selfdestruct(address dest_addr);
```
Creates and sends the message that carries all the remaining balance
of the current smart contract and destroys the current account.
See example of how to use the `selfdestruct` function:
* [Kamikaze](https://github.com/everx-labs/samples/blob/master/solidity/8_Kamikaze.sol)
#### sha256
```TVMSolidity
(1)
sha256(TvmSlice slice) returns (uint256)
(2)
sha256(bytes b) returns (uint256)
(3)
sha256(string str) returns (uint256)
```
1. Computes the SHA-256 hash. If the bit-length of `slice` is not divisible by eight, throws a cell
underflow [exception](#tvm-exception-codes). References of `slice` are not used to compute the hash. Only data bits located
in the root cell of `slice` are used.
2. Computes the SHA-256 hash only for the first 127 bytes. If `bytes.length > 127`, then `b[128],
b[129], b[130] ...` elements are ignored.
3. Same as for `bytes`: only the first 127 bytes are taken into account.
See also [tvm.hash()](#tvmhash) to compute representation hash of the whole tree of cells.
#### gasToValue
```TVMSolidity
gasToValue(uint128 gas) returns (uint128 value)
gasToValue(uint128 gas, int8 wid) returns (uint128 value)
```
Returns worth of **gas** in workchain **wid**.
Throws an exception if **wid** is not equal to `0` or `-1`.
If `wid` is omitted than used the contract's `wid`.
#### valueToGas
```TVMSolidity
valueToGas(uint128 value) returns (uint128 gas)
valueToGas(uint128 value, int8 wid) returns (uint128 gas)
```
Counts how much **gas** could be bought on **value** nanoevers in workchain **wid**.
Throws an exception if **wid** is not equal to `0` or `-1`.
If `wid` is omitted than used the contract's `wid`.
#### gasleft
```TVMSolidity
gasleft() returns (uint64)
```
[Capabilities](#tvm-capabilities) required: `CapsTvmBugfixes2022`.
Returns the remaining gas.
### TVM capabilities
Rust implementation of TVM has capabilities. Capabilities are flags that can be set to turn on
some features or behavior of TVM. Full list of capabilities can be found in `enum GlobalCapabilities` in [ever-block](https://github.com/everx-labs/ever-block/blob/master/src/config_params.rs) repo.
Set capabilities store in 8th parameter of the global config of the blockchain. To get it you can use command:
```bash
ever-cli --json getconfig 8
```
### TVM exception codes
| Name | Code | Definition |
|-------------------|:----:|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| Stack underflow | 2 | Not enough arguments in the stack for a primitive |
| Stack overflow | 3 | More values have been stored on a stack than allowed by this version of TVM |
| Integer overflow | 4 | Integer does not fit into expected range (by default −2<sup>256</sup> ≤ x < 2<sup>256</sup>), or a division by zero has occurred |
| Range check error | 5 | Integer out of expected range |
| Invalid opcode | 6 | Instruction or its immediate arguments cannot be decoded |
| Type check error | 7 | An argument to a primitive is of incorrect value type |
| Cell overflow | 8 | Error in one of the serialization primitives |
| Cell underflow | 9 | Deserialization error |
| Dictionary error | 10 | Error while deserializing a dictionary object |
| Unknown error | 11 | Unknown error, may be thrown by user programs |
| Fatal error | 12 | Thrown by TVM in situations deemed impossible |
| Out of gas | -14 | Thrown by TVM when the remaining gas (g<sub>r</sub>) becomes negative. This exception cannot be caught and leads to an immediate termination of TVM |
See also: [TVM][1] - 4.5.7
### Solidity runtime errors
Smart-contract written in TVM Solidity can throw runtime errors while execution.
Solidity runtime error codes:
* **40** - External inbound message has an invalid signature. See [tvm.pubkey()](#tvmpubkey) and [msg.pubkey()](#msgpubkey).
* **50** - Array index or index of [\<mapping\>.at()](#mappingat) is out of range.
* **51** - Contract's constructor has already been called.
* **52** - Replay protection exception. See `timestamp` in [pragma AbiHeader](#pragma-abiheader).
* **54** - `<array>.pop` call for an empty array.
* **57** - External inbound message is expired. See `expire` in [pragma AbiHeader](#pragma-abiheader).
* **58** - External inbound message has no signature but has public key. See `pubkey` in [pragma AbiHeader](#pragma-abiheader).
* **60** - Inbound message has wrong function id. In the contract there are no functions with such function id and there is no fallback function that could handle the message. See [fallback](#fallback).
* **61** - Deploying `StateInit` has no public key in `data` field.
* **62** - Reserved for internal usage.
* **63** - See [\<optional(T)\>.get()](#optionaltget).
* **67** - See [gasToValue](#gastovalue) and [valueToGas](#valuetogas).
* **68** - There is no config parameter 20 or 21.
* **69** - Zero to the power of zero calculation (`0**0` in TVM Solidity style or `0^0`).
* **70** - `string` method `substr` was called with substr longer than the whole string.
* **71** - Function marked by `externalMsg` was called by internal message.
* **72** - Function marked by `internalMsg` was called by external message.
* **76** - Public function was called before constructor.
* **77** - It's impossible to convert `variant` type to target type. See [variant.toUint()](#varianttouint).
* **78** - There's no private function with the function id.
* **79** - You are deploying contract that uses [pragma upgrade func/oldsol](#pragma-upgrade-funcoldsol). Use the
* **80** - See [\<T\>.get()](#tget).
### Division and rounding
Let consider we have `x` and `y` and we want to divide `x` by `y`. Compute the quotient `q` and the
remainder `r` of the division of `x` by `y`: `x = y*q + r` where `|r| < |y|`.
In TVM there are 3 options of rounding:
* **floor** - quotient `q` is rounded to −∞. `q = ⌊x/y⌋`, `r` has the same sign as `y`. This
rounding option is used for operator `/`.
Example:
```TVMSolidity
int res = int(-2) / 3; // res == -1
int res = int(-5) / 10; // res == -1
int res = int(5) / 10; // res == 0
int res = int(15) / 10; // res == 1
```
* **ceiling** - quotient `q` is rounded to +∞. `q = ⌈x/y⌉`, `r` and `y` have opposite signs.
Example:
```TVMSolidity
int res = math.divc(-2, 3); // res == 0
int res = math.divc(-5, 10); // res == 0
int res = math.divc(5, 10); // res == 1
int res = math.divc(15, 10); // res == 2
```
* **nearest** - quotient `q` is rounded to the nearest number. `q = ⌊x/y + 1/2⌋` and `|r| ≤ |y|/2`.
Example:
```TVMSolidity
int res = math.divr(-2, 3); // res == -1
int res = math.divr(-5, 10); // res == 0
int res = math.divr(5, 10); // res == 1
int res = math.divr(15, 10); // res == 2
```
### Contract execution
Before executing any contract function special code is executed. In `*.code` file there are two special
functions: `main_internal` and `main_external` that run on internal and external messages
respectively. These functions initialize some internal global variables and call contract
function of special function like `receive`, `fallback`, `onBounce`, `onTickTock`, etc.
Before calling contract's function `main_external` does:
1. Checks the message signature. Let's consider how the signature is checked:
- If signature exists and `pubkey` header isn't defined, then `tvm.pubkey()` is used
for checking.
- If signature isn't exists and `pubkey` header isn't defined, then signature isn't checked.
- If signature exists, `pubkey` header is defined and `pubkey` isn't exists in the
message, then `tvm.pubkey()` is used for checking.
- If signature exists, `pubkey` header is defined and `pubkey` exists in the
message, then `msg.pubkey()` is used for checking.
- If signature isn't exists, `pubkey` header is defined and `pubkey` exists in the
message, then an [exception with code 58](#solidity-runtime-errors) is thrown.
2. Replay protection:
- [*time* header](#pragma-abiheader) exists (`pragma AbiHeader notime` is not used), then the contract checks whether
`oldTime` < `time` < `now * 1000 + 30 minutes`. If it's true, then `oldTime` is updated by new `time`.
Otherwise, an exception is thrown.
- there is `afterSignatureCheck` (despite usage of `time`), then make your own replay protection.
3. Message expiration:
- `expire` exists and there is no `afterSignatureCheck`, then the contract checks whether
`expire` > `now`.
- there is `afterSignatureCheck` (despite usage of `expire`), then make your own check.
See also: [pragma AbiHeader](#pragma-abiheader), [afterSignatureCheck](#aftersignaturecheck).
### Gas optimization hints
Try to reduce count of `[]` operations for mappings and arrays. For example:
```TVMSolidity
Struct Point {
uint x;
uint y;
uint z;
}
Point[] points;
```
Here we have 3 `[]` operations:
```TVMSolidity
points[0].x = 5;
points[0].y = 10;
points[0].z = -5;
```
We can use a temp variable:
```TVMSolidity
Point p = points[0];
p.x = 5;
p.y = 10;
p.z = -5;
points[0] = p;
```
[1]: https://test.ton.org/tvm.pdf "TVM"
[2]: https://test.ton.org/tblkch.pdf "TBLKCH"
[3]: https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb "TL-B scheme"