Getting Started
This guide walks through creating a BST-20 fungible token contract from scratch, testing it locally with BasaltTestHost, and deploying it to a devnet. By the end, you will have a working token with mint, transfer, and balance-query functionality.
Prerequisites
- .NET 9 SDK (version 9.0 or later). Download from dot.net.
- Basalt CLI. Included in the Basalt repository under
tools/Basalt.Cli.
Verify your .NET installation:
dotnet --version
# Expected: 9.0.x or later
Scaffold a New Project
The Basalt CLI generates a contract project with the correct NuGet references, build configuration, and directory structure:
dotnet run --project tools/Basalt.Cli -- init MyToken
This creates a MyToken/ directory with a .csproj that references Basalt.Sdk.Contracts and Basalt.Sdk.Analyzers, plus a companion test project referencing Basalt.Sdk.Testing and xUnit.
Write the Contract
A BST-20 token is the simplest starting point. Create a contract that inherits from BST20Token, the SDK's built-in fungible token base class:
using Basalt.Sdk.Contracts;
[Contract("MyToken")]
public class MyToken : BST20Token
{
public MyToken() : base("My Token", "MTK", 18) { }
[ContractMethod]
public void Mint(Address to, UInt256 amount)
{
RequireOwner();
_Mint(to, amount);
}
}
This contract:
- Inherits all BST-20 functionality (transfer, approve, transferFrom, balanceOf, totalSupply, allowance) from the
BST20Tokenbase class. - Defines the token name as "My Token", the symbol as "MTK", and 18 decimal places.
- Exposes a
Mintmethod restricted to the contract owner that creates new tokens and assigns them to the target address.
Build
Compile the contract using the standard .NET build command:
dotnet build
The 12 Roslyn analyzers from Basalt.Sdk.Analyzers run automatically during the build. If the contract contains reflection usage, dynamic types, non-deterministic APIs, or other prohibited patterns, the build will fail with a descriptive error pointing to the exact line and violation.
A clean build with zero warnings and zero errors means the contract is AOT-safe, deterministic, and ready for testing.
Test with BasaltTestHost
Write tests using xUnit and BasaltTestHost, the in-process blockchain emulator. No running node or network connection is required.
[Fact]
public void Mint_IncreasesBalance()
{
var host = new BasaltTestHost();
var token = host.Deploy<MyToken>(owner);
host.Call(token, owner, t => t.Mint(alice, 1000));
Assert.Equal(1000, host.Query(token, t => t.BalanceOf(alice)));
}
The test host provides a complete execution environment:
host.Deploy<T>(deployer)deploys the contract and returns a handle.host.Call(contract, caller, c => c.Method(args))executes a state-modifying method as the specified caller.host.Query(contract, c => c.ReadMethod(args))executes a read-only view method.host.AdvanceBlock()andhost.AdvanceBlocks(n)advance the simulated block height.host.SetTimestamp(DateTimeOffset)sets the simulated block timestamp for testing time-dependent logic.host.CreateAddress()generates test addresses.
Test reverts by asserting that invalid operations throw ContractRevertException:
[Fact]
public void Mint_NonOwner_Reverts()
{
var host = new BasaltTestHost();
var token = host.Deploy<MyToken>(owner);
Assert.Throws<ContractRevertException>(() =>
host.Call(token, alice, t => t.Mint(alice, 1000)));
}
Run all tests:
dotnet test
Deploy to Devnet
Once the contract builds cleanly and all tests pass, deploy it to a running devnet using the Basalt CLI or the REST API:
dotnet run --project tools/Basalt.Cli -- deploy \
--contract ./bin/Release/net9.0/MyToken.dll \
--private-key <path-to-keyfile> \
--node http://localhost:5100
The CLI submits a deployment transaction, waits for block inclusion, and prints the resulting contract address.
Full IDE Debugging
Basalt contracts support step-through debugging in Visual Studio and JetBrains Rider. Set breakpoints inside contract methods, inspect storage state, and step through execution exactly as you would with any other .NET application. The BasaltTestHost test harness runs in-process, so the standard debugger attaches without additional configuration.
Next Steps
- SDK Reference -- Full reference for the base class, attributes, storage primitives, and types.
- Token Standards -- Explore all seven BST token standards and eight system contracts.
- Policy Hooks -- Add transfer enforcement policies to your token.
- Analyzers -- Understand the compile-time safety checks.
- Testing -- Advanced testing techniques with
BasaltTestHost.