# How to use a vanity contract (https://docs-orhepa2tm-ton-core-docs.vercel.app/llms/contract-dev/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`](/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 so the address is visible in block explorers.

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](/llms/foundations/addresses/overview/content.md), and then immediately sets its actual state from the payload. This is a special case of [upgrading](/llms/contract-dev/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](/llms/contract-dev/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](/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](/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](/llms/contract-dev/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.
