Learn
Jetton contract
Jetton deployment

Jetton contract

Jetton deployment

Did you notice something unclear, incorrect or get stuck with some issue in guide? Please ask a question in the Telegram chat (opens in a new tab) or text me directly @iftryalexg (opens in a new tab). Guide will be updated ASAP and all unclear points will be clarified 🚒💦🔥.

Jetton tact demo project

Take example of project from GitHub:

git clone https://github.com/ton-community/tact-jetton
cd tact-jetton

Minter

In jetton.tact defines minter contract, that will deploy initial contracts of jetton wallets with special "Mint" message. Minter, usually used before Token become using by users, to distribute to all owners. In current case, we will deliver all Tokens to one owner and instantly deactivate option of mint again. Look briefly to our contract:

import "@stdlib/jetton";
 
message Mint {
    amount: Int;
}
 
contract SampleJetton with Jetton {
 
    totalSupply: Int as coins;
    owner: Address;
    content: Cell?;
    mintable: Bool;
 
    init(owner: Address, content: Cell?) {
        self.totalSupply = 0;
        self.owner = owner;
        self.mintable = true;
        self.content = content;
    }
 
    receive(msg: Mint) {
        let ctx: Context = context();
        self.mint(ctx.sender, msg.amount, ctx.sender);
    }
 
    receive("Mint!") {
        let ctx: Context = context();
        self.mint(ctx.sender, 1000000000, ctx.sender);
    }
}

In general, this contract receive "Mint" message, and if it happens he invoke mint() function, that declared in @stdlib/jetton. mint() create message and send it to new jetton-wallet contract address.

jetton-8

  1. Wallet App A send request to Wallet A send mint message to minter. Currently Minter does not exist in blockchain.
  2. Wallet A send "Mint" message to Minter's contract address. When it delivered, Minter become deployed and invoke in its mint() function.
  3. Minter send to Jetton A address Transfer message with token's supply value. When it delivered, Jetton A contract become deployed.

Deployment of jetton wallets for new users

Similar process happens when user of Wallet App A, want to send tokens to user of Wallet App B. The trick is, our contract Jetton always send information and the whole code to another address. When it comes to destination, code executes and from case was it deployed before or already deployed. In this case - transfer (opens in a new tab) jetton message become the initial message at same moment and deploys Jetton B smart contract.

jetton-8

From jetton/wallet.tact (opens in a new tab), we can see, that it will create initial data for new jetton wallet contract:

//previous code
 
       let init: StateInit = initOf JettonDefaultWallet(self.master, msg.destination);
        let walletAddress: Address = contractAddress(init);
        send(SendParameters{
            to: walletAddress, 
            value: 0,
            mode: SendRemainingValue, 
            bounce: true,
            body: TokenTransferInternal{
                amount: msg.amount,
                queryId: msg.queryId,
                from: self.owner,
                responseAddress: self.owner,
                forwardTonAmount: msg.forwardTonAmount,
                forwardPayload: msg.forwardPayload
            }.toCell(),
            code: init.code,
            data: init.data
        });
        

Here, initOf allows to calculate new contract's init data. It calculates from address of regular Wallet B, here msg.destination and address of Token master contract self.master. Because of that we always now both, we can now what address we will use as destination.

To display all data clear, application should read each element of process with get methods. It is job, that, for example, have to do blockchain explorers. jetton-8

Deployment of tact.jetton

This project has ready-made example of script for deploying jetton in testnet. Specify following things:

  • Input your deployment Testnet wallet seed in tact-wallet/sources/jetton.deploy.ts:
  // Insert your test wallet's 24 words, make sure you have some test Toncoins on its balance. Every deployment spent 0.5 test toncoin.
  let mnemonics = "multiply voice predict admit hockey fringe flat bike napkin child quote piano";
  • Input owner address at same jetton.deploy.ts:
  // Owner should usually be the deploying wallet's address.
  let owner = Address.parse('kQDND6yHEzKB82ZGRn58aY9Tt_69Ie_uz73e2V...');
  • Note, that in deployment script using walletV4. If you want use your V3R2, you need change wallet contract here.

  • Run deployment script

  yarn deploy

As a result of successfully deployment, you should deploy two contracts:

What to read next?

This article was inspired by the following materials about jetton standards:

Useful social

Useful TON links