Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6e73c97
WIP: Migrate Hardhat to Foundry with comprehensive test suite
h4x3rotab Jul 23, 2025
f1b4cf8
Complete Hardhat removal - migrate to pure Foundry setup
h4x3rotab Jul 23, 2025
9ac2ca3
Remove Foundry build artifacts and update .gitignore
h4x3rotab Jul 23, 2025
3129129
Clean up test suite - remove duplicate upgrade tests
h4x3rotab Jul 23, 2025
5ef8213
wip
h4x3rotab Jul 28, 2025
c1670bd
wip
h4x3rotab Jul 28, 2025
1890fce
refactor: modularize Anvil testing with separate setup and run scripts
h4x3rotab Aug 1, 2025
5336333
docs: update README with 100% test pass rate and new testing workflow
h4x3rotab Aug 1, 2025
67177ae
chore: remove unnecessary files
h4x3rotab Aug 1, 2025
5090575
Clean up documentation and remove script overlaps
h4x3rotab Aug 2, 2025
005efa2
remove unused code
h4x3rotab Aug 4, 2025
2849421
refactor: make Foundry tests run by default
h4x3rotab Aug 4, 2025
d537736
branding: s/(DS|Ds)tack/dstack
h4x3rotab Aug 4, 2025
4df9836
fix spdx annotation
h4x3rotab Aug 15, 2025
d87d2e8
fix: move Foundry CI workflow to repository root and add --ffi flag
h4x3rotab Nov 20, 2025
d5fed7d
fix: add view modifier to pure assertion test functions
h4x3rotab Nov 20, 2025
854d5d4
chore: format Solidity code with forge fmt
h4x3rotab Nov 20, 2025
135a380
fix: add --ffi flag to forge test in run-tests.sh
h4x3rotab Nov 20, 2025
c7a7516
docs: update KMS documentation for Foundry migration
h4x3rotab Jan 14, 2026
fea4351
fix: upgrade to Solidity 0.8.24 for OpenZeppelin 5.x compatibility
h4x3rotab Jan 14, 2026
32936b9
chore: add broadcast/ and coverage/ to gitignore
h4x3rotab Jan 14, 2026
e6c83a1
ci: add permissions block to foundry-test workflow
h4x3rotab Jan 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/foundry-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
#
# SPDX-License-Identifier: Apache-2.0

name: KMS Auth-ETH Foundry Tests

on:
push:
paths:
- 'kms/auth-eth/**'
- '.github/workflows/foundry-test.yml'
pull_request:
paths:
- 'kms/auth-eth/**'
- '.github/workflows/foundry-test.yml'
workflow_dispatch:

permissions:
contents: read

env:
FOUNDRY_PROFILE: ci

jobs:
check:
name: Foundry project
runs-on: ubuntu-latest
defaults:
run:
working-directory: kms/auth-eth
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Show Forge version
run: |
forge --version

- name: Run Forge fmt
run: |
forge fmt --check
id: fmt

- name: Run Forge build
run: |
forge build --sizes
id: build

- name: Run Forge tests
run: |
forge test --ffi -vvv
id: test
18 changes: 7 additions & 11 deletions .github/workflows/kms-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,26 +69,22 @@ jobs:
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
cache-dependency-path: kms/auth-eth/package-lock.json
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Install dependencies and compile contracts
- name: Compile contracts with Foundry
run: |
cd kms/auth-eth
npm ci
npx hardhat compile
forge install
forge build

- name: GitHub Release
uses: softprops/action-gh-release@v1
with:
name: "KMS Release v${{ env.VERSION }}"
files: |
kms/auth-eth/artifacts/contracts/DstackKms.sol/DstackKms.json
kms/auth-eth/artifacts/contracts/DstackApp.sol/DstackApp.json
kms/auth-eth/out/DstackKms.sol/DstackKms.json
kms/auth-eth/out/DstackApp.sol/DstackApp.json
body: |
## Docker Image Information

Expand Down
13 changes: 13 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
#
# SPDX-License-Identifier: Apache-2.0

[submodule "kms/auth-eth/lib/forge-std"]
path = kms/auth-eth/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "kms/auth-eth/lib/openzeppelin-contracts-upgradeable"]
path = kms/auth-eth/lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "kms/auth-eth/lib/openzeppelin-foundry-upgrades"]
path = kms/auth-eth/lib/openzeppelin-foundry-upgrades
url = https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades
27 changes: 16 additions & 11 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,20 @@ cargo clippy -- -D warnings --allow unused_variables

```bash
cd kms/auth-eth
npm install
npm run build # Compile TypeScript
npm test # Run tests
npm run test:coverage # Run tests with coverage

# Hardhat commands
npx hardhat compile
npx hardhat test
npx hardhat node # Start local node
npm install # Install Node.js dependencies for bootAuth server
forge install # Install Foundry dependencies (submodules)

# Build
forge build # Compile smart contracts
npm run build # Build TypeScript server

# Test
forge test --ffi # Run Foundry contract tests
npm test # Run TypeScript server tests
npm run test:coverage # Run TypeScript tests with coverage

# Local development
anvil # Start local Ethereum node
```

### Python SDK
Expand Down Expand Up @@ -174,8 +179,8 @@ This rule is enforced in `.cursorrules`.
- Via Web UI: `http://localhost:9080` (or configured port)
- Via CLI: `./vmm-cli.py` (see `docs/vmm-cli-user-guide.md`)
- Requires:
1. On-chain app registration (`npx hardhat kms:create-app`)
2. Adding compose hash to whitelist (`npx hardhat app:add-hash`)
1. On-chain app registration (see `docs/onchain-governance.md`)
2. Adding compose hash to whitelist
3. Deploying via VMM with App ID

### Accessing Deployed Apps
Expand Down
2 changes: 1 addition & 1 deletion docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ Continue? [y/N]

**Before pressing 'y'**, add the compose hash to your auth server whitelist:
- For auth-simple: Add to `composeHashes` array in `auth-config.json`
- For auth-eth: Use `app:add-hash` (see [On-Chain Governance](./onchain-governance.md#register-gateway-app))
- For auth-eth: Use Foundry scripts (see [On-Chain Governance](./onchain-governance.md#register-gateway-app))

Then return to the first terminal and press 'y' to deploy.

Expand Down
60 changes: 35 additions & 25 deletions docs/onchain-governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,38 @@ On-chain governance adds:

- Production dstack deployment with KMS and Gateway as CVMs (see [Deployment Guide](./deployment.md))
- Ethereum wallet with funds on Sepolia testnet (or your target network)
- Node.js and npm installed
- Alchemy API key (for Sepolia) - get one at https://www.alchemy.com/
- [Foundry](https://book.getfoundry.sh/getting-started/installation) installed
- Node.js and npm installed (for the bootAuth server)

## Deploy DstackKms Contract

```bash
cd dstack/kms/auth-eth
npm install
npx hardhat compile
PRIVATE_KEY=<your-key> ALCHEMY_API_KEY=<your-key> npx hardhat kms:deploy --with-app-impl --network sepolia
npm install # Install Node.js dependencies
forge install # Install Foundry dependencies

# Deploy contracts (deploys both DstackApp implementation and DstackKms proxy)
PRIVATE_KEY=<your-key> forge script script/Deploy.s.sol:DeployScript \
--broadcast --rpc-url https://eth-sepolia.g.alchemy.com/v2/<your-alchemy-key>
```

The command will prompt for confirmation. Sample output:
Sample output:

```
✅ DstackApp implementation deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3
DstackKms Proxy deployed to: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
Implementation deployed to: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
Deploying with account: 0x...
DstackApp implementation deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3
DstackKms implementation deployed to: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
DstackKms proxy deployed to: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
```

Note the proxy address (e.g., `0x9fE4...`).

Set environment variables for subsequent commands:

```bash
export KMS_CONTRACT_ADDRESS="<DstackKms-proxy-address>"
export KMS_CONTRACT_ADDR="<DstackKms-proxy-address>"
export PRIVATE_KEY="<your-private-key>"
export ALCHEMY_API_KEY="<your-alchemy-key>"
export RPC_URL="https://eth-sepolia.g.alchemy.com/v2/<your-alchemy-key>"
```

## Configure KMS for On-Chain Auth
Expand All @@ -52,42 +56,45 @@ KMS_CONTRACT_ADDR=<your-dstack-kms-contract-address>
ETH_RPC_URL=<ethereum-rpc-endpoint>
```

Note: The auth-api uses `KMS_CONTRACT_ADDR`, while Hardhat tasks use `KMS_CONTRACT_ADDRESS`.

The auth-api validates boot requests against the smart contract. See [Deployment Guide](./deployment.md#2-deploy-kms-as-cvm) for complete setup instructions.

## Whitelist OS Image

```bash
npx hardhat kms:add-image --network sepolia 0x<os-image-hash>
OS_IMAGE_HASH=0x<os-image-hash> \
forge script script/Manage.s.sol:AddOsImage --broadcast --rpc-url $RPC_URL
```

Output: `Image added successfully`
Output: `Added OS image hash: 0x...`

The `os_image_hash` is in the `digest.txt` file from the guest OS image build (see [Building Guest Images](./deployment.md#building-guest-images)).

## Register Gateway App

```bash
npx hardhat kms:create-app --network sepolia --allow-any-device
# Create a new app with allowAnyDevice=true
ALLOW_ANY_DEVICE=true \
forge script script/Manage.s.sol:DeployApp --broadcast --rpc-url $RPC_URL
```

Sample output:

```
✅ App deployed and registered successfully!
Proxy Address (App Id): 0x75537828f2ce51be7289709686A69CbFDbB714F1
Deployed new app at: 0x75537828f2ce51be7289709686A69CbFDbB714F1
Owner: 0x...
Allow any device: true
```

Note the App ID (Proxy Address) from the output.
Note the App ID (deployed app address) from the output.

Set it as the gateway app:

```bash
npx hardhat kms:set-gateway --network sepolia <app-id>
GATEWAY_APP_ID=<app-id> \
forge script script/Manage.s.sol:SetGatewayAppId --broadcast --rpc-url $RPC_URL
```

Output: `Gateway App ID set successfully`
Output: `Set gateway app ID: <app-id>`

Add the gateway's compose hash to the whitelist. To compute the compose hash:

Expand All @@ -98,10 +105,11 @@ sha256sum /path/to/gateway-compose.json | awk '{print "0x"$1}'
Then add it:

```bash
npx hardhat app:add-hash --network sepolia --app-id <app-id> <compose-hash>
APP_CONTRACT_ADDR=<app-id> COMPOSE_HASH=<compose-hash> \
forge script script/Manage.s.sol:AddComposeHash --broadcast --rpc-url $RPC_URL
```

Output: `Compose hash added successfully`
Output: `Added compose hash: 0x...`

## Register Apps On-Chain

Expand All @@ -110,7 +118,8 @@ For each app you want to deploy:
### Create App

```bash
npx hardhat kms:create-app --network sepolia --allow-any-device
ALLOW_ANY_DEVICE=true \
forge script script/Manage.s.sol:DeployApp --broadcast --rpc-url $RPC_URL
```

Note the App ID from the output.
Expand All @@ -126,7 +135,8 @@ sha256sum /path/to/your-app-compose.json | awk '{print "0x"$1}'
Then add it:

```bash
npx hardhat app:add-hash --network sepolia --app-id <app-id> <compose-hash>
APP_CONTRACT_ADDR=<app-id> COMPOSE_HASH=<compose-hash> \
forge script script/Manage.s.sol:AddComposeHash --broadcast --rpc-url $RPC_URL
```

### Deploy via VMM
Expand Down
21 changes: 21 additions & 0 deletions kms/auth-eth/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
#
# SPDX-License-Identifier: Apache-2.0

# Example environment configuration for local testing

# Server configuration
PORT=8000
HOST=127.0.0.1

# Ethereum configuration
ETH_RPC_URL=http://127.0.0.1:8545
KMS_CONTRACT_ADDR=0x0000000000000000000000000000000000000000

# For testing with local Anvil node (Foundry):
# ETH_RPC_URL=http://127.0.0.1:8545
# KMS_CONTRACT_ADDR=<deployed_contract_address>

# For testing with testnet:
# ETH_RPC_URL=https://rpc.sepolia.org
# KMS_CONTRACT_ADDR=<your_deployed_contract_address>
11 changes: 10 additions & 1 deletion kms/auth-eth/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
/artifacts
/broadcast
/cache
/coverage
/dist
/out
/out

# Test logs
anvil-test.log
anvil.log
deploy.log
server-test.log
.env.test
Loading