Skip to content

feat: Stellar soroban gas abstraction#642

Merged
NicoMolinaOZ merged 25 commits into
mainfrom
feature/stellar-soroban-gas-abstraction
Feb 9, 2026
Merged

feat: Stellar soroban gas abstraction#642
NicoMolinaOZ merged 25 commits into
mainfrom
feature/stellar-soroban-gas-abstraction

Conversation

@NicoMolinaOZ

@NicoMolinaOZ NicoMolinaOZ commented Feb 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds gas abstraction support for Stellar Soroban transactions, allowing users to pay transaction fees using tokens other than XLM.

Changes

  • Gas abstraction flow: New transaction preparation pipeline for Soroban gas-abstracted transactions
  • Soroswap integration: DEX service for token swaps to cover gas fees
  • Fee forwarder service: Handles fee forwarding logic for sponsored transactions
  • Auth entry signing: Helper tool for signing Soroban authorization entries
  • Configuration updates: New server config options for gas abstraction settings

Key Files

  • src/services/stellar_fee_forwarder/ - Fee forwarding service
  • src/services/stellar_dex/soroswap_service.rs - Soroswap DEX integration
  • src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs - Transaction preparation
  • helpers/sign_soroban_auth_entry.rs - Auth entry signing tool

Related PR:
OpenZeppelin/openzeppelin-relayer-sdk#249

Testing Process

Checklist

  • Add a reference to related issues in the PR description.
  • Add unit tests if applicable.

Note

If you are using Relayer in your stack, consider adding your team or organization to our list of Relayer Users in the Wild!

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Soroban gas abstraction support for sponsored transactions with fee forwarding capabilities
    • Integrated Soroswap DEX service for token swaps on Soroban contracts
    • Introduced fee forwarder service for handling Soroban contract authorization and invocation
    • Added tooling for signing Soroban authorization entries with Stellar-compatible keys
  • Chores

    • Added configuration support for fee forwarder and Soroswap contract addresses
    • Enhanced transaction request handling with authorization entry support

@coderabbitai

coderabbitai Bot commented Feb 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

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

This PR introduces comprehensive Soroban gas abstraction support to the Stellar relayer, enabling sponsored transactions with authorization signing, FeeForwarder contract integration for fee management, Soroswap DEX routing for token swaps, and simulation-based contract token balance retrieval.

Changes

Cohort / File(s) Summary
Manifest & Configuration
Cargo.toml, src/config/server_config.rs, src/utils/mocks.rs, src/services/mod.rs
Added sign_soroban_auth_entry example entry; extended ServerConfig with four optional Stellar address fields (fee_forwarder, soroswap_router, soroswap_factory, soroswap_native_wrapper); added stellar_fee_forwarder service module export.
Gas Abstraction Core Implementation
src/domain/relayer/stellar/gas_abstraction.rs, src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs, src/services/stellar_fee_forwarder/mod.rs
Major Soroban gas abstraction support: branching between classic and Soroban paths in quote/build flows, FeeForwarder service with authorization building, fee simulation, envelope crafting, auth entry injection, sequence management, and resource buffering for Soroban transactions.
DEX Services & Routing
src/services/stellar_dex/soroswap_service.rs, src/services/stellar_dex/stellar_dex_service.rs, src/services/stellar_dex/mod.rs, src/domain/relayer/stellar/mod.rs
New SoroswapService implementing Soroban-based DEX with quote routing, path building, i128 conversion, contract address parsing; updated DexServiceWrapper to route to Soroswap alongside OrderBook; added default router/factory address helpers for testnet/mainnet.
Signer Extensions
src/services/signer/stellar/aws_kms_signer.rs, src/services/signer/stellar/google_cloud_kms_signer.rs, src/services/signer/stellar/local_signer.rs, src/services/signer/stellar/turnkey_signer.rs
Extended all signer implementations to handle SorobanGasAbstraction TransactionInput variant alongside existing UnsignedXdr and SignedXdr paths; expanded XDR imports for Soroban types.
Transaction Handling & Validation
src/domain/transaction/stellar/stellar_relayer.rs, src/domain/transaction/stellar/stellar_transaction.rs, src/domain/transaction/stellar/status.rs, src/domain/transaction/stellar/submit.rs, src/domain/transaction/stellar/test_helpers.rs
Updated signer field visibility to pub(crate); added StellarSignTrait bound requirement across generic parameters; introduced MockStellarCombinedSigner composite test mock aggregating Signer and StellarSignTrait implementations.
Transaction Models & Requests
src/models/transaction/request/stellar.rs, src/models/transaction/repository.rs, src/models/transaction/stellar/conversion.rs, src/domain/transaction/stellar/prepare/mod.rs
Added signed_auth_entry optional field to StellarTransactionRequest with validation (requires transaction_xdr, mutually exclusive with fee_bump); introduced SorobanGasAbstraction TransactionInput variant with xdr and signed_auth_entry; added soroban_gas_abstraction processing module.
RPC Response Models
src/models/rpc/stellar/mod.rs, src/models/transaction/response.rs, src/models/rpc/stellar/mod.rs
Added user_auth_entry optional field to PrepareTransactionResult with conditional serialization; updated documentation for fee_payment_strategy and transaction result variants to mention Soroban gas abstraction context.
Token & Contract Operations
src/domain/transaction/stellar/token.rs, src/domain/relayer/stellar/token_swap.rs, src/models/relayer/mod.rs
Refactored contract token balance retrieval from storage-based to simulation-based approach using provider.call_contract; added is_user_fee_payment() helper on RelayerStellarPolicy; updated token swap flow with signed_auth_entry field.
Documentation & Examples
helpers/sign_soroban_auth_entry.rs, src/models/relayer/config.rs, src/models/transaction/request/mod.rs
New example tool for signing Soroban auth entries with secret key, network detection, and unit tests for passphrase resolution; added documentation clarifying Soroban gas abstraction modes and FeeForwarder enablement conditions.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant StellarRelayer as StellarRelayer<br/>(quote_soroban_from_xdr)
    participant Provider as StellarProvider
    participant FeeForwarder as FeeForwarderService
    
    Client->>StellarRelayer: quote_sponsored_transaction(xdr, config)
    StellarRelayer->>StellarRelayer: detect_soroban_invoke_from_xdr()
    alt Soroban Detected
        StellarRelayer->>StellarRelayer: extract SorobanInvokeInfo
        StellarRelayer->>StellarRelayer: validate token & fee-forwarder
        StellarRelayer->>FeeForwarder: build_user_auth_entry_standalone()
        FeeForwarder-->>StellarRelayer: user_auth_entry
        StellarRelayer->>StellarRelayer: build_forward_args, create invoke
        StellarRelayer->>Provider: simulate_transaction_envelope()
        Provider-->>StellarRelayer: simulation result + fees
        StellarRelayer->>StellarRelayer: apply_max_fee_slippage()
        StellarRelayer->>StellarRelayer: compute token conversion
        StellarRelayer-->>Client: SponsoredTransactionQuoteResponse
    end
Loading
sequenceDiagram
    participant Client
    participant StellarRelayer as StellarRelayer<br/>(build_soroban_sponsored)
    participant FeeForwarder as FeeForwarderService
    participant Provider as StellarProvider
    participant Signer as StellarSigner
    
    Client->>StellarRelayer: build_sponsored_transaction(xdr, config)
    StellarRelayer->>StellarRelayer: detect_soroban_invoke_from_xdr()
    alt Soroban Detected
        StellarRelayer->>FeeForwarder: build_user_auth_entry_standalone()
        FeeForwarder-->>StellarRelayer: user_auth_entry
        StellarRelayer->>FeeForwarder: build_relayer_auth_entry_standalone()
        FeeForwarder-->>StellarRelayer: relayer_auth_entry
        StellarRelayer->>StellarRelayer: build_invoke_operation(auth_entries)
        StellarRelayer->>StellarRelayer: build_soroban_transaction_envelope()
        StellarRelayer->>Provider: simulate_transaction_envelope()
        Provider-->>StellarRelayer: sim_response (footprint, fees)
        StellarRelayer->>StellarRelayer: apply_simulation_to_soroban_envelope()
        StellarRelayer->>Signer: sign_xdr_transaction()
        Signer-->>StellarRelayer: signed envelope
        StellarRelayer-->>Client: SponsoredTransactionBuildResponse
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • zeljkoX
  • LuisUrrutia
  • dylankilkenny

Poem

🐰 Soroban hops with auth entries signed,
Fee forwarders forward with Soroswap aligned,
Gas abstraction flows through relayers so keen,
A sponsored-transaction dream, Stellar-Soroban seen!
🌟✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is largely incomplete. It lacks detailed information about testing, has unchecked required checklist items, and misses reference to related issues. Add testing process details, check off or complete the checklist items (add issue references and confirm unit tests are included), and fill in the summary with more comprehensive information about the changes and their implications.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Stellar soroban gas abstraction' directly and clearly describes the main feature introduced across the changeset: Soroban gas abstraction support for Stellar.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/stellar-soroban-gas-abstraction

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

@NicoMolinaOZ NicoMolinaOZ changed the title Feature/stellar soroban gas abstraction feat: Stellar soroban gas abstraction Feb 3, 2026
Comment thread helpers/sign_soroban_auth_entry.rs Fixed
Comment thread helpers/sign_soroban_auth_entry.rs Fixed
@NicoMolinaOZ
NicoMolinaOZ marked this pull request as ready for review February 3, 2026 21:13
@NicoMolinaOZ
NicoMolinaOZ requested a review from a team as a code owner February 3, 2026 21:13
@codecov

codecov Bot commented Feb 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.11458% with 456 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.74%. Comparing base (260c2b6) to head (bb64e53).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/services/stellar_fee_forwarder/mod.rs 80.94% 129 Missing ⚠️
...saction/stellar/prepare/soroban_gas_abstraction.rs 94.98% 78 Missing ⚠️
src/services/stellar_dex/soroswap_service.rs 94.73% 51 Missing ⚠️
src/domain/transaction/stellar/utils.rs 90.54% 47 Missing ⚠️
src/domain/relayer/stellar/mod.rs 0.00% 34 Missing ⚠️
...domain/transaction/stellar/prepare/unsigned_xdr.rs 94.94% 25 Missing ⚠️
src/domain/transaction/mod.rs 0.00% 23 Missing ⚠️
src/config/server_config.rs 72.46% 19 Missing ⚠️
src/models/transaction/repository.rs 57.14% 15 Missing ⚠️
src/domain/transaction/stellar/prepare/mod.rs 0.00% 14 Missing ⚠️
... and 4 more
Additional details and impacted files
Flag Coverage Δ
ai 0.27% <0.15%> (-0.01%) ⬇️
dev 91.73% <91.11%> (+0.14%) ⬆️
properties 0.02% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

@@            Coverage Diff             @@
##             main     #642      +/-   ##
==========================================
+ Coverage   91.60%   91.74%   +0.14%     
==========================================
  Files         274      278       +4     
  Lines      107708   114163    +6455     
==========================================
+ Hits        98668   104743    +6075     
- Misses       9040     9420     +380     
Files with missing lines Coverage Δ
src/constants/stellar_transaction.rs 75.00% <ø> (ø)
src/domain/relayer/stellar/gas_abstraction.rs 95.18% <ø> (+1.43%) ⬆️
src/domain/relayer/stellar/stellar_relayer.rs 98.56% <100.00%> (+<0.01%) ⬆️
src/domain/relayer/stellar/token_swap.rs 93.96% <ø> (ø)
src/domain/relayer/stellar/utils.rs 100.00% <100.00%> (ø)
src/domain/transaction/stellar/status.rs 96.77% <ø> (ø)
.../domain/transaction/stellar/stellar_transaction.rs 86.75% <ø> (ø)
src/domain/transaction/stellar/submit.rs 93.65% <ø> (ø)
src/models/relayer/config.rs 91.60% <ø> (ø)
src/models/rpc/stellar/mod.rs 96.73% <100.00%> (+0.75%) ⬆️
... and 24 more

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@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: 8

Caution

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

⚠️ Outside diff range comments (2)
src/domain/transaction/stellar/token.rs (1)

249-314: ⚠️ Potential issue | 🔴 Critical

Fix Int128 two's complement sign/range handling for simulated balances.

The current code misclassifies negative values and incorrectly rejects balances in the 2^63 to 2^64-1 range. The implementation checks hi != 0 which indiscriminately rejects both negative i128 values (hi = -1) and valid overflow cases, then casts lo as i64 to detect negatives—which fails for values ≥ 2^63 when hi == 0.

Correctly determine sign from hi using two's complement: reject when hi < 0 (negative), reject when hi > 0 (overflow), and return parts.lo directly when hi == 0 to cover the full u64 range.

🛠️ Proposed fix
-        ScVal::I128(parts) => {
-            // Check for overflow (hi should be 0 for values that fit in u64)
-            if parts.hi != 0 {
-                return Err(StellarTransactionUtilsError::BalanceTooLarge(
-                    parts.hi, parts.lo,
-                ));
-            }
-            // Check for negative balance
-            let lo_as_i64 = parts.lo as i64;
-            if lo_as_i64 < 0 {
-                return Err(StellarTransactionUtilsError::NegativeBalanceI128(parts.lo));
-            }
-            debug!(
-                "Balance for account {} on contract {}: {}",
-                account_id, contract_address, lo_as_i64
-            );
-            Ok(lo_as_i64 as u64)
-        }
+        ScVal::I128(parts) => {
+            if parts.hi < 0 {
+                return Err(StellarTransactionUtilsError::NegativeBalanceI128(parts.lo));
+            }
+            if parts.hi > 0 {
+                return Err(StellarTransactionUtilsError::BalanceTooLarge(
+                    parts.hi, parts.lo,
+                ));
+            }
+            debug!(
+                "Balance for account {} on contract {}: {}",
+                account_id, contract_address, parts.lo
+            );
+            Ok(parts.lo)
+        }
src/models/transaction/response.rs (1)

184-198: ⚠️ Potential issue | 🟡 Minor

Doc comment mentions expiration_ledger, but StellarPrepareTransactionResult doesn't expose it.

The struct only includes user_auth_entry for Soroban; expiration_ledger is used internally to compute valid_until but is not returned. Remove the inaccurate reference from the doc comment.

Doc fix
-    /// For Soroban: includes optional user_auth_entry, expiration_ledger
+    /// For Soroban: includes optional user_auth_entry
🤖 Fix all issues with AI agents
In `@helpers/sign_soroban_auth_entry.rs`:
- Around line 7-9: Update the doc example name in the file
helpers/sign_soroban_auth_entry.rs: replace the incorrect example invocation
string "sign_auth_entry" inside the code block with the actual example name
"sign_soroban_auth_entry" so the usage in the documentation matches the example
defined in Cargo.toml (ensure the code block lines showing --example ... use
"sign_soroban_auth_entry").

In `@src/domain/relayer/stellar/gas_abstraction.rs`:
- Around line 974-989: get_expiration_ledger currently does floor division so
very short validity_seconds can yield 0 ledgers added and immediate expiry;
change the math to use ceiling division of validity_seconds by
LEDGER_TIME_SECONDS and ensure at least 1 ledger is added, then perform a
saturating/clamped addition to current_ledger.sequence so it cannot overflow
u32. Update the computation that sets ledgers_to_add (referencing
LEDGER_TIME_SECONDS and get_expiration_ledger) to: compute ((validity_seconds +
LEDGER_TIME_SECONDS - 1) / LEDGER_TIME_SECONDS).max(1), do the addition in wider
integer space if needed, and clamp/saturate the final result into u32 (or use
u32::MAX on overflow) before returning.
- Around line 676-689: The build path is missing the Soroban contract-address
validation that quote performs: add the same validation for params.fee_token in
the build flow (where fee_forwarder and params.transaction_xdr are handled) so
invalid fee_token values return a RelayerError::ValidationError with a clear
message; reuse the same validation routine/logic used by quote (the code that
verifies fee_token is a Soroban contract address) and apply it to
params.fee_token before proceeding to construct the transaction.

In `@src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs`:
- Around line 25-44: The doc comment for the function soroban_gas_abstraction.rs
describes steps that don't match the implementation (it claims the relayer
signer signs an auth entry and that the signer is used), but the code does not
use the _signer parameter; update the top-level doc comment for the function
(the numbered steps) to remove or revise steps about signing with `_signer`,
reflect that the relayer's authorization entry is not signed in-function (or is
expected pre-signed), and ensure the list matches the actual behavior: parse
XDR, deserialize user signed auth entry, inject auth entries, re-simulate for
footprint, update sorobanData and sequence, and return prepared transaction
data; reference the function name and the `_signer` parameter so reviewers can
find the change.
- Around line 254-263: The apply_resource_buffer function currently multiplies
u32 fields and casts back to u32, which can silently truncate on overflow;
change it to perform the scaling in u64 using a BUFFER_MULTIPLIER: u64 constant,
use saturating_mul on the u64 value, divide by 100, then clamp the result to
u32::MAX before casting back to u32; apply this safe scaler to
resources.instructions, resources.disk_read_bytes, and resources.write_bytes
(referencing apply_resource_buffer and SorobanResources) so results never wrap
or truncate.

In `@src/services/signer/stellar/local_signer.rs`:
- Around line 34-38: The XDR import list in local_signer.rs includes unused
types; remove the unused symbols HashIdPreimage,
HashIdPreimageSorobanAuthorization, ScBytes, ScMap, ScMapEntry, ScSymbol, ScVal,
ScVec, SorobanAddressCredentials, SorobanAuthorizationEntry, SorobanCredentials,
and VecM from the use/import statement so only actually-used types like
DecoratedSignature, Hash, Limits, ReadXdr, Signature, SignatureHint,
Transaction, TransactionEnvelope, TransactionSignaturePayload,
TransactionSignaturePayloadTaggedTransaction, Uint256, and WriteXdr remain;
after editing the import list, run cargo check/build to ensure there are no
missing references and adjust any remaining references if they were accidentally
removed.

In `@src/services/stellar_dex/soroswap_service.rs`:
- Around line 384-422: In prepare_swap_transaction, do not return an empty
placeholder XDR; instead fail fast by returning an Err indicating swap
transaction construction is unimplemented (e.g., use a NotImplemented or
equivalent variant on StellarDexServiceError with a clear message like "Soroswap
swap transaction build not implemented") from the function (replace the
placeholder_xdr Ok branch), so callers receive an explicit error rather than an
invalid empty XDR; reference prepare_swap_transaction and StellarDexServiceError
when making the change.

In `@src/services/stellar_fee_forwarder/mod.rs`:
- Around line 609-616: The test function name test_parse_account_address_valid
is misleading because it passes an invalid address to
FeeForwarderService::<StellarProvider>::parse_account_address and expects Err;
rename the test to test_parse_account_address_invalid_format (or alternatively
supply a real valid G-address like
"GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF" and change the
assertion to is_ok()) so the test name matches the asserted behavior; update
only the function name or the input/assertion accordingly.
🧹 Nitpick comments (10)
helpers/sign_soroban_auth_entry.rs (1)

176-177: Minor: Comment numbering is inconsistent.

The comments jump from step 8 (line 168) to step 10 (line 176), skipping step 9.

📝 Proposed fix
-    // 10. Create the signature ScVal (Vec containing a Map with public_key and signature)
+    // 9. Create the signature ScVal (Vec containing a Map with public_key and signature)

And similarly update subsequent step numbers (10 → 10, 11 → 10, 12 → 11).

src/services/stellar_fee_forwarder/mod.rs (6)

17-24: Move std::time imports to file header.

SystemTime and UNIX_EPOCH are imported inside function bodies at lines 184, 243, and 515. Per coding guidelines, prefer header imports over function-level imports.

Suggested fix
 use crate::services::provider::StellarProviderTrait;
 use soroban_rs::xdr::{
     ContractId, Hash, Int128Parts, InvokeContractArgs, Limits, Operation, OperationBody, ScAddress,
     ScSymbol, ScVal, ScVec, SorobanAddressCredentials, SorobanAuthorizationEntry,
     SorobanAuthorizedFunction, SorobanAuthorizedInvocation, SorobanCredentials, VecM, WriteXdr,
 };
 use std::sync::Arc;
+use std::time::{SystemTime, UNIX_EPOCH};
 use thiserror::Error;

Then remove the use std::time::{SystemTime, UNIX_EPOCH}; statements from lines 184, 243, and 515.


77-86: Consider deriving Debug for FeeForwarderService.

Adding #[derive(Debug)] would help with debugging and logging, consistent with coding guidelines recommending implementing common traits where appropriate.


183-189: Consolidate nonce generation to avoid duplication and fragile differentiation.

Nonce generation logic is repeated three times (lines 183-189, 241-247, 514-520). The relayer nonce adds +1 to differentiate from user nonce, but this is fragile—if these methods are called at different times, nonces could collide or be inverted.

Consider extracting a single generate_nonce helper that accepts an optional offset or salt parameter, or use a more robust differentiation approach (e.g., include a type discriminator in the nonce computation).

Suggested approach
/// Generate a unique nonce for authorization entries.
/// Uses nanosecond timestamp with an optional salt for differentiation.
fn generate_nonce_with_salt(salt: u64) -> i64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map(|d| (d.as_nanos().wrapping_add(salt as u128)) as i64)
        .unwrap_or(salt as i64)
}

Then use generate_nonce_with_salt(0) for user and generate_nonce_with_salt(1) for relayer consistently.

Also applies to: 241-247, 510-520


299-302: Remove unused _fee_forwarder_address parameter.

This parameter is not used in the function body. If it's intended for future use, consider adding a TODO comment or removing it until needed.


371-396: Consider extracting shared utilities to reduce duplication.

parse_contract_address and i128_to_scval are nearly identical to implementations in soroswap_service.rs (lines 60-68 and 116-120). These could be extracted to a shared Soroban utilities module, with error conversion handled at call sites.

Suggested approach

Create a shared module (e.g., src/services/stellar_utils.rs) with generic versions:

pub fn parse_contract_address(address: &str) -> Result<ScAddress, String> {
    let contract = stellar_strkey::Contract::from_string(address)
        .map_err(|e| format!("Invalid contract '{address}': {e}"))?;
    Ok(ScAddress::Contract(ContractId(Hash(contract.0))))
}

pub fn i128_to_scval(amount: i128) -> ScVal {
    let hi = (amount >> 64) as i64;
    let lo = amount as u64;
    ScVal::I128(Int128Parts { hi, lo })
}

Then each service wraps the error appropriately.


419-508: build_user_auth_entry duplicates build_user_auth_entry_standalone logic.

The instance method shares ~80% of its code with the standalone version. Consider having build_user_auth_entry delegate to build_user_auth_entry_standalone:

Suggested refactor
 pub fn build_user_auth_entry(
     &self,
     params: &FeeForwarderParams,
     requires_target_auth: bool,
 ) -> Result<SorobanAuthorizationEntry, FeeForwarderError> {
-    let fee_forwarder_addr = Self::parse_contract_address(&self.fee_forwarder_address)?;
-    // ... ~80 lines of duplicated logic ...
+    Self::build_user_auth_entry_standalone(
+        &self.fee_forwarder_address,
+        params,
+        requires_target_auth,
+    )
 }
src/services/signer/stellar/aws_kms_signer.rs (1)

20-23: Same observation: verify usage of new XDR imports.

Same expanded imports as local_signer.rs. These types don't appear to be used in the visible changed code. If they're for future use, consider adding them when actually needed to keep imports clean.

src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs (1)

176-197: Consider failing fast when auth entries are missing.
Right now the code proceeds even with a single/empty auth list; surfacing a ValidationError earlier will produce clearer failures.

Possible guard
-    let mut auth_entries: Vec<SorobanAuthorizationEntry> = invoke_op.auth.to_vec();
-
-    if auth_entries.is_empty() {
-        // If there are no auth entries, just add the user's signed one
-        auth_entries.push(signed_user_auth);
-    } else {
-        // Replace the first auth entry (user's) with the signed version
-        auth_entries[0] = signed_user_auth;
-
-        // Convert the relayer's auth entry (second entry) to use SourceAccount credentials.
-        // Since the relayer is the transaction source account, the transaction signature
-        // already authorizes this entry - no separate auth entry signature is needed.
-        if auth_entries.len() > 1 {
-            let relayer_auth = &auth_entries[1];
-            let source_account_auth = SorobanAuthorizationEntry {
-                credentials: SorobanCredentials::SourceAccount,
-                root_invocation: relayer_auth.root_invocation.clone(),
-            };
-            auth_entries[1] = source_account_auth;
-            debug!("Converted relayer auth entry to SourceAccount credentials");
-        }
-    }
+    let mut auth_entries: Vec<SorobanAuthorizationEntry> = invoke_op.auth.to_vec();
+    if auth_entries.len() < 2 {
+        return Err(TransactionError::ValidationError(
+            "Expected at least two authorization entries".to_string(),
+        ));
+    }
+
+    // Replace the first auth entry (user's) with the signed version
+    auth_entries[0] = signed_user_auth;
+
+    // Convert the relayer's auth entry (second entry) to use SourceAccount credentials.
+    // Since the relayer is the transaction source account, the transaction signature
+    // already authorizes this entry - no separate auth entry signature is needed.
+    let relayer_auth = &auth_entries[1];
+    let source_account_auth = SorobanAuthorizationEntry {
+        credentials: SorobanCredentials::SourceAccount,
+        root_invocation: relayer_auth.root_invocation.clone(),
+    };
+    auth_entries[1] = source_account_auth;
+    debug!("Converted relayer auth entry to SourceAccount credentials");
src/domain/relayer/stellar/gas_abstraction.rs (1)

6-70: Align soroban_rs imports and avoid function-level use.

The external soroban_rs::xdr import is split below local imports, and TransactionEnvelope is re-imported inside the function. Consider consolidating these at the header for consistency and to follow the Rust import guidelines.

Suggested import cleanup
-use soroban_rs::xdr::{Limits, Operation, TransactionEnvelope, WriteXdr};
+use soroban_rs::xdr::{
+    HostFunction, Limits, Operation, OperationBody, ReadXdr, ScVal, TransactionEnvelope, WriteXdr,
+};
 ...
-use soroban_rs::xdr::{HostFunction, OperationBody, ReadXdr, ScVal};
-fn detect_soroban_invoke_from_xdr(xdr: &str) -> Result<Option<SorobanInvokeInfo>, RelayerError> {
-    use soroban_rs::xdr::TransactionEnvelope;
+fn detect_soroban_invoke_from_xdr(xdr: &str) -> Result<Option<SorobanInvokeInfo>, RelayerError> {

As per coding guidelines, Order imports alphabetically and group by: std, external crates, local crates; Prefer header imports over function-level imports of dependencies.

Comment thread helpers/sign_soroban_auth_entry.rs
Comment thread src/domain/relayer/stellar/gas_abstraction.rs Outdated
Comment thread src/domain/relayer/stellar/gas_abstraction.rs Outdated
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs
Comment thread src/services/signer/stellar/local_signer.rs Outdated
Comment thread src/services/stellar_dex/soroswap_service.rs
Comment thread src/services/stellar_fee_forwarder/mod.rs
Comment thread src/config/server_config.rs Outdated
Comment thread src/domain/relayer/stellar/mod.rs Outdated

@zeljkoX zeljkoX left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Still reviewing.

Great job!

Added few comments

Comment thread src/domain/transaction/stellar/prepare/mod.rs Outdated
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs
Comment thread src/models/transaction/repository.rs
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs
Comment thread src/config/server_config.rs Outdated
Comment thread src/services/stellar_fee_forwarder/mod.rs
Comment thread src/services/stellar_dex/soroswap_service.rs Outdated
Comment thread src/services/stellar_dex/soroswap_service.rs
Comment thread src/services/stellar_dex/soroswap_service.rs Outdated
Comment thread src/domain/relayer/stellar/gas_abstraction.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds Soroban gas abstraction support for Stellar by introducing a FeeForwarder transaction flow, Soroswap-based quoting/swaps for contract tokens, and request/response + signer updates to carry and submit Soroban authorization entries.

Changes:

  • Introduces a new stellar_fee_forwarder service to build Soroban auth entries and FeeForwarder invoke operations.
  • Adds Soroswap DEX strategy and integrates it into the Stellar DEX routing layer (alongside classic orderbook).
  • Extends Stellar transaction request/handling to support Soroban gas abstraction (XDR + signed auth entry), plus new server config options and an auth-entry signing helper.

Reviewed changes

Copilot reviewed 35 out of 36 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/utils/mocks.rs Adds mock config fields for FeeForwarder/Soroswap addresses.
src/services/stellar_fee_forwarder/mod.rs New FeeForwarder service for building Soroban auth entries and invoke ops (with tests).
src/services/stellar_dex/stellar_dex_service.rs Adds Soroswap strategy wiring and expands unit tests for strategy selection/routing.
src/services/stellar_dex/soroswap_service.rs New Soroswap service for Soroban token quotes and swap-tx XDR preparation (with tests).
src/services/stellar_dex/mod.rs Exposes Soroswap module/service in the stellar_dex public API.
src/services/signer/stellar/turnkey_signer.rs Extends signer to accept Soroban gas abstraction transaction input variant.
src/services/signer/stellar/local_signer.rs Extends signer to accept Soroban gas abstraction transaction input variant; trims unused imports.
src/services/signer/stellar/google_cloud_kms_signer.rs Extends signer to accept Soroban gas abstraction transaction input variant.
src/services/signer/stellar/aws_kms_signer.rs Extends signer to accept Soroban gas abstraction transaction input variant; adds Soroban-related XDR imports.
src/services/mod.rs Exposes the new stellar_fee_forwarder service module.
src/models/transaction/stellar/conversion.rs Prevents conversion of Soroban gas abstraction XDR inputs into Transaction.
src/models/transaction/response.rs Updates response enum docs to mention Soroban support.
src/models/transaction/request/stellar.rs Adds signed_auth_entry field and validation rules for Soroban gas abstraction submissions.
src/models/transaction/request/mod.rs Updates top-level request docs to describe Soroban gas abstraction usage for Stellar.
src/models/transaction/repository.rs Adds TransactionInput::SorobanGasAbstraction and integrates request parsing/handling.
src/models/rpc/stellar/mod.rs Adds Soroban-specific optional fields to fee/prepare result schemas and clarifies request docs.
src/models/relayer/mod.rs Adjusts Stellar asset identifier validation to accept contract-address fee tokens.
src/models/relayer/config.rs Documents how fee_payment_strategy=user ties into Soroban gas abstraction configuration.
src/domain/transaction/stellar/token.rs Changes contract-token balance retrieval to call balance() via simulation instead of ledger storage reads; updates tests.
src/domain/transaction/stellar/test_helpers.rs Introduces a combined Stellar mock signer for tests needing both Signer and StellarSignTrait.
src/domain/transaction/stellar/submit.rs Updates trait bounds to require Stellar XDR signing capability.
src/domain/transaction/stellar/stellar_transaction.rs Updates trait bounds and swaps default DEX type to the multi-strategy StellarDexService.
src/domain/transaction/stellar/status.rs Updates trait bounds and test types to require Stellar XDR signing capability.
src/domain/transaction/stellar/prepare/unsigned_xdr.rs Extends swap validation for Soroswap invoke ops; applies Soroban simulation outputs into envelopes; adds tests.
src/domain/transaction/stellar/prepare/mod.rs Routes Soroban gas abstraction transaction inputs into a dedicated preparation path.
src/domain/transaction/mod.rs Builds a multi-strategy Stellar DEX service based on policy + config/default addresses.
src/domain/relayer/stellar/token_swap.rs Updates Stellar transaction requests to include the new signed_auth_entry field (None).
src/domain/relayer/stellar/stellar_relayer.rs Makes signer accessible within crate for updated transaction flows; updates tests.
src/domain/relayer/stellar/mod.rs Initializes Soroswap DEX service when configured (instead of skipping).
src/constants/stellar_transaction.rs Adds default Soroswap/FeeForwarder addresses and helper getters.
src/config/server_config.rs Adds env-driven config for FeeForwarder and Soroswap contract addresses.
openapi.json Updates API descriptions/schemas for Soroban gas abstraction-related fields.
helpers/sign_soroban_auth_entry.rs Adds an example CLI tool to sign Soroban authorization entries.
Cargo.toml Registers the sign_soroban_auth_entry example binary.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/constants/stellar_transaction.rs Outdated
Comment thread helpers/sign_soroban_auth_entry.rs
Comment thread src/domain/transaction/stellar/prepare/unsigned_xdr.rs
Comment thread helpers/sign_soroban_auth_entry.rs
Comment thread src/models/relayer/mod.rs
Comment thread openapi.json
Comment thread src/models/transaction/response.rs

@zeljkoX zeljkoX left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Great work!

Comment thread src/domain/relayer/stellar/gas_abstraction.rs Outdated
Comment thread src/domain/relayer/stellar/gas_abstraction.rs Outdated
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs Outdated
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs Outdated
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs Outdated
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs Outdated
Comment thread src/domain/transaction/stellar/prepare/soroban_gas_abstraction.rs Outdated
Comment thread src/services/stellar_dex/soroswap_service.rs
Comment thread src/services/stellar_fee_forwarder/mod.rs Outdated
Comment thread src/services/stellar_fee_forwarder/mod.rs Outdated
"Updated transaction sorobanData with simulation results, preserved fee={}",
original_fee
"Updated transaction sorobanData with simulation results, fee={}",
fee_to_set

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

weird that it does not complain here

@NicoMolinaOZ
NicoMolinaOZ merged commit 3a9b71c into main Feb 9, 2026
25 of 26 checks passed
@NicoMolinaOZ
NicoMolinaOZ deleted the feature/stellar-soroban-gas-abstraction branch February 9, 2026 16:06
@github-actions github-actions Bot locked and limited conversation to collaborators Feb 9, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants