Address
Every smart contract has an address used for all on-chain interactions.
Tolk provides the following types for working with addresses:
address— a standard address; also called "internal address".address?— nullable address, i.e., either a standard address ornull; also called "internal or none".any_address— any kind of address, including external addresses.
Components
A standard, internal address consists of:
- a
int8workchain — currently, there are only two: masterchain (-1) and basechain (0); - a
uint256hash — a 256-bit account ID.
address has methods to retrieve these components:
fun checkAddress(addr: address, expectHash: uint256) {
val (wc, hash) = addr.getWorkchainAndHash();
assert (wc == 0) throw 123;
assert (hash == expectHash) throw 456;
}When serialized, values of address type occupy 267 bits:
- 3 bits for the standard address prefix —
0b100 - 8-bit workchain
- 256-bit hash
During deserialization from a cell, the values of type address are automatically validated at runtime: if parsing succeeds, the resulting address is guaranteed to be valid.
Comparison
Compare addresses using == or !=. Internally, an address is represented as a raw slice without references, so == and != test for bits equality.
struct Storage {
owner: address
// ...
}
fun onInternalMessage(in: InMessage) {
var st = Storage.load();
// process a message only from owner
if (in.senderAddress == st.owner) {
// ...
}
}Embedding
Embed a constant value of type address using the address() function:
const REFUND_ADDR = address("EQCRDM9h4k3UJdOePPuyX40mCgA4vxge5Dc5vjBR8djbEKC5")Nullable address
A nullable address often represents a potentially absent value:
- There might be an
adminAddressin the contract's storage, but it may be unset. - There might be an
sendExcessesTofield in a message: if exists, send surplus there; if not, keep it.
Thus, type address? represents a "none address": either an internal address or none. Check for null before usage:
// May have no admin
fun send(adminAddress: address?) {
if (adminAddress == null) {
return;
}
// send a message to adminAddress, it's not null
}When a value of type address? is serialized and is not null, it occupies 267 as the standard address. If it is null, then it occupies only 2 zero bits, a so-called addr_none.
The "none" address can be created using createAddressNone().
Any address
All external messages from outside world to blockchain contracts, such as wallet contracts, come from external addresses.
To represent internal and external addresses, as well as nullable addresses, use any_address:
struct CrossBridgeMessage {
destination: any_address
}Casts
To manually operate on the bits of an address, cast it to a slice:
val s = someAddr as slice;
s.loadUint(3); // 0b100 — internal address tag
s.loadInt(8); // workchainSince an address is represented as a slice at the TVM level, such cast is permitted and is safe. Conversely, the cast in another direction is unsafe, because no validation is performed at runtime and any further use might fail:
var b = beginCell()
.storeUint(0b01) // addr_extern
...;
var s = b.endCell().beginParse();
return s as any_address;Last updated on