Calculate Contract Address

When a contract is deployed to the chain, it receives an address by which users can refer to it and send it transactions.

In this example, we have two different contracts: Todo1 and Todo2. They are deployed separately and each gets its own unique address. As we've seen before, a contract can always know its own address by running myAddress().

The special bit in this example is that each contract can also get the address of the other contract by running contractAddress(stateInit).

How is the contract address generated?

Contract addresses on TON are derived from the initial code of the contract (the compiled bytecode) and the initial data of the contract (the arguments of init).

Both contracts don't have any constructor arguments, so their initial data is the identical. Their addresses are different because their code is different.

The combination of the inital code and the initial data is called the stateInit of the contract. Tact gives easy access to the stateInit using the initOf statement.

All Examples
import "@stdlib/deploy";

message HiFromParent {
    greeting: String;
}

message HiFromChild {
    fromSeqno: Int as uint64;
    greeting: String;
}

// we have multiple instances of the children
contract TodoChild {

    seqno: Int as uint64;
 
    // when deploying an instance, we must specify its index (sequence number)
    init(seqno: Int) {
        self.seqno = seqno;
    }

    receive(msg: HiFromParent) {
        dump(self.seqno);
        dump("😃 handling hi from parent");
        self.reply(HiFromChild{fromSeqno: self.seqno, greeting: "sup"}.toCell());
    }
}

// we have one instance of the parent
contract TodoParent with Deployable {
 
    init() {}

    receive("greet 3") {
        let i: Int = 0;
        repeat (3) {
            i = i + 1;
            let init: StateInit = initOf TodoChild(i);
            send(SendParameters{
                to: contractAddress(init),
                body: HiFromParent{greeting: "darling"}.toCell(),
                value: ton("0.1"),              // pay for message and potential deployment
                mode: SendIgnoreErrors,
                code: init.code,                // if child is not deployed, also deploy it
                data: init.data
            });
        }
    }

    receive(msg: HiFromChild) {
        dump("😑 handling hi from child");
        dump(msg.fromSeqno);
    }
}