| title | Contract Deployment | ||||||
|---|---|---|---|---|---|---|---|
| description | Deploy dstack KMS smart contracts to Sepolia testnet from your local machine | ||||||
| section | KMS Deployment | ||||||
| stepNumber | 1 | ||||||
| totalSteps | 3 | ||||||
| lastUpdated | 2026-01-09 | ||||||
| prerequisites |
|
||||||
| tags |
|
||||||
| difficulty | intermediate | ||||||
| estimatedTime | 15 minutes |
This tutorial deploys the dstack KMS smart contracts to the Sepolia testnet. Contracts are deployed from your local machine - your private key never leaves your computer.
Before starting, ensure you have:
- Completed Blockchain Wallet Setup with:
- Wallet private key stored in
~/.dstack/secrets/sepolia-private-key - Sepolia testnet ETH (~0.01 ETH recommended)
- Wallet private key stored in
- dstack repository cloned locally at v0.5.7:
git clone -b v0.5.7 https://github.com/Dstack-TEE/dstack ~/dstack
The deployment creates two smart contracts on Sepolia:
| Contract | Purpose |
|---|---|
| DstackKms Proxy | Main entry point - manages KMS settings and app authorization |
| DstackApp Implementation | Logic template for application contracts |
These contracts use the UUPS (Universal Upgradeable Proxy Standard) pattern for future upgrades.
Important: Run these steps on your LOCAL machine, not on the TDX server. Contract deployment requires your Ethereum private key. By running locally, your private key never touches the server. You need a clone of the dstack repo on your local machine:
git clone -b v0.5.7 https://github.com/Dstack-TEE/dstack ~/dstack
On your local machine, clone the dstack repository (if you haven't already) and check out v0.5.7:
git clone https://github.com/Dstack-TEE/dstack.git ~/dstack 2>/dev/null || true
cd ~/dstack
git checkout v0.5.7
cd kms/auth-ethInstall nvm (Node Version Manager), then use it to install the correct Node.js version:
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# Load nvm into current shell
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# Install and use Node.js 18 (LTS)
nvm install 18
nvm use 18
# Verify versions
node --version # Should show v18.x.x
npm --version # Should show 9.x.x or 10.x.xThen install the project dependencies:
npm installLoad your wallet private key and set the RPC URL:
# Load wallet private key
export PRIVATE_KEY=$(cat ~/.dstack/secrets/sepolia-private-key)
# Set RPC URL for Sepolia testnet
export RPC_URL="https://ethereum-sepolia-rpc.publicnode.com"Verify the private key loaded correctly:
echo "Private key loaded: ${PRIVATE_KEY:0:6}...${PRIVATE_KEY: -4}"# Check balance using cast
cast balance "$(cat ~/.dstack/secrets/sepolia-address)" --rpc-url $RPC_URLYou need at least 0.01 ETH (shown in wei: 10000000000000000). If insufficient, get free Sepolia ETH from:
- PoW Faucet (no requirements)
- Faucet List (more options)
npx hardhat compileExpected output (compiler version and file count may vary):
Downloading compiler 0.8.22
Generating typings for: 19 artifacts in dir: typechain-types for target: ethers-v6
Successfully generated 72 typings!
Compiled 19 Solidity files successfully (evm target: paris).
This generates the contract artifacts (ABI and bytecode) needed for deployment.
npx hardhat kms:deploy --with-app-impl --network customExpected output:
Deploying with account: 0xYourAddress
Account balance: 0.123456789 ETH
Step 1: Deploying DstackApp implementation...
DstackApp implementation deployed to: 0x...
Step 2: Deploying DstackKms...
DstackKms Proxy deployed to: 0x...
Complete KMS setup deployed successfully!
Save the deployed addresses for use in later tutorials:
# Replace with your actual addresses from the output above
KMS_ADDRESS="0xYourKmsProxyAddress"
APP_ADDRESS="0xYourAppImplAddress"
# Save to secrets directory
echo "$KMS_ADDRESS" > ~/.dstack/secrets/kms-contract-address
echo "$APP_ADDRESS" > ~/.dstack/secrets/app-contract-address
echo "Addresses saved to ~/.dstack/secrets/"Check the contract exists on-chain:
KMS_ADDRESS=$(cat ~/.dstack/secrets/kms-contract-address)
cast code "$KMS_ADDRESS" --rpc-url https://ethereum-sepolia-rpc.publicnode.com | head -c 20If the contract is deployed, this returns bytecode (starting with 0x). If it shows just 0x, the contract was not found.
View on Etherscan:
echo "https://sepolia.etherscan.io/address/$KMS_ADDRESS"The contracts use UUPS (Universal Upgradeable Proxy Standard):
Client Request
│
▼
┌─────────────┐
│ KMS Proxy │ ← Stores state, immutable address
│ (0x...) │
└─────┬───────┘
│ delegatecall
▼
┌─────────────┐
│ KMS Logic │ ← Contains code, can be upgraded
│ (impl) │
└─────────────┘
This allows upgrading contract logic without changing addresses or losing state.
The DstackKms contract provides:
| Function | Purpose |
|---|---|
isAppAllowed(appId) |
Check if an app is authorized |
registerApp(appId) |
Register a new application |
gatewayAppId() |
Get the gateway app identifier |
For detailed solutions, see the KMS Deployment Troubleshooting Guide:
| Operation | Gas Used | Cost at 2 gwei |
|---|---|---|
| DstackApp implementation | ~1,100,000 | ~0.0022 ETH |
| DstackKms proxy | ~210,000 | ~0.0004 ETH |
| Total | ~1,300,000 | ~0.0026 ETH |
Sepolia testnet ETH is free from faucets.
With contracts deployed, you're ready to build and configure the KMS:
- KMS Build & Configuration - Build and configure the dstack Key Management Service