# How to use a vanity contract (https://docs.ton.org/llms/contracts/techniques/vanity/content.md)



A [vanity contract](https://github.com/ton-community/vanity-contract) allows customization of the address of a smart contract being deployed. It does this by making its own [`StateInit`](https://docs.ton.org/llms/foundations/messages/deploy/content.md) depend on constant data that is randomly generated many times until a desired address is found. It is often used to deploy contracts with a specific prefix or suffix, making the address more recognizable in [explorers](https://docs.ton.org/llms/onboarding/explorers/overview/content.md).

The contract code and data are included in the vanity deploy message. The vanity contract is first deployed with a `StateInit` that produces the [desired address](https://docs.ton.org/llms/foundations/addresses/overview/content.md), and then immediately sets its actual state from the payload. This is a special case of [upgrading](https://docs.ton.org/llms/contracts/techniques/upgrades/content.md) contract's code.

## Prerequisites [#prerequisites]

* OpenCL-capable GPU
* [Python 3](https://www.python.org/downloads/)
* [`pyopencl`](https://pypi.org/project/pyopencl/)
* [Blueprint](https://docs.ton.org/llms/contracts/blueprint/overview/content.md)

## How it works [#how-it-works]

The vanity contract code:

```tolk title="Tolk" expandable
struct VanityStorage {
    padding: uint5
    owner: address
    salt: uint256
}

struct DeployPayload {
    code: cell
    data: cell
}

fun onInternalMessage(in: InMessage) {
    val storage = lazy VanityStorage.fromCell(contract.getData());

    // Read sender address
    val sender = in.senderAddress;

    // Allow deployment only to the owner
    assert (sender == storage.owner) throw 100;

    // Set code and data
    val payload = lazy DeployPayload.fromSlice(in.body);
    contract.setCodePostponed(payload.code);
    contract.setData(payload.data);
}
```

It loads the owner from the typed `VanityStorage`, checks whether the message comes from this owner, then loads `DeployPayload` and replaces the contract's code and data with the cells from the incoming message.

In a vanity contract, a `salt` is a 256-bit value stored in `StateInit` along with five padding bits and the owner address. The contract declares this layout in `VanityStorage`, but only the `owner` field is needed at runtime. The `salt` does not affect runtime behavior and only influences the resulting address via the `StateInit` hash.

The `owner` field is required because someone could intercept an external message, extract the `salt`, and deploy their own contract with the same `salt` concurrently. Since the `owner` value also unpredictably affects the address, the intercepted `salt` is useless unless the attacker can send the message from the same `owner` address.

Because a contract address is derived from the `StateInit` hash, changing the `salt` changes the address deterministically. The search for a suitable `salt` happens entirely off-chain: a Python script with an OpenCL kernel for speed generates many random `salt` values, computes the resulting address, and reports matches. The on-chain vanity contract does not brute-force salts; it only verifies the owner and then applies the provided code and data when deployed.

## Generate salt [#generate-salt]

To generate the `salt`, copy the code from [`src/generator`](https://github.com/ton-community/vanity-contract/tree/6baeb39500de0fee79bd241047699ca65ee71f55/src/generator) in the same [repository](https://github.com/ton-community/vanity-contract). It includes the `run.py` script and the `vanity.cl` OpenCL kernel.

Run the command with the desired search parameters, including `-w` for the [workchain](https://docs.ton.org/llms/foundations/addresses/overview/content.md) and the owner address allowed to perform the deployment. The example below searches on the basechain for the specified suffix.

```bash
python3 run.py -w 0 --end '<SUFFIX>' --case-sensitive <OWNER_ADDR>
```

Where:

* `<SUFFIX>` – desired address suffix; case sensitive when `--case-sensitive` is set.
* `<OWNER_ADDR>` – address allowed to deploy via the vanity contract.

After running, the script prints logs and starts the search, printing every found `salt`. It also writes found `salt` to the `found.txt` file. The search continues until it is stopped or exits after the first match when `--only-one` is set.

```text title="Example output"
Searching wallets case-sensitive, with "TEST" in the end
Owner:  UQCSQnz9h3iilIHMueOPs8RaryGqzb-bJpReZuZAUsm6TDRo
Flags:  1100
Kernel conditions: result[44] == 'T' && result[45] == 'E' && result[46] == 'S' && result[47] == 'T'

Using device:  Apple M2 Max
Speed: 198 Mh/s, miss: 4, found: 0
Speed: 204 Mh/s, miss: 2, found: 0
Found:  EQBas7IlwGKmd6CT7_l0PLynkUv2fmrANn2FFgcMntBATEST salt:  1045adb4ffb9af72021354a07a6f3e64ebc9822775f80b7d98beb195f57093df
Speed: 207 Mh/s, miss: 1, found: 1
Speed: 206 Mh/s, miss: 4, found: 1
Found:  EQB1p467NtIyNpwVAF0qZYDCaXzA56mk8P6nqt6QJFeQTEST salt:  fa683a39082696af7bafecaa63f6172b615f5b7d89fea24c941d52aa3310bbc3
Speed: 208 Mh/s, miss: 0, found: 2
Speed: 205 Mh/s, miss: 2, found: 2
Speed: 208 Mh/s, miss: 2, found: 2
Found:  EQBXaec9-r5Ge65hXTQopw7akH6LQr4rms9DdzkhxcUiTEST salt:  e7336b387099b3f8a31fa114ff801b799f14f3fe7f6c27c6cf0ccbb542ab743d
Speed: 206 Mh/s, miss: 2, found: 3
Speed: 203 Mh/s, miss: 2, found: 3
Speed: 203 Mh/s, miss: 3, found: 3
```

The more specific the search, the rarer the matches, and the more compute is required to find one. A 4-character match typically appears in a few seconds on a laptop. TON [user-friendly addresses](https://docs.ton.org/llms/foundations/addresses/formats/content.md) are base64, so each character encodes 6 bits; four characters correspond to 24 bits, i.e., about 1 in 2<sup>24</sup> trials on average. Once a `salt` is found, it can be used to deploy an arbitrary smart contract at that address.

## Deploy the contract [#deploy-the-contract]

Deploy of the vanity contract and the message that replaces its code and data usually come in a single [message](https://github.com/ton-blockchain/ton/blob/5c0349110bb03dd3a241689f2ab334ae1a554ffb/crypto/block/block.tlb#L155):

```text
init:
    code: vanity contract code
    data:
        owner: owner's address
        salt: generated salt
body:
    code: new contract's code
    data: new contract's data
```

This example uses [Blueprint](https://docs.ton.org/llms/contracts/blueprint/overview/content.md) to create and send this message. Define a vanity contract wrapper at `wrappers/VanityContract.ts`:

```ts title="TypeScript" expandable
import { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode } from '@ton/core';

export type VanityContractConfig = {
    owner: Address;
    salt: Buffer;
};

export function vanityContractConfigToCell(
    config: VanityContractConfig
): Cell {
    return beginCell()
        .storeUint(0, 5)
        .storeAddress(config.owner)
        .storeBuffer(config.salt, 32)
        .endCell();
}

// from https://github.com/ton-community/vanity-contract/blob/6baeb39500de0fee79bd241047699ca65ee71f55/src/contract/vanity-address.cell
const vanityCode = Cell.fromBoc(
    Buffer.from(
        'b5ee9c72010102010032000114ff00f4a413f4bcf2c80b010046d3ed44d075d721fa408307d721d102d0d30331fa403058c705f288d4d4d101fb04ed54',
        'hex',
    ),
)[0];

export class VanityContract implements Contract {
    constructor(
        readonly address: Address,
        readonly init?: { code: Cell; data: Cell },
    ) {}

    static createFromAddress(address: Address) {
        return new VanityContract(address);
    }

    static createFromConfig(
        config: VanityContractConfig,
        workchain = 0
    ) {
        const data = vanityContractConfigToCell(config);
        const init = {
            code: vanityCode,
            data,
        };
        return new VanityContract(
            contractAddress(workchain, init),
            init,
        );
    }

    async sendDeploy(
        provider: ContractProvider,
        via: Sender,
        value: bigint,
        newCode: Cell,
        newData: Cell,
    ) {
        const body = beginCell()
            .storeRef(newCode)
            .storeRef(newData)
            .endCell();
        await provider.internal(via, {
            value,
            sendMode: SendMode.PAY_GAS_SEPARATELY,
            body,
        });
    }
}
```

Create `scripts/deployExampleContract.ts`:

```ts title="TypeScript" expandable
import { toNano, Address } from '@ton/core';
import { ExampleContract } from '../wrappers/ExampleContract';
import { VanityContract } from '../wrappers/VanityContract';
import { compile, NetworkProvider } from '@ton/blueprint';

export async function run(provider: NetworkProvider) {
    const vanityContract = provider.open(
        VanityContract.createFromConfig({
            owner: Address.parse('<OWNER_ADDR>'),
            salt: Buffer.from('<SALT_HEX>', 'hex'),
        }),
    );

    const exampleContract = provider.open(
        ExampleContract.createFromConfig(
            {},
            await compile('ExampleContract'),
        ),
    );

    const init = exampleContract.init!;

    await vanityContract.sendDeploy(
        provider.sender(),
        toNano('0.01'), // attach value for deployment fees
        init.code,
        init.data,
    );

    await provider.waitForDeploy(vanityContract.address);
}
```

Where:

* `<OWNER_ADDR>` – address allowed to deploy via the vanity contract.
* `<SALT_HEX>` – 32-byte `salt` in hex found by the generator.

Run the script via `npx blueprint run`. The deployment succeeds when `<OWNER_ADDR>` matches the address of the wallet used for actual deployment. `ExampleContract` can be replaced with any contract; the vanity contract does not depend on the specifics of the code or data.
