Diagnosing a TON deployment address mismatch from StateInit

A deployment script predicts one address while the signer builds a message for another. Even a small change to the serialized initial data can explain the mismatch before a transaction is sent.

Hold code and workchain fixed

This local @ton/core example uses an empty code cell to isolate address derivation. The two results differ because a 32-bit field in the data cell changed. The fixture illustrates serialization only and does not implement an executable contract.

import { beginCell, contractAddress } from "@ton/core";
const code = beginCell().endCell();
for (const salt of [7, 8]) {
  const data = beginCell().storeUint(salt, 32).endCell();
  console.log(contractAddress(0, { code, data }).toRawString());
}

Compare the inputs the deployer actually used

Capture the code and data cell hashes from the exact StateInit in the outgoing deployment. Compare those with the predictor, including field widths and the order of references. Encoding the same numeric salt in 64 bits gives a different bit string. Use the original initialization material for this check: the data of an already active account may have changed after deployment.

docs.ton.org Deriving TON addresses