Build
End-to-end build guide: write a gate extension, publish it, and test the complete jump flow. For concepts and behaviour, see the Gate README.
Prerequisites
Follow environment-setup
Complete step-by-step instructions: builder-scaffold builder-flow
Gate API
Custom contracts use the typed witness pattern: define a witness struct (Auth) and register it on the gate. The world gate module verifies the type at runtime.
Authorize an extension:
public fun authorize_extension<Auth: drop>(
gate: &mut Gate,
owner_cap: &OwnerCap<Gate>,
)Issue a jump permit (called by your extension):
public fun issue_jump_permit<Auth: drop>(
source_gate: &Gate,
destination_gate: &Gate,
character: &Character,
_: Auth,
expires_at_timestamp_ms: u64,
ctx: &mut TxContext,
)Jump with a permit:
JumpPermit (from the world module): contains character_id, route_hash, and expires_at_timestamp_ms. The route_hash is direction-agnostic — a permit for Gate A → Gate B also works for Gate B → Gate A.
Below is the high-level understanding:
1. Understand the example contract
The scaffold includes a working gate extension at move-contracts/smart_gate/. It has three modules:
config.move — shared configuration object and the witness type:
XAuth is the witness type registered on the gate. ExtensionConfig is a shared object where extension modules store their rules as dynamic fields. AdminCap controls who can update those rules.
tribe_permit.move — issues jump permits only to characters in a configured tribe:
The key pattern: your module calls gate::issue_jump_permit<XAuth> with your witness type. The gate verifies XAuth matches the type registered via authorize_extension.
corpse_gate_bounty.move — a more advanced example that combines a storage unit interaction with a gate permit. Players deposit a bounty item and receive a jump permit in return.
2. Build and publish
For local network, provide the world package path:
From the publish output, note the package ID and the ExtensionConfig object ID. Set both in your .env:
3. Configure extension rules
Set the tribe and expiry parameters on the shared ExtensionConfig:
This calls tribe_permit::set_tribe_config with a tribe ID and permit expiry duration. You can modify ts-scripts/smart_gate/configure-rules.ts to change the values.
4. Authorize the extension on both gates
Register your XAuth type on each gate so it switches from default (open) to permit-based:
Under the hood this builds a transaction that:
Borrows the gate's
OwnerCapfrom the characterCalls
gate::authorize_extension<XAuth>on the gateReturns the
OwnerCapto the character
After this, the default jump function is disabled — players must use jump_with_permit.
5. Issue a jump permit
Issue a permit to a player character:
This calls tribe_permit::issue_jump_permit, which checks the character's tribe and mints a JumpPermit object owned by the character.
Players can collect/buy permit from a builder dapp.
6. Jump with permit
The player uses their permit to jump through the gate:
A successful jump emits a JumpEvent and consumes the permit. Ideally this flow happens in the game.
Writing your own extension
To create a gate extension from scratch:
Define a witness struct (e.g.,
public struct MyAuth has drop {})Write a function that enforces your rules and calls
gate::issue_jump_permit<MyAuth>Publish the contract and authorize it on your gate with
gate::authorize_extension<MyAuth>
Here's a minimal toll gate that requires payment before issuing a permit:
Other ideas:
Allowlist — check a stored list of approved characters
Bounty gate — require depositing an item to earn passage (see
corpse_gate_bounty.movein the scaffold)
See the Gate API above for the full function signatures.
Reference
world-contracts — EVE Frontier Sui Move contracts
gate.move — core gate module
builder-scaffold smart_gate — example gate extension
contracts/world — world contract package
Last updated

