Use this file to discover all available pages before exploring further.
It is often useful to derive an address of an account to interact with it, either on-chain or off-chain. The general algorithm for address derivation is to compose the StateInit of an account, calculate its hash, and build the address in the desired format.The StateInit is distinct from the account’s current state. It is the initial state, which an account stores at deployment. After that, state can be changed by the smart contract itself — for example, by updating the data. Since the address depends on StateInit, to derive the address it is necessary to compose the initial state rather than the current one. In practice, address derivation is mostly about composing the correct StateInit.
If it’s known how to compose the contract’s initial code and data, it’s enough to follow the general algorithm mentioned above as is. Code and data form a StateInit, and the workchain is usually hardcoded. Below is one of the most common patterns when code is a constant cell known in advance and data is composed at runtime.
Tolk
// Compose an address builderfun calculateAddress( code: cell, data: cell, workchain: int): builder { val addr = AutoDeployAddress { workchain, stateInit: ContractState { code, data } }; return addr.buildAddress();}// Placeholder for the code cell encoded as a bag of cellsfun getCode(): cell asm "B{b5ee9c724101010100020000004cacb9cd} B>boc PUSHREF";// Placeholder for data that is usually assembled at runtimefun getData(): cell { return beginCell() .storeUint(123, 123) .storeSlice("hello, world") .endCell();}fun main() { val code = getCode(); val data = getData(); val workchain = BASECHAIN; val builderWithAddress = calculateAddress(code, data, workchain); // Example usage if the derived address has to be written in another cell. val exampleCell = beginCell() .storeBuilder(builderWithAddress) .endCell(); debug.print(exampleCell);}
The b5ee9c724101010100020000004cacb9cd in the getCode function is a placeholder for a hardcoded code cell in BoC format known at compile-time. The getData function is a placeholder for building a data cell, and the actual implementation depends on the storage layout of the target smart contract. Usually, data is composed in a parametrized way, but this does not alter the rest of the logic — only the getData function.The calculateAddress function uses the AutoDeployAddress built-in that handles all the underlying StateInit and address composing logic. In the Tolk stdlib, the code and data pair is represented by ContractState. The buildAddress method returns a builder containing the resulting address, which can be cheaply stored in another builder — the most common use case.
When working with the contract sharding pattern, child contracts usually have a StateInit that depends on the parent. In the example below, the dependence is implemented by adding the parent address to the child StateInit. The same logic from the simple on-chain case works here, and only getData has to be changed.
Tolk
// Compose an address builder using the AutoDeployAddress built-in.fun calculateAddress(code: cell, data: cell, workchain: int): builder { val addr = AutoDeployAddress { workchain, stateInit: ContractState { code, data } }; return addr.buildAddress();}// Placeholder for the code cell encoded as a BoC.fun getCode(): cell asm "B{b5ee9c724101010100020000004cacb9cd} B>boc PUSHREF";// Placeholder for child data that depends on the parent address.fun getChildData(parentAddress: address): cell { return beginCell() .storeSlice("hello, world") .storeAddress(parentAddress) .endCell();}fun main() { val code = getCode(); val parentAddress = contract.getAddress(); val data = getChildData(parentAddress); val workchain = BASECHAIN; val builderWithAddress = calculateAddress(code, data, workchain); // Example usage if the derived address has to be written in another cell. val exampleCell = beginCell() .storeBuilder(builderWithAddress) .endCell(); debug.print(exampleCell);}
Child contracts also often have some kind of index or additional data that they depend on, but it is case-specific and up to the implementation. The common pattern is to include at least the parent address in StateInit.
A vanity contract allows customizing the address of a smart contract that is being deployed. It does that by making its own StateInit depend on some salt that is randomly generated many times until a desired address is found.In this case, there is no real correlation between the data the contract holds and its final address. So there is no way to actually derive the address. The only option left is to define a constant with the actual address that is obtained in advance.
Tolk
// Constant address in raw format.const VANITY_ADDRESS_RAW: address = address("0:4de24b95c1c3c9b6a94231460716192c7d2b4e444ca6ae9a98bc5c4b3fcdef3f");// Constant address in user-friendly format.const VANITY_ADDRESS_USER_FRIENDLY: address = address("EQBN4kuVwcPJtqlCMUYHFhksfStOREymrpqYvFxLP83vP-Ci");fun main() { debug.print(VANITY_ADDRESS_RAW); debug.print(VANITY_ADDRESS_USER_FRIENDLY);}
The toShard field in AutoDeployAddress allows smart contracts to have a specific prefix in the address for the purpose of deploying it to a certain shardchain. This can be useful for cross-contract latency optimization, as in Jetton 2.0.This may seem similar to the vanity case, but it serves a different purpose. A vanity generator finds such a StateInit that an address composed from its hash will have certain letters in a prefix or suffix. The toShard does not alter the whole address and only tells the blockchain to replace the first few bits of the address to which the contract is being deployed. This optimization is used in Jetton 2.0.The logic here is more similar to the simple case. The only difference is the additional toShard field.
Tolk
// Compose an address builder using the AutoDeployAddress built-in.fun deriveAddress(target: address, prefixLength: int): builder { val code = getCode(); val data = getData(); val workchain = BASECHAIN; val addr = AutoDeployAddress { workchain, stateInit: ContractState { code, data }, toShard: { fixedPrefixLength: prefixLength, closeTo: target } }; return addr.buildAddress();}// Placeholder for the code cell encoded as a BoC.fun getCode(): cell asm "B{b5ee9c724101010100020000004cacb9cd} B>boc PUSHREF";// Placeholder for data cell composition.fun getData(): cell { return beginCell().endCell();}fun main() { // Using a constant as a target. val constTarget: address = address("0:AA00000000000000000000000000000000000000000000000000000000000000"); val constBuilder = deriveAddress(constTarget, 8); // Example usage if the derived address has to be written in another cell. val constCell = beginCell() .storeBuilder(constBuilder) .endCell(); debug.print(constCell); // Using contract's own address as a target. val runtimeTarget = contract.getAddress(); val runtimeBuilder = deriveAddress(runtimeTarget, 8); // Example usage if the derived address has to be written in another cell. val runtimeCell = beginCell() .storeBuilder(runtimeBuilder) .endCell(); debug.print(runtimeCell);}
The logic mirrors the on-chain example. The @ton/core library has the contractAddress function that handles StateInit hash calculation and composes the address.
import { contractAddress, Cell, beginCell } from "@ton/core";// constant code from a BoCconst code = Cell.fromBoc( Buffer.from("b5ee9c724101010100020000004cacb9cd", "hex"),)[0];// data composing exampleconst data = beginCell() .storeUint(123, 123) .storeStringTail("hello, world!") .endCell();const init = { code, data,};const addr = contractAddress(0, init);console.log(addr); // EQC235M1tplyIg2OUQZQgG8D3BNF6_TZJ1932iaIV26XBVCH