Skip to content

feat: sui rfq vault and tests#11

Closed
reddyismav wants to merge 3 commits into
mainfrom
sui-rfq
Closed

feat: sui rfq vault and tests#11
reddyismav wants to merge 3 commits into
mainfrom
sui-rfq

Conversation

@reddyismav

@reddyismav reddyismav commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added an RFQ vault package enabling vault creation, deposits, and quote settlement or refunds using signature-verified authorization.
    • Added owner controls for pausing/unpausing, updating the solver key, transferring ownership, and rescuing/funding tokens.
    • Added public read access to vault and quote status (balances, used/marked states).
  • Bug Fixes
    • Prevents replay by marking quotes as used/refunded/marked-for-refund, and validates quote identifiers.
  • Tests
    • Introduced comprehensive Move test coverage for settlement, refund, pause behavior, and authorization flows.
  • Chores
    • Added Sui deployment/build/test scripts and updated ignore rules.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 363 files, which is 63 over the limit of 300.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4f359d90-b6dd-413b-80b4-b06ce0bcb67c

📥 Commits

Reviewing files that changed from the base of the PR and between 48f0a46 and 59bc5fd.

⛔ Files ignored due to path filters (1)
  • sui/rfq-vault/Move.lock is excluded by !**/*.lock
📒 Files selected for processing (363)
  • .gitignore
  • deployments/prod/addresses/sui.json
  • package.json
  • scripts/sui/deployRfqVault.ts
  • scripts/sui/printKmsSolverKey.ts
  • scripts/sui/rfqVaultDeploymentConfig.ts
  • sui/rfq-vault/Move.toml
  • sui/rfq-vault/Published.toml
  • sui/rfq-vault/build/RfqVault/BuildInfo.yaml
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/address.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/ascii.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/bcs.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/bit_vector.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/bool.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/debug.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/fixed_point32.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/hash.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/internal.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/macros.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/option.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/string.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/type_name.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/u128.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/u16.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/u256.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/u32.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/u64.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/u8.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/uq32_32.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/uq64_64.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/MoveStdlib/vector.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/accumulator.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/accumulator_metadata.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/accumulator_settlement.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/address.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/address_alias.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/authenticator_state.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/bag.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/balance.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/bcs.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/bls12381.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/borrow.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/clock.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/coin.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/coin_registry.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/config.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/deny_list.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/derived_object.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/display.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/display_registry.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/dynamic_field.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/dynamic_object_field.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/ecdsa_k1.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/ecdsa_r1.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/ecvrf.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/ed25519.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/event.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/funds_accumulator.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/groth16.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/group_ops.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/hash.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/hex.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/hmac.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/kiosk.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/kiosk_extension.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/linked_table.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/math.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/nitro_attestation.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/object.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/object_bag.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/object_table.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/package.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/party.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/pay.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/poseidon.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/priority_queue.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/protocol_config.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/prover.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/random.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/rangeproofs.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/ristretto255.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/sui.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/table.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/table_vec.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/token.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/transfer.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/transfer_policy.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/tx_context.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/types.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/url.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/vdf.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/vec_map.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/vec_set.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/versioned.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/zklogin_verified_id.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/dependencies/Sui/zklogin_verified_issuer.mv
  • sui/rfq-vault/build/RfqVault/bytecode_modules/vault.mv
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/address.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/address.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/ascii.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/ascii.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/bcs.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/bcs.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/bit_vector.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/bit_vector.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/bool.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/bool.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/debug.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/debug.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/fixed_point32.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/fixed_point32.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/hash.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/hash.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/internal.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/internal.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/macros.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/macros.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/option.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/option.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/string.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/string.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/type_name.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/type_name.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u128.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u128.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u16.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u16.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u256.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u256.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u32.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u32.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u64.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u64.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u8.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/u8.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/uq32_32.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/uq32_32.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/uq64_64.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/uq64_64.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/vector.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/MoveStdlib/vector.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/accumulator.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/accumulator.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/accumulator_metadata.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/accumulator_metadata.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/accumulator_settlement.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/accumulator_settlement.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/address.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/address.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/address_alias.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/address_alias.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/authenticator_state.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/authenticator_state.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/bag.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/bag.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/balance.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/balance.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/bcs.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/bcs.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/bls12381.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/bls12381.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/borrow.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/borrow.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/clock.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/clock.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/coin.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/coin.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/coin_registry.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/coin_registry.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/config.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/config.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/deny_list.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/deny_list.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/derived_object.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/derived_object.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/display.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/display.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/display_registry.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/display_registry.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/dynamic_field.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/dynamic_field.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/dynamic_object_field.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/dynamic_object_field.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ecdsa_k1.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ecdsa_k1.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ecdsa_r1.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ecdsa_r1.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ecvrf.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ecvrf.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ed25519.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ed25519.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/event.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/event.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/funds_accumulator.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/funds_accumulator.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/groth16.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/groth16.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/group_ops.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/group_ops.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/hash.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/hash.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/hex.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/hex.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/hmac.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/hmac.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/kiosk.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/kiosk.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/kiosk_extension.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/kiosk_extension.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/linked_table.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/linked_table.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/math.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/math.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/nitro_attestation.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/nitro_attestation.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/object.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/object.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/object_bag.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/object_bag.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/object_table.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/object_table.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/package.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/package.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/party.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/party.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/pay.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/pay.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/poseidon.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/poseidon.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/priority_queue.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/priority_queue.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/protocol_config.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/protocol_config.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/prover.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/prover.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/random.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/random.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/rangeproofs.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/rangeproofs.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ristretto255.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/ristretto255.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/sui.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/sui.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/table.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/table.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/table_vec.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/table_vec.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/token.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/token.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/transfer.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/transfer.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/transfer_policy.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/transfer_policy.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/tx_context.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/tx_context.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/types.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/types.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/url.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/url.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/vdf.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/vdf.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/vec_map.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/vec_map.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/vec_set.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/vec_set.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/versioned.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/versioned.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/zklogin_verified_id.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/zklogin_verified_id.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/zklogin_verified_issuer.json
  • sui/rfq-vault/build/RfqVault/debug_info/dependencies/Sui/zklogin_verified_issuer.mvd
  • sui/rfq-vault/build/RfqVault/debug_info/vault.json
  • sui/rfq-vault/build/RfqVault/debug_info/vault.mvd
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/address.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/ascii.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/bcs.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/bit_vector.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/bool.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/debug.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/fixed_point32.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/hash.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/internal.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/macros.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/option.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/string.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/type_name.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/u128.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/u16.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/u256.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/u32.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/u64.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/u8.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/uq32_32.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/uq64_64.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/MoveStdlib/vector.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/accumulator.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/accumulator_metadata.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/accumulator_settlement.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/address.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/address_alias.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/authenticator_state.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/bag.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/balance.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/bcs.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/bls12381.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/borrow.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/clock.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/coin.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/coin_registry.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/config.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/deny_list.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/derived_object.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/display.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/display_registry.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/dynamic_field.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/dynamic_object_field.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/ecdsa_k1.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/ecdsa_r1.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/ecvrf.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/ed25519.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/event.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/funds_accumulator.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/groth16.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/group_ops.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/hash.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/hex.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/hmac.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/kiosk.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/kiosk_extension.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/linked_table.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/math.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/nitro_attestation.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/object.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/object_bag.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/object_table.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/package.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/party.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/pay.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/poseidon.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/priority_queue.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/protocol_config.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/prover.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/random.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/rangeproofs.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/ristretto255.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/sui.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/table.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/table_vec.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/token.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/transfer.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/transfer_policy.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/tx_context.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/types.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/url.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/vdf.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/vec_map.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/vec_set.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/versioned.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/zklogin_verified_id.move
  • sui/rfq-vault/build/RfqVault/sources/dependencies/Sui/zklogin_verified_issuer.move
  • sui/rfq-vault/build/RfqVault/sources/vault.move
  • sui/rfq-vault/sources/vault.move
  • sui/rfq-vault/tests/vault_tests.move

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

New Sui Move package rfq_vault with a Vault module for owner-controlled custody, per-quote accounting, solver-signed fulfil/refund flows, test coverage, and Sui deployment tooling.

RFQ Vault implementation

Layer / File(s) Summary
Package manifest, Vault object, and message structs
sui/rfq-vault/Move.toml, sui/rfq-vault/sources/vault.move
Defines the package metadata, the Vault shared object, and the structs used for emitted events and signed settlement payloads.
Vault creation, deposits, and quote settlement
sui/rfq-vault/sources/vault.move
create_vault initializes the vault, deposit stores typed coins, fulfil verifies solver signatures before paying out, mark_for_refund records signed refund eligibility, and refund pays out signed refunds.
Owner controls, read helpers, and signing internals
sui/rfq-vault/sources/vault.move
Adds owner-gated funding, rescue, pause, unpause, solver pubkey updates, ownership transfer, public accessors, message builders, signature verification, balance management, validation, and token-type derivation.
Vault test suite and deterministic helpers
sui/rfq-vault/tests/vault_tests.move
Covers deposits, fulfil/refund replay rules, refund marking, pause gating, owner-only actions, quote-id validation, vault creation, and deterministic setup/signing helpers.
Deployment config, npm scripts, and ignore rule
scripts/sui/rfqVaultDeploymentConfig.ts, package.json, .gitignore
Adds RFQ vault deployment constants, npm scripts for build/test/deploy, and an ignore rule for .cursor/rules/.
Sui deployment workflow
scripts/sui/deployRfqVault.ts
Builds and deploys the package with Sui CLI commands, validates inputs, persists deployment addresses, and exits on uncaught errors.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

A vault took shape in Move tonight,
With signed quotes guarded left and right.
One key, one quote, one path to pay,
Then tests and scripts lit up the way.
The deployer marched, the chain replied —
RFQ coins now have a place toाइड.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding the Sui RFQ vault and its tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sui-rfq

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sui/rfq-vault/Move.toml (1)

1-7: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Pin the Sui CLI/toolchain for sui/rfq-vault
Move.lock only fixes framework sources; it does not pin the compiler version. This package depends on implicit framework deps, so older Sui releases can still fail to resolve std/sui.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sui/rfq-vault/Move.toml` around lines 1 - 7, The RfqVault package is only
pinning framework sources indirectly, so the Sui CLI/compiler version can still
drift and break resolution of implicit deps like std and sui. Update the
Move.toml for RfqVault to explicitly pin the Sui toolchain/compiler version
using the package’s standard version pinning mechanism, and keep the existing
package/address configuration intact so builds use a consistent Sui release
regardless of local CLI version.
🧹 Nitpick comments (2)
sui/rfq-vault/sources/vault.move (2)

209-219: 🔒 Security & Privacy | 🔵 Trivial

Emit events for security-sensitive owner operations.

rescue moves custodied funds out, and set_solver_pubkey/pause/unpause/transfer_ownership change the trust and availability posture, yet none emit events. For a fund-holding vault this should emit structured events so off-chain systems can monitor and alert on owner actions (especially rescue withdrawals and solver-key rotations).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sui/rfq-vault/sources/vault.move` around lines 209 - 219, The owner-sensitive
Vault operations currently mutate custody and control state without any event
emission, so update the relevant entry functions in Vault to publish structured
events for monitoring. Add event emission to rescue, set_solver_pubkey, pause,
unpause, and transfer_ownership using the existing Vault event patterns/symbols
in the module, and include enough fields to identify the action, actor, receiver
or new owner, amount, and key change details so off-chain alerting can track
withdrawals and governance changes.

132-156: 🔒 Security & Privacy | 🔵 Trivial

Solver key is the sole authority over all pooled funds; nonce is signed but unenforced.

Two things to lock down on the settlement signing model (applies to refund and mark_for_refund too):

  1. fulfil/refund take an arbitrary signed amount and receiver and withdraw from the per-token pooled Balance. There is no per-quote escrow and no global cap, so a leaked/compromised solver key drains the entire balance for any token type. This is inherent to the design — ensure the solver key uses HSM/threshold custody, support rotation via set_solver_pubkey, and add off-chain monitoring/alerting on Fulfilled/Refunded volume.

  2. nonce is part of the signed SettlementMessage but is never checked on-chain; replay protection comes solely from quote_used. Confirm this is intended and not a missing nonce check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sui/rfq-vault/sources/vault.move` around lines 132 - 156, The settlement flow
in fulfil, refund, and mark_for_refund relies on a signed nonce but never
enforces it on-chain, so replay protection currently depends only on quote_id
usage. Update the Vault settlement path to explicitly validate and record nonce
reuse alongside quote_id, or remove nonce from SettlementMessage if it is not
meant to be an on-chain guard; make the behavior consistent across fulfil,
refund, and mark_for_refund using the existing verify_signature and
mark_quote_id flow as the reference points.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sui/rfq-vault/tests/vault_tests.move`:
- Around line 52-226: Add negative coverage for the settlement auth paths in the
vault tests by extending the existing settlement helpers and test cases around
fulfil, refund, and mark_for_refund. Create tests that call vault::fulfil,
vault::refund, and vault::mark_for_refund with signatures that are either signed
by the wrong keypair or otherwise malformed, and assert they abort instead of
accepting the request. Reuse the existing helpers like sign_fulfil, sign_refund,
sign_mark_for_refund, and the Vault/shared setup in vault_tests.move so the
failure cases sit alongside the current positive replay/consumption checks.
- Around line 321-355: The admin-path coverage in
owner_can_rescue_and_update_admin_state only checks the happy path for
set_solver_pubkey, pause, unpause, and transfer_ownership, so add negative tests
proving a non-owner is rejected by each of those Vault entrypoints. Use the
existing non_owner_cannot_rescue pattern as a guide, and add separate
expected_failure cases around vault::set_solver_pubkey, vault::pause,
vault::unpause, and vault::transfer_ownership to ensure the owner-only guard in
Vault is enforced consistently.

---

Outside diff comments:
In `@sui/rfq-vault/Move.toml`:
- Around line 1-7: The RfqVault package is only pinning framework sources
indirectly, so the Sui CLI/compiler version can still drift and break resolution
of implicit deps like std and sui. Update the Move.toml for RfqVault to
explicitly pin the Sui toolchain/compiler version using the package’s standard
version pinning mechanism, and keep the existing package/address configuration
intact so builds use a consistent Sui release regardless of local CLI version.

---

Nitpick comments:
In `@sui/rfq-vault/sources/vault.move`:
- Around line 209-219: The owner-sensitive Vault operations currently mutate
custody and control state without any event emission, so update the relevant
entry functions in Vault to publish structured events for monitoring. Add event
emission to rescue, set_solver_pubkey, pause, unpause, and transfer_ownership
using the existing Vault event patterns/symbols in the module, and include
enough fields to identify the action, actor, receiver or new owner, amount, and
key change details so off-chain alerting can track withdrawals and governance
changes.
- Around line 132-156: The settlement flow in fulfil, refund, and
mark_for_refund relies on a signed nonce but never enforces it on-chain, so
replay protection currently depends only on quote_id usage. Update the Vault
settlement path to explicitly validate and record nonce reuse alongside
quote_id, or remove nonce from SettlementMessage if it is not meant to be an
on-chain guard; make the behavior consistent across fulfil, refund, and
mark_for_refund using the existing verify_signature and mark_quote_id flow as
the reference points.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a472848a-c664-4d83-b1a8-39ed798f0a3a

📥 Commits

Reviewing files that changed from the base of the PR and between 78519c8 and 97eeb10.

⛔ Files ignored due to path filters (1)
  • sui/rfq-vault/Move.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • sui/rfq-vault/Move.toml
  • sui/rfq-vault/sources/vault.move
  • sui/rfq-vault/tests/vault_tests.move

Comment on lines +52 to +226
#[test]
fun fulfil_with_solver_signature_releases_funds_and_blocks_replay() {
let mut scenario = setup_funded_vault(2 * AMOUNT);
scenario.next_tx(OTHER);
{
let mut vault = scenario.take_shared<Vault>();
let quote_id = quote_id(2);
let nonce = 7;
let signature = sign_fulfil<VAULT_TESTS>(&vault, copy quote_id, nonce, AMOUNT, RECEIVER);

vault::fulfil<VAULT_TESTS>(
&mut vault,
copy quote_id,
nonce,
AMOUNT,
RECEIVER,
signature,
scenario.ctx(),
);

assert!(vault::vault_balance<VAULT_TESTS>(&vault) == AMOUNT);
assert!(vault::is_quote_used(&vault, copy quote_id));
test_scenario::return_shared(vault);
};
scenario.next_tx(RECEIVER);
{
let coin = scenario.take_from_address<Coin<VAULT_TESTS>>(RECEIVER);
assert!(coin.value() == AMOUNT);
transfer::public_transfer(coin, OWNER);
};
scenario.end();
}

#[test, expected_failure(abort_code = vault::E_INVALID_QUOTE_ID)]
fun fulfil_replay_aborts() {
let mut scenario = setup_funded_vault(2 * AMOUNT);
scenario.next_tx(OTHER);
{
let mut vault = scenario.take_shared<Vault>();
let quote_id = quote_id(3);
let signature = sign_fulfil<VAULT_TESTS>(&vault, copy quote_id, 8, AMOUNT, RECEIVER);

vault::fulfil<VAULT_TESTS>(
&mut vault,
copy quote_id,
8,
AMOUNT,
RECEIVER,
copy signature,
scenario.ctx(),
);
vault::fulfil<VAULT_TESTS>(
&mut vault,
quote_id,
8,
AMOUNT,
RECEIVER,
signature,
scenario.ctx(),
);

test_scenario::return_shared(vault);
};
scenario.end();
}

#[test, expected_failure(abort_code = vault::E_INVALID_QUOTE_ID)]
fun fulfil_after_refund_aborts() {
let mut scenario = setup_funded_vault(2 * AMOUNT);
scenario.next_tx(OTHER);
{
let mut vault = scenario.take_shared<Vault>();
let quote_id = quote_id(4);
let refund_signature = sign_refund<VAULT_TESTS>(&vault, copy quote_id, 9, AMOUNT, RECEIVER);
vault::refund<VAULT_TESTS>(
&mut vault,
copy quote_id,
9,
AMOUNT,
RECEIVER,
refund_signature,
scenario.ctx(),
);

let fulfil_signature = sign_fulfil<VAULT_TESTS>(&vault, copy quote_id, 10, AMOUNT, RECEIVER);
vault::fulfil<VAULT_TESTS>(
&mut vault,
quote_id,
10,
AMOUNT,
RECEIVER,
fulfil_signature,
scenario.ctx(),
);

test_scenario::return_shared(vault);
};
scenario.end();
}

#[test]
fun mark_for_refund_consumes_quote_id_and_blocks_refund() {
let mut scenario = setup_funded_vault(AMOUNT);
scenario.next_tx(OTHER);
{
let mut vault = scenario.take_shared<Vault>();
let quote_id = quote_id(5);
let signature = sign_mark_for_refund(&vault, copy quote_id, 11);

vault::mark_for_refund(&mut vault, copy quote_id, 11, signature);

assert!(vault::is_quote_used(&vault, copy quote_id));
assert!(vault::is_marked_for_refund(&vault, copy quote_id));
test_scenario::return_shared(vault);
};
scenario.end();
}

#[test, expected_failure(abort_code = vault::E_INVALID_QUOTE_ID)]
fun refund_after_mark_for_refund_aborts() {
let mut scenario = setup_funded_vault(AMOUNT);
scenario.next_tx(OTHER);
{
let mut vault = scenario.take_shared<Vault>();
let quote_id = quote_id(6);
let mark_signature = sign_mark_for_refund(&vault, copy quote_id, 12);
vault::mark_for_refund(&mut vault, copy quote_id, 12, mark_signature);

let refund_signature = sign_refund<VAULT_TESTS>(&vault, copy quote_id, 13, AMOUNT, RECEIVER);
vault::refund<VAULT_TESTS>(
&mut vault,
quote_id,
13,
AMOUNT,
RECEIVER,
refund_signature,
scenario.ctx(),
);

test_scenario::return_shared(vault);
};
scenario.end();
}

#[test]
fun refund_with_solver_signature_releases_funds() {
let mut scenario = setup_funded_vault(AMOUNT);
scenario.next_tx(OTHER);
{
let mut vault = scenario.take_shared<Vault>();
let quote_id = quote_id(7);
let signature = sign_refund<VAULT_TESTS>(&vault, copy quote_id, 14, AMOUNT, RECEIVER);

vault::refund<VAULT_TESTS>(
&mut vault,
copy quote_id,
14,
AMOUNT,
RECEIVER,
signature,
scenario.ctx(),
);

assert!(vault::vault_balance<VAULT_TESTS>(&vault) == 0);
assert!(vault::is_quote_used(&vault, quote_id));
test_scenario::return_shared(vault);
};
scenario.next_tx(RECEIVER);
{
let coin = scenario.take_from_address<Coin<VAULT_TESTS>>(RECEIVER);
assert!(coin.value() == AMOUNT);
transfer::public_transfer(coin, OWNER);
};
scenario.end();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Add invalid-signature coverage for the settlement paths.

These tests only use signatures produced by solver_keypair(). The suite never proves that fulfil, refund, or mark_for_refund reject a wrong key or malformed signature, so a broken verify_signature path would still leave the core auth boundary green.

Also applies to: 439-476

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sui/rfq-vault/tests/vault_tests.move` around lines 52 - 226, Add negative
coverage for the settlement auth paths in the vault tests by extending the
existing settlement helpers and test cases around fulfil, refund, and
mark_for_refund. Create tests that call vault::fulfil, vault::refund, and
vault::mark_for_refund with signatures that are either signed by the wrong
keypair or otherwise malformed, and assert they abort instead of accepting the
request. Reuse the existing helpers like sign_fulfil, sign_refund,
sign_mark_for_refund, and the Vault/shared setup in vault_tests.move so the
failure cases sit alongside the current positive replay/consumption checks.

Comment on lines +321 to +355
#[test]
fun owner_can_rescue_and_update_admin_state() {
let mut scenario = setup_funded_vault(AMOUNT);
scenario.next_tx(OWNER);
{
let mut vault = scenario.take_shared<Vault>();
let new_keypair = ecdsa_k1::secp256k1_keypair_from_seed(
&b"Another random 32 byte test seed",
);

vault::set_solver_pubkey(&mut vault, *new_keypair.public_key(), scenario.ctx());
vault::pause(&mut vault, scenario.ctx());
assert!(vault::is_paused(&vault));
vault::unpause(&mut vault, scenario.ctx());
assert!(!vault::is_paused(&vault));
vault::rescue<VAULT_TESTS>(&mut vault, AMOUNT, RECEIVER, scenario.ctx());
vault::transfer_ownership(&mut vault, OTHER, scenario.ctx());

assert!(vault::owner(&vault) == OTHER);
assert!(vault::vault_balance<VAULT_TESTS>(&vault) == 0);
test_scenario::return_shared(vault);
};
scenario.end();
}

#[test, expected_failure(abort_code = vault::E_ONLY_OWNER)]
fun non_owner_cannot_rescue() {
let mut scenario = setup_funded_vault(AMOUNT);
scenario.next_tx(OTHER);
{
let mut vault = scenario.take_shared<Vault>();
vault::rescue<VAULT_TESTS>(&mut vault, AMOUNT, RECEIVER, scenario.ctx());
test_scenario::return_shared(vault);
};
scenario.end();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Add non-owner abort cases for the other admin entrypoints.

This only proves the happy path for set_solver_pubkey, pause, unpause, and transfer_ownership, while rescue is the only admin path with a negative auth test. A missing owner check on any of those other entrypoints would not be caught here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sui/rfq-vault/tests/vault_tests.move` around lines 321 - 355, The admin-path
coverage in owner_can_rescue_and_update_admin_state only checks the happy path
for set_solver_pubkey, pause, unpause, and transfer_ownership, so add negative
tests proving a non-owner is rejected by each of those Vault entrypoints. Use
the existing non_owner_cannot_rescue pattern as a guide, and add separate
expected_failure cases around vault::set_solver_pubkey, vault::pause,
vault::unpause, and vault::transfer_ownership to ensure the owner-only guard in
Vault is enforced consistently.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
scripts/sui/deployRfqVault.ts (1)

64-94: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Read deployment overrides from process.env.

The resolver passes the checked-in constants directly to requireConfig, so setting SUI_RFQ_VAULT_* environment variables has no effect and the blank defaults still fail. This should resolve env first, then fall back to the config constants.

Proposed fix
 function requireConfig(name: string, value: string): string {
   const trimmed = value.trim();
   if (!trimmed) {
@@
 
   return trimmed;
 }
+
+function deploymentValue(name: string, fallback: string): string {
+  return requireConfig(name, process.env[name] ?? fallback);
+}
 
 function resolveDeploymentConfig(): DeploymentConfig {
   const config = {
-    networkAlias: requireConfig(
+    networkAlias: deploymentValue(
       'SUI_RFQ_VAULT_NETWORK_ALIAS',
       SUI_RFQ_VAULT_NETWORK_ALIAS,
     ),
-    rpcUrl: requireConfig('SUI_RFQ_VAULT_RPC_URL', SUI_RFQ_VAULT_RPC_URL),
-    ownerAddress: requireConfig(
+    rpcUrl: deploymentValue('SUI_RFQ_VAULT_RPC_URL', SUI_RFQ_VAULT_RPC_URL),
+    ownerAddress: deploymentValue(
       'SUI_RFQ_VAULT_OWNER_ADDRESS',
       SUI_RFQ_VAULT_OWNER_ADDRESS,
     ),
-    solverPublicKey: requireConfig(
+    solverPublicKey: deploymentValue(
       'SUI_RFQ_VAULT_SOLVER_PUBLIC_KEY',
       SUI_RFQ_VAULT_SOLVER_PUBLIC_KEY,
     ),
-    domain: requireConfig('SUI_RFQ_VAULT_DOMAIN', SUI_RFQ_VAULT_DOMAIN),
-    gasBudget: requireConfig(
+    domain: deploymentValue('SUI_RFQ_VAULT_DOMAIN', SUI_RFQ_VAULT_DOMAIN),
+    gasBudget: deploymentValue(
       'SUI_RFQ_VAULT_GAS_BUDGET',
       SUI_RFQ_VAULT_GAS_BUDGET,
     ),

As per path instructions, “Will another developer easily understand and modify this in 6 months?”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sui/deployRfqVault.ts` around lines 64 - 94, The deployment config
resolver is using the checked-in SUI_RFQ_VAULT_* constants directly, so
environment overrides are ignored. Update resolveDeploymentConfig to read each
value from process.env first and fall back to the imported config constants only
when the env var is unset, while keeping requireConfig as the shared validation
step. Use the existing requireConfig and resolveDeploymentConfig symbols to wire
the env lookup for all fields consistently.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/sui/deployRfqVault.ts`:
- Around line 241-242: Namespace the Sui deployment output by network alias so
`deploymentsPath` no longer points all Sui deployments to the same
`deployments/<stage>/addresses/sui.json` file. Update the `deploymentsPath`
helper and the call sites in `deployRfqVault.ts` to include the Sui network
alias in the path or key namespace, matching the per-network persistence pattern
used by the RFQ vault executor helper, so separate aliases do not overwrite each
other’s package/vault IDs.
- Around line 383-410: The deployment flow in deployRfqVault.ts persists state
too late: the optional verify-source step runs before persistDeployment, so a
verification failure leaves the successful publish/create_vault results
unrecorded. Move the persistDeployment call to immediately after
createVaultResult is available, before the config.verifySource block, and keep
using the existing packageId, vaultId, upgradeCapId, and digest fields from
publishResult/createVaultResult. Then run runSui for source verification after
the IDs have already been saved so reruns don’t create duplicate deployments.
- Around line 296-310: The key import in deployRfqVault.ts passes
deployer.secret directly to runSui as a command-line argument, which exposes it
in argv. Update the keytool import flow to use an import path or stdin-based
mechanism that keeps the secret out of the command line, and keep the change
localized around the runSui invocation that imports into the temporary keystore
with DEPLOYER_ALIAS.

---

Nitpick comments:
In `@scripts/sui/deployRfqVault.ts`:
- Around line 64-94: The deployment config resolver is using the checked-in
SUI_RFQ_VAULT_* constants directly, so environment overrides are ignored. Update
resolveDeploymentConfig to read each value from process.env first and fall back
to the imported config constants only when the env var is unset, while keeping
requireConfig as the shared validation step. Use the existing requireConfig and
resolveDeploymentConfig symbols to wire the env lookup for all fields
consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 450c9329-e676-484c-b937-d4ddd61e29c9

📥 Commits

Reviewing files that changed from the base of the PR and between 97eeb10 and 48f0a46.

📒 Files selected for processing (4)
  • .gitignore
  • package.json
  • scripts/sui/deployRfqVault.ts
  • scripts/sui/rfqVaultDeploymentConfig.ts
✅ Files skipped from review due to trivial changes (1)
  • .gitignore

Comment on lines +241 to +242
function deploymentsPath(stage: string): string {
return resolve(REPO_ROOT, 'deployments', stage, 'addresses', 'sui.json');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Namespace deployment records by Sui network alias.

deploymentsPath always writes fixed keys into deployments/<stage>/addresses/sui.json, so a second Sui deployment for another alias overwrites the previous package/vault IDs. This should include the network alias in the path or namespace the keys; the existing RFQ vault executor helper persists per-network address files.

Proposed fix
-function deploymentsPath(stage: string): string {
-  return resolve(REPO_ROOT, 'deployments', stage, 'addresses', 'sui.json');
+function deploymentsPath(stage: string, networkAlias: string): string {
+  return resolve(
+    REPO_ROOT,
+    'deployments',
+    stage,
+    'addresses',
+    `${networkAlias}.json`,
+  );
 }

As per path instructions, “Check for resource leaks, race conditions, and unhandled edge cases.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function deploymentsPath(stage: string): string {
return resolve(REPO_ROOT, 'deployments', stage, 'addresses', 'sui.json');
function deploymentsPath(stage: string, networkAlias: string): string {
return resolve(
REPO_ROOT,
'deployments',
stage,
'addresses',
`${networkAlias}.json`,
);
🧰 Tools
🪛 ast-grep (0.44.0)

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from 'child_process';
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sui/deployRfqVault.ts` around lines 241 - 242, Namespace the Sui
deployment output by network alias so `deploymentsPath` no longer points all Sui
deployments to the same `deployments/<stage>/addresses/sui.json` file. Update
the `deploymentsPath` helper and the call sites in `deployRfqVault.ts` to
include the Sui network alias in the path or key namespace, matching the
per-network persistence pattern used by the RFQ vault executor helper, so
separate aliases do not overwrite each other’s package/vault IDs.

Source: Path instructions

Comment on lines +296 to +310
runSui(
[
'keytool',
'import',
'--alias',
DEPLOYER_ALIAS,
'--json',
deployer.secret,
deployer.scheme,
],
{
env,
label: 'import SUI_DEPLOYER into temporary keystore',
redactions: [deployer.secret],
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify which non-argv import modes are supported by the installed Sui CLI.
sui keytool import --help

Repository: SocketDotTech/openrouter

Length of output: 203


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the deploy script and the Sui command wrapper.
git ls-files 'scripts/sui/deployRfqVault.ts' 'scripts/**' | sed -n '1,120p'

echo '--- deployRfqVault.ts outline ---'
ast-grep outline scripts/sui/deployRfqVault.ts --view expanded

echo '--- runSui references ---'
rg -n "runSui\(" scripts/sui -S

echo '--- keytool import usage ---'
rg -n "keytool import|import --alias|DEPLOYER_ALIAS|secret" scripts/sui -S

Repository: SocketDotTech/openrouter

Length of output: 8007


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the relevant section and the helper that spawns the child process.
sed -n '158,320p' scripts/sui/deployRfqVault.ts | cat -n

echo '---'
sed -n '320,420p' scripts/sui/deployRfqVault.ts | cat -n

Repository: SocketDotTech/openrouter

Length of output: 8664


🌐 Web query:

Sui CLI keytool import supports stdin file alias secret argv

💡 Result:

The sui keytool import command is used to add a new key to the Sui CLI keystore [1][2]. Regarding the specific aspects queried: 1. Stdin: The command does not natively support passing the mnemonic phrase or private key via stdin (piping). The input string must be provided as a positional argument [1][2]. 2. File: The command does not natively support importing a key directly from a file path as an argument. The mnemonic phrase or Bech32-encoded key must be provided as a string argument [1][2]. 3. Alias: The command supports an optional --alias flag to set a human-readable name for the imported key [1][3]. If no alias is provided, the CLI will automatically generate one [1][2]. A bug that caused the --alias flag to be ignored when importing via mnemonic was fixed in 2024 [4]. 4. Secret: The command accepts the secret key in two formats: as a mnemonic phrase (12, 15, 18, 21, or 24 words) or as a Bech32-encoded string (33-byte flag || private key) starting with suiprivkey [1][2]. The secret string must be enclosed in single or double quotes in the CLI to prevent shell interpretation [5]. 5. Argv: The command expects the input string (mnemonic or suiprivkey) and the key scheme (e.g., ed25519, secp256k1, or secp256r1) as positional command-line arguments, with an optional derivation path as a final positional argument [1][2]. The standard usage syntax is: sui keytool import [OPTIONS] <INPUT_STRING> <KEY_SCHEME> [DERIVATION_PATH] [2]

Citations:


Avoid passing deployer.secret on the command line.
keytool import puts the secret in argv, which exposes it to local process listings; this needs an import path that keeps the secret out of the command line.

🧰 Tools
🪛 ast-grep (0.44.0)

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from 'child_process';
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sui/deployRfqVault.ts` around lines 296 - 310, The key import in
deployRfqVault.ts passes deployer.secret directly to runSui as a command-line
argument, which exposes it in argv. Update the keytool import flow to use an
import path or stdin-based mechanism that keeps the secret out of the command
line, and keep the change localized around the runSui invocation that imports
into the temporary keystore with DEPLOYER_ALIAS.

Comment thread scripts/sui/deployRfqVault.ts Outdated
@reddyismav reddyismav closed this Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant