> For the complete documentation index, see [llms.txt](https://syntrei.gitbook.io/0xsecure/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://syntrei.gitbook.io/0xsecure/0xsecure-sui-move-package.md).

# 0xsecure Sui-Move Package

This guide shows how Sui developers can add the 0xSecure Move package to their own contracts and protect sensitive functions with on-chain policy checks.

0xSecure on Move is an enforcement layer. It does not run the API, AI engine, simulator, or threat memory on-chain. Your contract checks a `Policy` and a one-time `ApprovalReceipt` before it performs a sensitive action.

## Testnet Package

The 0xSecure Move package is live on Sui testnet:

```
Package ID: 0x07c365ac725cc6cca2846899d8b816860b47e5449af687e688c331b2c39be44c
Modules: action, action_hash, approval, enforcement, errors, policy
```

## Add The Dependency

Add 0xSecure to your `Move.toml`:

```toml
[package]
name = "MyProtocol"
version = "0.0.1"
edition = "2024.beta"

[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" }
0xSecure = { git = "https://github.com/0xsecure/0xsecure.git", subdir = "Contracts/0xsecure", rev = "main" }

[addresses]
my_protocol = "0x0"
oxsecure = "0x07c365ac725cc6cca2846899d8b816860b47e5449af687e688c331b2c39be44c"
```

For production integrations, prefer a release tag or commit hash instead of `main` once one is available.

For local development against a checkout of this repo:

```toml
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" }
0xSecure = { local = "../0xsecure/Contracts/0xsecure" }

[addresses]
my_protocol = "0x0"
oxsecure = "0x0"
```

## Import The Modules

Use only the modules your contract needs:

```move
use oxsecure::action;
use oxsecure::approval::ApprovalReceipt;
use oxsecure::enforcement;
use oxsecure::policy::Policy;
use sui::clock::Clock;
```

## Choose A Policy

Policies are created by the protocol owner or setup transaction. The constructor transfers both a `Policy` and matching `PolicyCap` to the sender. Keep the `PolicyCap` with governance, multisig, or a controlled operator process.

Common constructors:

* `policy::create_flexible_agent_policy`: low-friction agent protection. Requires a valid `agent_execute` receipt but no recipient allowlist or amount cap by default.
* `policy::create_agent_policy`: agent protection with an amount cap and optional recipient allowlist.
* `policy::create_treasury_policy`: treasury withdrawals with amount cap, recipient allowlist, and `treasury_withdraw` action type.
* `policy::create_admin_policy`: admin/config actions with receipt enforcement.
* `policy::create_protocol_policy`: custom action allowlist.
* `policy::create_bound_protocol_policy`: custom policy bound to a specific object ID, such as one vault, market, or treasury.

Example flexible agent setup:

```move
public fun setup_agent_policy(issuer: address, ctx: &mut TxContext) {
    oxsecure::policy::create_flexible_agent_policy(
        issuer,
        300000,
        ctx,
    );
}
```

Example treasury setup:

```move
public fun setup_treasury_policy(
    issuer: address,
    allowed_recipients: vector<address>,
    ctx: &mut TxContext,
) {
    oxsecure::policy::create_treasury_policy(
        1_000_000_000,
        issuer,
        allowed_recipients,
        300000,
        ctx,
    );
}
```

## Protect A Function

Call `enforcement::assert_action` before changing state or moving funds.

```move
public fun guarded_withdraw(
    treasury: &mut Treasury,
    policy: &Policy,
    receipt: ApprovalReceipt,
    action_hash: vector<u8>,
    recipient: address,
    amount: u64,
    clock: &Clock,
) {
    enforcement::assert_action(
        policy,
        receipt,
        action_hash,
        action::treasury_withdraw(),
        recipient,
        amount,
        clock,
    );

    // Do the sensitive work only after the policy check passes.
    treasury.balance = treasury.balance - amount;
}
```

For policies bound to a protocol object, use `assert_protocol_action`:

```move
enforcement::assert_protocol_action(
    policy,
    receipt,
    action_hash,
    action::protocol_operation(),
    protocol_id,
    recipient,
    amount,
    clock,
);
```

## Receipt Flow

Every protected action needs an `ApprovalReceipt`.

The receipt binds:

* policy ID
* action hash
* action type
* issuer
* optional protocol object ID
* recipient
* amount
* nonce
* expiry timestamp

Only the policy's configured issuer can create a valid receipt. The receipt is consumed after successful enforcement, so it cannot be reused.

If you use the 0xSecure API, the API decides whether to issue or relay approvals. If you use the Move package only, your own backend, governance, multisig, or operator process must decide when to issue receipts.

## Build The Action Hash

The protected transaction must pass the same hash that was approved in the receipt. The canonical on-chain helper is `oxsecure::action_hash`.

For an unbound action:

```move
let action_hash = oxsecure::action_hash::digest_unbound(
    policy_id,
    action::treasury_withdraw(),
    recipient,
    amount,
    nonce,
    expires_at_ms,
);
```

For a bound protocol action:

```move
let action_hash = oxsecure::action_hash::digest_bound(
    policy_id,
    action::protocol_operation(),
    protocol_id,
    recipient,
    amount,
    nonce,
    expires_at_ms,
);
```

Off-chain code must BCS-encode the same fields in the same order and hash them with Blake2b-256.

## Minimal Restriction Defaults

0xSecure policies are designed to start flexible and become stricter only where needed:

* empty recipient list means any recipient is allowed
* empty action type list means any action type is allowed
* no bound protocol means any protocol object is allowed
* `max_receipt_ttl_ms = 0` means no TTL ceiling
* `has_amount_limit = false` means amount checks are skipped

The core check remains the receipt: correct issuer, correct action hash, correct action type, not expired, not reused.

## Common Failures

* `E_AMOUNT_TOO_HIGH`: the policy has an amount limit and the action amount is above it.
* `E_RECIPIENT_NOT_ALLOWED`: the recipient allowlist is non-empty and does not include the recipient.
* `E_ACTION_TYPE_NOT_ALLOWED`: the action type allowlist is non-empty and does not include the expected action.
* `E_PROTOCOL_MISMATCH`: the policy is bound to one protocol object but the receipt/action uses another.
* `E_RECEIPT_EXPIRED`: the receipt expiry has passed.
* `E_RECEIPT_TTL_TOO_LONG`: the receipt expiry is too far in the future for the policy.
* `E_RECEIPT_REQUIRED`: a receipt-required policy was checked with a basic no-receipt helper.

## Test Your Integration

Run:

```bash
sui move build
sui move test
```

If you are publishing to testnet:

```bash
sui client switch --env testnet
sui client publish . --gas-budget 200000000
```

Make sure your `Move.toml` uses the testnet package ID above for `oxsecure`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://syntrei.gitbook.io/0xsecure/0xsecure-sui-move-package.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
