solang 0.2.1

Solang Solidity Compiler
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
Types
=====

The following primitive types are supported.

Boolean Type
____________

``bool``
  This represents a single value which can be either ``true`` or ``false``.

Integer Types
_____________

``uint``
  This represents a single unsigned integer of 256 bits wide. Values can be for example
  ``0``, ``102``, ``0xdeadcafe``, or ``1000_000_000_000_000``.

``uint64``, ``uint32``, ``uint16``, ``uint8``
  These represent shorter single unsigned integers of the given width. These widths are
  most efficient and should be used whenever possible.

``uintN``
  These represent shorter single unsigned integers of width ``N``. ``N`` can be anything
  between 8 and 256 bits and a multiple of 8, e.g. ``uint24``.

``int``
  This represents a single signed integer of 256 bits wide. Values can be for example
  ``-102``, ``0``, ``102`` or ``-0xdead_cafe``.

``int64``, ``int32``, ``int16``, ``int8``
  These represent shorter single signed integers of the given width. These widths are
  most efficient and should be used whenever possible.

``intN``
  These represent shorter single signed integers of width ``N``. ``N`` can be anything
  between 8 and 256 bits and a multiple of 8, e.g. ``int128``.

Underscores ``_`` are allowed in numbers, as long as the number does not start with
an underscore.  ``1_000`` is allowed but ``_1000`` is not. Similarly
``0xffff_0000`` is fine, but ``0x_f`` is not.

Scientific notation is supported, e.g. ``1e6`` is one million. Only integer values
are supported.

Assigning values which cannot fit into the type gives a compiler error. For example::

    uint8 foo = 300;

The largest value an ``uint8`` can hold is (2 :superscript:`8`) - 1 = 255. So, the compiler says:

.. code-block:: none

    value 300 does not fit into type uint8

.. tip::

  When using integers, whenever possible use the ``int64``, ``int32`` or ``uint64``,
  ``uint32`` types.

  The Solidity language has its origins for the Ethereum Virtual Machine (EVM), which has
  support for 256 bit arithmetic. Most common CPUs like x86_64 do not implement arithmetic
  for such large types, and any EVM virtual machine implementation has to do bigint
  calculations, which are expensive.

  WebAssembly or BPF do not support this. As a result that Solang has to emulate larger types with
  many instructions, resulting in larger contract code and higher gas cost or compute units.

Fixed Length byte arrays
________________________

Solidity has a primitive type unique to the language. It is a fixed-length byte array of 1 to 32
bytes, declared with *bytes* followed by the array length, for example:
``bytes32``, ``bytes24``, ``bytes8``, or ``bytes1``. ``byte`` is an alias for ``byte1``, so
``byte`` is an array of 1 element. The arrays can be initialized with either a hex string ``hex"414243"``,
or a text string ``"ABC"``, or a hex value ``0x414243``.

.. code-block:: solidity

  bytes4 foo = "ABCD";
  bytes4 bar = hex"41_42_43_44";

The ascii value for ``A`` is 41 in hexadecimal. So, in this case, foo and bar
are initialized to the same value. Underscores are allowed in hex strings; they exist to aid
readability. If the string is shorter than the type, it is padded with zeros. For example:

.. code-block:: solidity

  bytes6 foo = "AB" "CD";
  bytes5 bar = hex"41";

String literals can be concatenated like they can in C or C++. Here the types are longer than
the initializers; this means they are padded at the end with zeros. foo will contain the following
bytes in hexadecimal ``41 42 43 44 00 00`` and bar will be ``41 00 00 00 00``.

These types can be used with all the bitwise operators, ``~``, ``|``, ``&``, ``^``, ``<<``, and
``>>``. When these operators are used, the type behaves like an unsigned integer type. In this case
think the type not as an array but as a long number. For example, it is possible to shift by one bit:

.. code-block:: solidity

  bytes2 foo = hex"0101" << 1;
  // foo is 02 02

Since this is an array type, it is possible to read array elements too. They are indexed from zero.
It is not permitted to set array elements; the value of a bytesN type can only be changed
by setting the entire array value.

.. code-block:: solidity

  bytes6 wake_code = "heotymeo";
  bytes1 second_letter = wake_code[1]; // second_letter is "e"

The length can be read using the ``.length`` member variable. Since this is a fixed size array, this
is always the length of the type itself.

.. code-block:: solidity

  bytes32 hash;
  assert(hash.length == 32);
  byte b;
  assert(b.length == 1);

Address and Address Payable Type
________________________________

The ``address`` type holds the address of an account. The length of an ``address`` type depends on
the target being compiled for. On EVM, an address is 20 bytes. Solana and Substrate have an address
length of 32 bytes. The format of an address literal depends on what target you are building for. On EVM,
ethereum addresses can be specified with a particular hexadecimal number.

.. code-block:: solidity

  address foo = 0xE9430d8C01C4E4Bb33E44fd7748942085D82fC91;

The hexadecimal string should be 40 hexadecimal characters, and not contain any underscores.
The capitalization, i.e. whether ``a`` to ``f`` values are capitalized, is important.
It is defined in
`EIP-55 <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md>`_. For example,
when compiling:

.. code-block:: solidity

  address foo = 0xe9430d8C01C4E4Bb33E44fd7748942085D82fC91;

Since the hexadecimal string is 40 characters without underscores, and the string does
not match the EIP-55 encoding, the compiler will refused to compile this. To make this
a regular hexadecimal number, not an address literal, add some leading zeros or some underscores.
In order to fix the address literal, copy the address literal from the compiler error message:

.. code-block:: none

  error: address literal has incorrect checksum, expected ‘0xE9430d8C01C4E4Bb33E44fd7748942085D82fC91’

Substrate or Solana addresses are base58 encoded, not hexadecimal. An address literal can be specified with
the special syntax ``address"<account>"``.

.. code-block:: solidity

    address foo = address"5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sjeZ";

An address can be payable or not. An payable address can used with the
:ref:`.send() and .transfer() functions <send_transfer>`, and
:ref:`selfdestruct` function. A non-payable address or contract can be cast to an ``address payable``
using the ``payable()`` cast, like so:

.. code-block:: solidity

    address payable addr = payable(this);

``address`` cannot be used in any arithmetic or bitwise operations. However, it can be cast to and from
bytes types and integer types. The ``==`` and ``!=`` operators work for comparing two address types.

.. code-block:: solidity

  address foo = address(0);

.. note::
    The type name ``address payable`` cannot be used as a cast in the Ethereum Foundation Solidity compiler,
    and the cast should be declared ``payable`` instead. This is
    `apparently due to a limitation in their parser <https://github.com/ethereum/solidity/pull/4926#discussion_r216586365>`_.
    Solang's generated parser has no such limitation and allows ``address payable`` to be used as a cast,
    but allows ``payable`` to be used as a cast well, for compatibility reasons.

.. note::

    Substrate can be compiled with a different type for Address. If your substrate has a different
    length for address, you can specify ``--address-length`` on the command line.

Enums
_____

Solidity enums types need to have a definition which lists the possible values it can hold. An enum
has a type name, and a list of unique values. Enum types can used in public functions, but the value
is represented as a ``uint8`` in the ABI. Enum are limited to 256 values.

.. include:: ../examples/enum_type.sol
  :code: solidity

An enum can be converted to and from integer, but this requires an explicit cast. The value of an enum
is numbered from 0, like in C and Rust.

If enum is declared in another contract, the type can be refered to with `contractname.typename`. The
individual enum values are `contractname.typename.value`. The enum declaration does not have to appear
in a contract, in which case it can be used without the contract name prefix.

.. include:: ../examples/enum_type_external.sol
  :code: solidity

Struct Type
___________

A struct is composite type of several other types. This is used to group related items together.

.. include:: ../examples/struct_type.sol
  :code: solidity

A struct has one or more fields, each with a unique name. Structs can be function arguments and return
values. Structs can contain other structs. There is a struct literal syntax to create a struct with
all the fields set.

.. include:: ../examples/struct_type_arguments.sol
  :code: solidity

The two contract storage variables ``card1`` and ``card2`` have initializers using struct literals. Struct
literals can either set fields by their position, or field name. In either syntax, all the fields must
be specified. When specifying structs fields by position, the order of the fields must match with the
struct definition. When fields are specified by name, the order is not important.

Struct definitions from other contracts can be used, by referring to them with the `contractname.`
prefix. Struct definitions can appear outside of contract definitions, in which case they can be used
in any contract without the prefix.

.. include:: ../examples/struct_type_arguments_external.sol
  :code: solidity

The `users` struct contains an array of `user`, which is another struct. The `users` struct is
defined in contract `db`, and can be used in another contract with the type name `db.users`.
Notice that the `db.users` struct type is used in the function `authenticate` before it is declared. In Solidity,
types can be always be used before their declaration, or even before the ``import`` directive.

Structs can be contract storage variables. Structs in contract storage can be assigned to structs
in memory and vice versa, like in the *set_card1()* function. Copying structs between storage
and memory is expensive; code has to be generated and executed for each field. In the *set_card1* function,
the following is done:

- The function argument ``c`` has to ABI decoded (1 copy + decoding overhead)
- The ``card1`` has to load from contract storage (1 copy + contract storage overhead)
- The ``c`` has to be stored into contract storage (1 copy + contract storage overhead)
- The ``previous`` struct has to ABI encoded (1 copy + encoding overhead)

Note that struct variables are references. When contract struct variables or normal struct variables
are passed around, just the memory address or storage slot is passed around internally. This makes
it very cheap, but it does mean that if a called function modifies the struct, then this is
visible in the caller as well.

.. include:: ../examples/struct_type_variable_references.sol
  :code: solidity

Fixed Length Arrays
___________________

Arrays can be declared by adding [length] to the type name, where length is a
constant expression. Any type can be made into an array, including arrays themselves (also
known as arrays of arrays). For example:

.. include:: ../examples/array_type_fixed_length.sol
  :code: solidity

Note the length of the array can be read with the ``.length`` member. The length is readonly.
Arrays can be initialized with an array literal. For example:

.. include:: ../examples/array_type_initialized.sol
  :code: solidity

Any array subscript which is out of bounds (either an negative array index, or an index past the
last element) will cause a runtime exception. In this example, calling ``primenumber(10)`` will
fail; the first prime number is indexed by 0, and the last by 9.

Arrays are passed by reference. If you modify the array in another function, those changes will
be reflected in the current function. For example:

.. include:: ../examples/array_type_references.sol
  :code: solidity

On Solang, it is not necessary to cast the first element of the array literal.

.. note::

  In Solidity, an fixed array of 32 bytes (or smaller) can be declared as ``bytes32`` or
  ``uint8[32]``. In the Ethereum ABI encoding, an ``int8[32]`` is encoded using
  32 × 32 = 1024 bytes. This is because the Ethereum ABI encoding pads each primitive to
  32 bytes. However, since ``bytes32`` is a primitive in itself, this will only be 32
  bytes when ABI encoded.

  On Substrate, the `SCALE <https://docs.substrate.io/reference/scale-codec/>`_
  encoding uses 32 bytes for both types. Similarly, the `borsh encoding <https://borsh.io/>`_
  used on Solana uses 32 bytes for both types.

Dynamic Length Arrays
_____________________

Dynamic length arrays are useful for when you do not know in advance how long your arrays
will need to be. They are declared by adding ``[]`` to your type. How they can be used depends
on whether they are contract storage variables or stored in memory.

Memory dynamic arrays must be allocated with ``new`` before they can be used. The ``new``
expression requires a single unsigned integer argument. The length can be read using
``length`` member variable.

.. include:: ../examples/array_type_dynamic.sol
  :code: solidity

.. note::

    There is experimental support for `push()` and `pop()` on memory arrays.

Storage dynamic memory arrays do not have to be allocated. By default, they have a
length of zero and elements can be added and removed using the ``push()`` and ``pop()``
methods.

.. include:: ../examples/array_type_dynamic_storage.sol
  :code: solidity

Calling the method ``pop()`` on an empty array is an error and contract execution will abort,
just like when accessing an element beyond the end of an array.

``push()`` without any arguments returns a storage reference. This is only available for types
that support storage references (see below).

.. include:: ../examples/array_type_dynamic_push.sol
  :code: solidity

Depending on the array element, ``pop()`` can be costly. It has to first copy the element to
memory, and then clear storage.

String
______

Strings can be initialized with a string literal or a hex literal. Strings can be concatenated and
compared, and formatted using `.format()`; no other operations are allowed on strings.

.. include:: ../examples/string_type.sol
  :code: solidity

Strings can be cast to `bytes`. This cast has no runtime cost, since both types use
the same underlying data structure.

.. note::

    The Ethereum Foundation Solidity compiler does not allow unicode characters in string literals,
    unless it is prefixed with unicode, e.g. ``unicode"€"`` . For compatibility, Solang also
    accepts the unicode prefix. Solang always allows unicode characters in strings.

Dynamic Length Bytes
____________________

The ``bytes`` datatype is a dynamic length array of bytes. It can be created with
the ``new`` operator, or from an string or hex initializer. Unlike the ``string`` type,
it is possible to index the ``bytes`` datatype like an array.

.. include:: ../examples/dynamic_bytes_type.sol
  :code: solidity

If the ``bytes`` variable is a storage variable, there is a ``push()`` and ``pop()``
method available to add and remove bytes from the array. Array elements in a
memory ``bytes`` can be modified, but no elements can be removed or added, in other
words, ``push()`` and ``pop()`` are not available when ``bytes`` is stored in memory.

A ``string`` type can be cast to ``bytes``. This way, the string can be modified or
characters can be read. Note this will access the string by byte, not character, so
any non-ascii characters will need special handling.

An dynamic array of bytes can use the type ``bytes`` or ``byte[]``. The latter
stores each byte in an individual storage slot, while the former stores the
entire string in a single storage slot, when possible. Additionally a ``string``
can be cast to ``bytes`` but not to ``byte[]``.

Mappings
________

Mappings are a dictionary type, or associative arrays. Mappings have a number of
limitations:

- They only work as storage variables
- They are not iterable
- The key cannot be a ``struct``, array, or another mapping.

Mappings are declared with ``mapping(keytype => valuetype)``, for example:

.. include:: ../examples/mapping_type.sol
  :code: solidity

.. tip::

  When assigning multiple members in a struct in a mapping, it is better to create
  a storage variable as a reference to the struct, and then assign to the reference.
  The ``add()`` function above can be optimized like the following.

  .. code-block:: solidity

    function add(string name, address addr) public {
        // assigning to a storage variable creates a reference
        user storage s = users[name];

        s.exists = true;
        s.addr = addr;
    }

  Here the storage slot for the struct is calculated only once, avoiding another expensive
  keccak256 calculation.

If you access a non-existing field on a mapping, all the fields will read as zero. It
is common practise to have a boolean field called ``exists``. Since mappings are not iterable,
it is not possible to ``delete`` an entire mapping itself, but individual mapping entries can be deleted.

.. note::

  Solidity on Ethereum and on Substrate takes the keccak 256 hash of the key and the storage slot, and simply uses that
  to find the entry. Its underlying hash table does not use separate chaining for collision resolution.
  The scheme is simple and avoids `"hash flooding" <https://en.wikipedia.org/wiki/Collision_attack#Hash_flooding>`_
  attacks that utilize hash collisions to exploit the worst-case time complexity for a separately chained
  hash table. When too many collisions exist in a such a data structure,
  it degenerates to a linked list, whose time complexity for searches is O(n).

  In order to implement mappings on Solana's storage, a new scheme must be found to prevent this
  attack. `SipHash <https://en.wikipedia.org/wiki/SipHash>`_ is a hash algorithm that solves the problem,
  but it cannot be used in smart contracts since there is no place to store secrets. Separate
  chaining for collision handling is needed since Solana accounts have a much smaller address
  space than the 256 bit storage slots. Any suggestions for solving this are very welcome!

  SipHash may serve as a way to implement mappings in memory, which would allow them to be local variables in
  functions. Although the Substrate environment provides a function to generate random numbers to serve
  as the hashes' secret, on Solana a safe alternative still needs to be found.

Contract Types
______________

In Solidity, other smart contracts can be called and created. So, there is a type to hold the
address of a contract. This is in fact simply the address of the contract, with some syntax
sugar for calling functions on it.

A contract can be created with the new statement, followed by the name of the contract. The
arguments to the constructor must be provided.

.. include:: ../examples/substrate/contract_type.sol
  :code: solidity

Since child does not have a constructor, no arguments are needed for the new statement. The variable
`c` of the contract `child` type, which simply holds its address. Functions can be called on
this type. The contract type can be cast to and from address, provided an explicit cast is used.

The expression ``this`` evaluates to the current contract, which can be cast to ``address`` or
``address payable``.

.. include:: ../examples/contract_type_cast_address.sol
  :code: solidity

Function Types
______________

Function types are references to functions. You can use function types to pass functions
for callbacks, for example. Function types come in two flavours, ``internal`` and ``external``.
An internal function is a reference to a function in the same contract or one of its base contracts.
An external function is a reference to a public or external function on any contract.

When declaring a function type, you must specify the parameters types, return types, mutability,
and whether it is external or internal. The parameters or return types cannot have names.

.. include:: ../examples/function_type.sol
  :code: solidity

If the ``internal`` or ``external`` keyword is omitted, the type defaults to internal.

Just like any other type, a function type can be a function argument, function return type, or a
contract storage variable. Internal function types cannot be used in public functions parameters or
return types.

An external function type is a reference to a function in a particular contract. It stores the address of
the contract, and the function selector. An internal function type only stores the function reference. When
assigning a value to an external function selector, the contract and function must be specified, by using
a function on particular contract instance.

.. include:: ../examples/function_type_callback.sol
  :code: solidity

Storage References
__________________

Parameters, return types, and variables can be declared storage references by adding
``storage`` after the type name. This means that the variable holds a references to a
particular contract storage variable.

.. include:: ../examples/storage_ref_type.sol
  :code: solidity

Functions which have either storage parameter or return types cannot be public; when a function
is called via the ABI encoder/decoder, it is not possible to pass references, just values.
However it is possible to use storage reference variables in public functions, as
demonstrated in function all_pumas().

User Defined Types
__________________

A user defined type is a new type which simply wraps an existing primitive type. First, a new type
is declared with the ``type`` syntax. The name of the type can now be used anywhere where a type
is used, for example in function arguments or return values.

.. include:: ../examples/user_defined_type.sol
  :code: solidity

Note that the wrapped value ``Value v`` cannot be used in any type of arithmetic or comparision. It needs to
be unwrapped before it can be used.