This guide will help you deploying your Solidity code on the TAC EVM. You can then invoke this code on TON side with the TAC SDK. Here you will learn on how to connect directly to the TAC EVM with an EVM wallet and deploy your solidity code.

View the Network Details for more information about the TAC EVM.

Environment Setup

To be able to deploy solidity code on TAC you will need to create and configure an EVM wallet like Rabby and then install and configure an EVM toolkit like Foundry or HardHat.

In this guide, we will use Foundry as our EVM toolkit. Foundry is a smart contract development toolkit for EVM chains. Start by installing Foundry with the following command:

curl -L https://foundry.paradigm.xyz | bash

Next, run the following commands to create a new Foundry project:

forge init my-tac-project
cd my-tac-project

The folder structure should look like this:

├── lib
├── script
├── src
└── test
foundry.toml

In the src folder, create a new Solidity file, for example MyContract.sol:

touch src/MyContract.sol

And write your smart contract code in MyContract.sol. To compile the contract, run the following command:

forge build

Get TAC Testnet Gastokens

You will need to load some TAC Testnet tokens to pay TAC gasfees to deploy a solidity contract on TAC EVM.

To get some testnet tokens, please visit the Turin Faucet (Coming Soon - later this week)

Deploy TON Jettons First (if needed)

If your application requires tokens, you must first deploy your Jettons on TON since Telegram guidelines require all tokens to be native to TON.

Get Testnet TON

Before deploying Jettons, you’ll need testnet TON tokens:

Deploy Jetton Contract

You have two options to deploy a Jetton on TON:

Option 1: Deploy Jetton Contract

If you’re familiar with FunC, you can deploy a Jetton contract directly. Create a new file jetton.fc:

#include "imports/stdlib.fc";
#include "imports/params.fc";
#include "imports/jetton-utils.fc";

() mint_tokens(slice to_address, cell jetton_wallet_code, int amount, cell master_msg) impure {
    cell state_init = calculate_jetton_wallet_state_init(to_address, my_address(), jetton_wallet_code);
    slice to_wallet_address = calculate_jetton_wallet_address(state_init);
    var msg = begin_cell()
        .store_uint(0x18, 6)
        .store_slice(to_wallet_address)
        .store_coins(amount)
        .store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
        .store_ref(state_init)
        .store_ref(master_msg);
    send_raw_message(msg.end_cell(), 1);
}

() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
    if (in_msg_body.slice_empty?()) {
        return ();
    }

    slice cs = in_msg_full.begin_parse();
    int flags = cs~load_uint(4);
    slice sender_address = cs~load_msg_addr();

    load_data();
    int op = in_msg_body~load_uint(32);

    if (op == op::mint()) {
        throw_unless(73, equal_slices(sender_address, admin_address));
        slice to_address = in_msg_body~load_msg_addr();
        int amount = in_msg_body~load_coins();
        cell master_msg = in_msg_body~load_ref();
        mint_tokens(to_address, jetton_wallet_code, amount, master_msg);
        save_data();
        return ();
    }
}

Option 2: Using TypeScript SDK

For most developers, using the TypeScript SDK is easier. Create a new project:

mkdir my-jetton
cd my-jetton
npm init -y
npm install @ton/ton @ton/core @ton/crypto

create deploy.ts with the following content:

import { mnemonicToWalletKey } from "@ton/crypto";
import { TonClient, WalletContractV4, JettonMinter } from "@ton/ton";

async function deploy() {
  // Initialize TON client
  const client = new TonClient({
    endpoint: "https://testnet.toncenter.com/api/v2/jsonRPC",
  });

  // Your wallet mnemonics (24 words)
  const mnemonic = "your mnemonic words here...";
  const key = await mnemonicToWalletKey(mnemonic.split(" "));
  const wallet = WalletContractV4.create({ publicKey: key.publicKey });
  const contract = client.open(wallet);

  // Jetton deployment parameters
  const jettonParams = {
    name: "My Token",
    symbol: "MTK",
    description: "My test token on TON",
    decimals: 9,
    image: "https://example.com/image.png",
  };

  // Deploy Jetton Minter contract
  const minter = await JettonMinter.create({
    admin: wallet.address,
    content: jettonParams,
    wallet: contract,
  });

  const deployResult = await minter.deploy(key.secretKey);
  console.log("Jetton deployed:", deployResult.address.toString());
}

deploy().catch(console.error);

To deploy:

npx ts-node deploy.ts

Make sure to:

  • Replace the mnemonic with your actual wallet words
  • Have sufficient testnet TON from the faucet
  • Save the deployed Jetton address - you’ll need it for TAC integration

Deploying Solidity Code

To deploy your contract on to the TAC network, run the following forge create command.

forge create --rpc-url TAC_RPC_URL \
--private-key YOUR_PRIVATE_KEY \
src/MyContract.sol:MyContract

Make sure to replace TAC_RPC_URL with the actual RPC URL of the TAC network and YOUR_PRIVATE_KEY with your actual private key.

Once the transaction is confirmed, you will see the contract address in the terminal. You can verify the contract on the Turin Block Explorer

No files changed, and compilation skipped
Deployer: 0x....
Deployed to: 0x....
Transaction hash: 0x....

Next Steps

Now that you’ve deployed solidity code on TAC, you need to build/modify a frontend or a Telegram Mini APP (TMA) that will interact with the solidity code you just deployed.