Deployment and Testing
This chapter walks through building, deploying, and configuring the tribe storage extension on the EVE Frontier Stillness testnet.
Prerequisites
Before deploying, make sure you have:
- The SUI CLI installed (
cargo install --locked --git https://github.com/MystenLabs/sui.git sui) - A SUI wallet with testnet SUI for gas (use
sui client fauceton testnet) - The EVE Frontier world contracts cloned locally (referenced as a dependency in
Move.toml)
Project Structure
``
contracts/tribe-storage-access/
├── Move.toml
├── Published.toml # Created after deployment
└── sources/
├── config.move
└── tribe_storage.move
`
Move.toml
toml[package]
name = "tribe_storage_access"
edition = "2024.beta"
[dependencies]
world = { local = "../../.world-contracts/contracts/world" }
[environments]
testnet_internal = "4c78adac"
testnet_utopia = "4c78adac"
testnet_stillness = "4c78adac"
The
[environments] section maps EVE Frontier environment names to chain identifiers. The world dependency points to the locally cloned game contracts, which provide StorageUnit, Character, OwnerCap, and other types.
Building
Compile the package to check for errors:
bashcd contracts/tribe-storage-access
sui move build
A successful build produces no errors and creates a
build/ directory with the compiled bytecode. Common build errors include:
- Missing dependencies -- ensure the
world path is correct
Ability mismatches -- check that your structs have the required abilities
Visibility errors -- public(package) functions cannot be called from outside the package
Deploying
Publish the package to the Stillness testnet:
bashsui client publish --gas-budget 100000000
On success, the output includes:
- Package ID -- the on-chain address of your published code
- Created objects -- the
AdminCap and ExtensionConfig object IDs
Example output (abbreviated):
`
----- Transaction Effects ----
Created Objects:
- ID: 0xabc123... , Owner: Account Address (0xYOUR_ADDR) ← AdminCap
- ID: 0xdef456... , Owner: Shared ← ExtensionConfig
Published Package: 0x789...
`
Record these three values. You will need them for configuration and dApp setup.
Published.toml
After deploying, create a
Published.toml file to record the deployment for future reference and for any tooling that needs it:
toml[stillness]
package_id = "0x789..." # Package ID from publish output
config_id = "0xdef456..." # ExtensionConfig object ID (Shared)
admin_cap_id = "0xabc123..." # AdminCap object ID (Owned)
published_at = "2025-01-15"
This file is not consumed by the Move compiler but is useful for scripts and documentation.
Post-Deployment Configuration
After publishing, you need to:
Set the tribe configuration
Have the SSU owner authorize the extension
Step 1: Set Tribe Config
Call
set_tribe_config to specify which tribe can use the shared storage:
bashsui client call \
--package 0x789... \
--module tribe_storage \
--function set_tribe_config \
--args 0xdef456... 0xabc123... 5 \
--gas-budget 10000000
Arguments in order:
0xdef456... -- ExtensionConfig object ID (shared)
0xabc123... -- AdminCap object ID (owned by you)
5 -- Tribe ID (u32)
Or from TypeScript:
typescriptimport { Transaction } from '@mysten/sui/transactions';
import { SuiGrpcClient } from '@mysten/sui/grpc';
const client = new SuiGrpcClient({ network: 'testnet' });
const tx = new Transaction();
tx.moveCall({
target: ${PACKAGE_ID}::tribe_storage::set_tribe_config,
arguments: [
tx.object(CONFIG_ID), // ExtensionConfig
tx.object(ADMIN_CAP_ID), // AdminCap
tx.pure.u32(5), // tribe ID
],
});
// Sign and execute with your wallet
Step 2: Authorize on SSU
The SSU owner must authorize the extension. This is done via a PTB that borrows the SSU's
OwnerCap:
typescriptconst tx = new Transaction();
const xAuthType = ${PACKAGE_ID}::config::XAuth;
const ssuType = ${EVE_FRONTIER_PKG}::storage_unit::StorageUnit;
// Borrow OwnerCap<StorageUnit> from the character
const [cap, receipt] = tx.moveCall({
target: ${EVE_FRONTIER_PKG}::character::borrow_owner_cap,
typeArguments: [ssuType],
arguments: [
tx.object(characterObjectId),
tx.object(Inputs.ReceivingRef({
objectId: ownerCapId,
version: capVersion,
digest: capDigest,
})),
],
});
// Authorize the extension
tx.moveCall({
target: ${EVE_FRONTIER_PKG}::storage_unit::authorize_extension,
typeArguments: [xAuthType],
arguments: [tx.object(ssuId), cap],
});
// Return the cap
tx.moveCall({
target: ${EVE_FRONTIER_PKG}::character::return_owner_cap,
typeArguments: [ssuType],
arguments: [tx.object(characterObjectId), cap, receipt],
});
Verifying the Deployment
Check the Package
bashsui client object 0x789...
This shows the published package metadata.
Check the Config Object
bashsui client object 0xdef456...
After
set_tribe_config, you should see a dynamic field attached to the object.
Test a Share Operation
Have a tribe member dock at the SSU in the game client, drag items from ship to SSU, then call
share() from the dApp. If everything is configured correctly:
- The transaction succeeds
- Items appear in the open inventory
- Other tribe members can see and withdraw them
Common Deployment Issues
"Package not found" or dependency errors
Ensure the
world dependency path in Move.toml points to the correct local clone of the EVE Frontier contracts. The clone must include the correct version for the target environment.
"Object equivocation" after failed transactions
If a transaction fails but the wallet still references stale object versions, you may see equivocation errors. Call
reportTransactionEffects on the SUI client to update the wallet's object cache, or wait a few seconds and retry.
"Dry run failed, could not determine gas budget"
Some wallet integrations fail on dry-run due to complex PTBs. Set an explicit gas budget:
typescripttx.setGasBudget(50_000_000n);
AdminCap lost or transferred
If the
AdminCap is sent to the wrong address, you lose admin control forever. There is no recovery mechanism -- you would need to publish a new package.
Key Takeaways
- Build with
sui move build, deploy with sui client publish --gas-budget .
Record the Package ID, ExtensionConfig ID, and AdminCap ID from the publish output.
Post-deployment requires two steps: set_tribe_config (admin sets tribe) and authorize_extension (SSU owner grants access).
Use Published.toml` to track deployment details for your team.
Sign in to track your progress.