Contract deployment
Learn how to deploy smart contracts
TODO: To be reworked. Some parts will go to deploy.mdx, and this page will become a part of a single cohesive tutorial.
In Acton, there is no dedicated acton deploy command. Instead, it uses Tolk scripts for deployment.
This approach provides maximum flexibility. Real-world contracts often require complex initialization data—such as dictionaries for metadata, encoded cell structures, or specific initial state configurations—which are cumbersome or impossible to pass via command-line arguments. By using scripts, you can utilize the full power of the Tolk language to prepare deployment data, calculate initial state, and manage the deployment flow programmatically.
Prerequisites
Before deploying to the real network, you need to configure a wallet in your wallets.toml (or global configuration).
[wallets.deployer]
kind = "v5r1"
workchain = 0
keys = { mnemonic = "word1 word2 word3 ... word24" }See the Setting up wallets guide for detailed instructions on configuring wallets safely.
Writing a Deploy Script
A deploy script is a standard Tolk script that interacts with the network. It typically involves three steps:
- Loading the deployer wallet.
- Preparing the contract's initial state and code.
- Sending the deployment transaction.
Here is an example of a script that deploys a simple Counter contract:
import "@acton/io"
import "@acton/emulation/network"
import "@acton/emulation/scripts"
import "@acton/build"
import "@wrappers/Counter" // Import your contract wrapper
import "@contracts/types" // Import types if needed
fun main() {
// 1. Load the configured wallet (searches wallets.toml and global wallets)
val deployer = scripts.wallet("deployer");
// 2. Prepare the contract
// We create the contract instance locally with its initial state
val counter = Counter.fromStorage({
id: 123, // Unique ID to randomize address
counter: 0, // Initial counter value
});
println("Deploying counter to {}", counter.address);
// 3. Deploy the contract
// This sends a transaction from the deployer wallet with the stateInit
val result = counter.deploy(deployer.address, { value: ton("0.05") });
// Wait for the transaction to be confirmed on the blockchain
if (!result.wait()) {
return;
}
println("Deployment complete: {}", counter.address);
println("On-chain counter is {}", counter.currentCounter());
}Complex Deployments
For more complex contracts like Jettons, you can construct dictionaries and other data structures directly in the script:
// ... imports ...
import "@acton/emulation/scripts"
fun main() {
val deployer = scripts.wallet("deployer");
// Construct Jetton metadata
val content = buildOnchainMetadata({
name: "MyJetton",
symbol: "JET",
description: "A cool jetton on TON",
image: "https://example.com/icon.png",
});
val minter = JettonMinter.fromStorage({
totalSupply: 1_000_000_000,
adminAddress: deployer.address,
content: content,
jettonWalletCode: build("JettonWallet"),
});
// Deploy
minter.deploy(deployer.address, { value: ton("0.05") }).wait();
println("Jetton deployed at {}", minter.address);
}Running the Deployment
To execute your deployment script on the real blockchain, use the acton script command with --net <network>.
Executing scripts in real blockchain is often called "broadcasting", opposed to local "emulation".
Testnet
acton script scripts/deploy.tolk --net testnetIn broadcast mode, read-only calls such as counter.currentCounter() use
the same network by default, so deploy scripts can verify on-chain state
without an extra --fork-net.
To deploy to testnet, your wallet must have testnet TONs. You can get them for free with acton wallet airdrop command or from the Testnet Faucet.
Mainnet
To deploy to the mainnet, specify the network flag:
acton script scripts/deploy.tolk --net mainnetWhen deploying to mainnet, real value is transferred. Ensure your contract logic is tested and audit-ready.
Localnet
Deployment to a local network allows you to get closer to real networks than tests, but at the same time not depend on the external network and remain completely local.
acton script scripts/deploy.tolk --net localnetBefore deploying, make sure you have launched the localnet.
Using API Keys
For faster and more reliable interactions, especially on mainnet, it is recommended to use an API key from TonCenter.
TONCENTER_MAINNET_API_KEY=YOUR_API_KEY acton script scripts/deploy.tolk --net mainnetSet TONCENTER_MAINNET_API_KEY for mainnet flows and
TONCENTER_TESTNET_API_KEY for testnet flows. Acton reads the matching env
variable automatically for the built-in TonCenter-backed networks.
Local Testing
One of the biggest advantages of using scripts is that you can test the exact same deployment logic locally before spending money.
Simply run the script without --net:
acton script scripts/deploy.tolkIn this mode, scripts.wallet("deployer") creates a virtual wallet, and the deployment happens in the local emulator. This allows you to verify that your state initialization and logic are correct before spending any money.
The same script can still call wrapper getters after deploy: in emulation they
read emulator state, and in broadcast mode they read the selected real network.
Last updated on