Skip to content

Soroban WASM Size & Gas Optimization - #124

Merged
thisisouvik merged 5 commits into
thisisouvik:mainfrom
deslawson:main
Jul 29, 2026
Merged

Soroban WASM Size & Gas Optimization#124
thisisouvik merged 5 commits into
thisisouvik:mainfrom
deslawson:main

Conversation

@deslawson

@deslawson deslawson commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Description

Removed Debug derives from all contracttype enums (excluded from WASM builds via cfg_attr), replaced O(n) Vec storage serialization in the lending contract with O(1) counter-based key storage, pinned the Rust toolchain, configured wasm32 build flags, and added wasm-opt post-build scripts. All 5 contracts compile cleanly on dev, test, and wasm32-release targets with zero new warnings.

Related Issue

Closes #105

Motivation and Context

Soroban smart contracts were growing in Wasm size and CPU instruction cost as features were added. This change reduces both by eliminating unnecessary Debug formatting code from production binaries, replacing O(n) Vec storage serialization with O(1) counter-based key lookups, and adding tooling for ongoing wasm-opt optimization.

How Has This Been Tested?

All 5 contracts verified via:

  • cargo check (dev profile) — clean
  • cargo check --tests — clean
  • cargo check --target wasm32-unknown-unknown --release — clean
  • cargo clippy --tests — no new warnings
  • cargo clippy --target wasm32-unknown-unknown --release — no new warnings
  • cargo test could not run due to missing native linker on this machine, but all code compiles and type-checks fully

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.

Closes #105

Summary by CodeRabbit

  • New Features
    • Added borrower/lender loan history queries (loan counts and loan IDs by index).
    • Updated lending loan request input to remove the previous rate model parameter.
  • Tests
    • Updated lending contract tests to use the new loan request input struct format.
  • Chores
    • Added WebAssembly optimization scripts for Windows and Unix-like environments.
    • Pinned the stable Rust toolchain and standardized Soroban/WASM build settings; reduced non-test debug metadata for selected contract enums.
    • Enhanced CI security auditing (lockfile generation) and added production deployment to Vercel.

@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

@deslawson is attempting to deploy a commit to the thisisouvik's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jul 25, 2026

Copy link
Copy Markdown

@deslawson Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 11f91e26-6eab-473c-bd74-1235f34faecf

📥 Commits

Reviewing files that changed from the base of the PR and between 21ee9c4 and f253b5a.

📒 Files selected for processing (3)
  • contracts/default_management/src/lib.rs
  • contracts/lending/src/lib.rs
  • contracts/lending/src/test.rs

📝 Walkthrough

Walkthrough

The PR configures Soroban WASM builds, limits Debug derives to test builds, changes lending request inputs and loan tracking to indexed storage, updates lending tests, adds WASM optimization scripts, and modifies CI deployment and audit steps.

Changes

Soroban contract optimization

Layer / File(s) Summary
Build configuration and contract shapes
contracts/rust-toolchain.toml, contracts/.cargo/config.toml, contracts/*/src/lib.rs
WASM targets and stack flags are configured, while contract enums derive Debug only in test builds.
Lending input and indexed loan storage
contracts/lending/src/lib.rs
LoanRequestInput omits rate_model; borrower and lender loan IDs use count-and-index storage with new query methods.
Lending test API migration
contracts/lending/src/test.rs, refactor.js, refactor.py
Loan creation tests and refactoring utilities use the structured LoanRequestInput call shape.
WASM optimization tooling
contracts/scripts/optimize-wasm.sh, contracts/scripts/optimize-wasm.ps1
Cross-platform scripts validate wasm-opt, optimize WASM files in place, and report size changes.

Delivery automation

Layer / File(s) Summary
CI deployment and audit workflow
.github/workflows/ci.yml, .github/workflows/contract-security.yml
The frontend job deploys to Vercel, and the security job generates a contracts lockfile before auditing.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: soumen0818, sauravs296, thisisouvik

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses wasm-size and storage optimizations, but it does not include the gas usage before/after documentation required by #105. Add a before/after gas-usage comparison for the optimized contracts, or update #105 if that deliverable is intentionally out of scope.
Out of Scope Changes check ⚠️ Warning The new Vercel deploy step in CI is unrelated to Soroban contract optimization and appears outside the linked issue scope. Remove the Vercel deployment step from this PR or split it into a separate frontend deployment change.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: Soroban WASM size and gas optimization.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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: 3

🤖 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 `@contracts/borrower_reputation/src/lib.rs`:
- Around line 8-9: Replace cfg_attr(test, derive(Debug)) with a target-based
predicate that derives Debug on non-Wasm targets at every affected derive block:
contracts/borrower_reputation/src/lib.rs lines 8-9 and 20-21,
contracts/default_management/src/lib.rs lines 8-9, contracts/escrow/src/lib.rs
lines 8-9, contracts/governance/src/lib.rs lines 20-21 and 35-36, and
contracts/lending/src/lib.rs lines 8-9. Preserve the existing Clone, Eq, and
PartialEq derives while ensuring host builds retain Debug and Wasm builds do
not.

In `@contracts/lending/src/lib.rs`:
- Around line 64-67: Implement a migration for existing borrower and lender loan
indexes before relying exclusively on the count-plus-index DataKey variants
BorrowerLoanCount, BorrowerLoanAt, LenderLoanCount, and LenderLoanAt. Preserve
each user’s existing loan ordering and make get_borrower_loan_count,
get_lender_loan_count, and get_*_loan_at continue returning legacy loans after
upgrade, using an upgrade-time or versioned lazy migration path.

In `@contracts/rust-toolchain.toml`:
- Line 2: Replace the moving "stable" channel in the Rust toolchain
configuration with the validated rustc release in exact major.minor.patch
format. Keep the toolchain declaration otherwise unchanged and ensure it matches
the version validated for the Wasm build workflow.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 07a48645-5311-4f34-88ef-3eb078c77151

📥 Commits

Reviewing files that changed from the base of the PR and between eab623a and 11fe3eb.

📒 Files selected for processing (9)
  • contracts/.cargo/config.toml
  • contracts/borrower_reputation/src/lib.rs
  • contracts/default_management/src/lib.rs
  • contracts/escrow/src/lib.rs
  • contracts/governance/src/lib.rs
  • contracts/lending/src/lib.rs
  • contracts/rust-toolchain.toml
  • contracts/scripts/optimize-wasm.ps1
  • contracts/scripts/optimize-wasm.sh

Comment on lines +8 to +9
#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(test, derive(Debug))]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== affected lib sections =="
for f in \
  contracts/borrower_reputation/src/lib.rs \
  contracts/default_management/src/lib.rs \
  contracts/escrow/src/lib.rs \
  contracts/governance/src/lib.rs \
  contracts/lending/src/lib.rs
do
  if [ -f "$f" ]; then
    echo "--- $f"
    cat -n "$f" | sed -n '1,70p'
  else
    echo "MISSING $f"
  fi
done

echo
echo "== Cargo targets / wasm conventions =="
rg -n 'target_arch\s*=\s*"wasm32"|target_arch.*wasm|cfg_attr\(\s*test|env!("CARGO_\w+")|contract|lib\.rs' Cargo.toml contracts -g 'Cargo.toml' -g 'Cargo.lock' -g '*.rs' 2>/dev/null | head -200 || true

echo
echo "== rustdoc cfg target predicates in repo =="
rg -n 'cfg_attr\(\s*doc\s*,\s*cfg\(' -g '*.rs' . | head -100 || true

echo
echo "== dependency on cosmwasm-std versions =="
rg -n 'cosmwasm-std|cosmwasm-schema' Cargo.toml contracts -g 'Cargo.toml' 2>/dev/null | head -100 || true

python3 - <<'PY'
# Read-only parser-style check: identify cfg_attr directives immediately above a derive containing Debug,
# and describe the predicates they contain.
import pathlib, re
for p in [
    pathlib.Path('contracts/borrower_reputation/src/lib.rs'),
    pathlib.Path('contracts/default_management/src/lib.rs'),
    pathlib.Path('contracts/escrow/src/lib.rs'),
    pathlib.Path('contracts/governance/src/lib.rs'),
    pathlib.Path('contracts/lending/src/lib.rs'),
]:
    text = p.read_text(errors='replace').splitlines()
    print(f'--- {p}')
    for i,line in enumerate(text,1):
        if 'derive(Debug)' in line:
            start=max(1,i-5); end=min(len(text),i+2)
            block=text[start-1:end]
            cfg=None; derive=None; ident=None
            for j,l in enumerate(block,0):
                if '#[cfg_attr' in l: cfg=l.strip()
                if 'derive(' in l: derive=l.strip()
                m=re.search(r'enum\s+([A-Za-z_][A-Za-z0-9_]*)', ' '.join(block[j:j])) if j < len(block) else None
                if m: ident=m.group(1)
            print(f'line {i} {derive}')
            print('pre:', cfg)
            print('enum:', ident)
PY

Repository: thisisouvik/trustlend-stellar

Length of output: 29360


Gate Debug only off the Wasm target.

cfg_attr(test, ...) removes Debug from host cfg(test) builds as well, so non-Wasm development/release builds that import these public contracttypes can fail to format them. Use a target predicate such as:

Proposed change
-#[cfg_attr(test, derive(Debug))]
+#[cfg_attr(any(test, not(target_arch = "wasm32")), derive(Debug))]
📝 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
#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(test, derive(Debug))]
#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(any(test, not(target_arch = "wasm32")), derive(Debug))]
📍 Affects 5 files
  • contracts/borrower_reputation/src/lib.rs#L8-L9 (this comment)
  • contracts/borrower_reputation/src/lib.rs#L20-L21
  • contracts/default_management/src/lib.rs#L8-L9
  • contracts/escrow/src/lib.rs#L8-L9
  • contracts/governance/src/lib.rs#L20-L21
  • contracts/governance/src/lib.rs#L35-L36
  • contracts/lending/src/lib.rs#L8-L9
🤖 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 `@contracts/borrower_reputation/src/lib.rs` around lines 8 - 9, Replace
cfg_attr(test, derive(Debug)) with a target-based predicate that derives Debug
on non-Wasm targets at every affected derive block:
contracts/borrower_reputation/src/lib.rs lines 8-9 and 20-21,
contracts/default_management/src/lib.rs lines 8-9, contracts/escrow/src/lib.rs
lines 8-9, contracts/governance/src/lib.rs lines 20-21 and 35-36, and
contracts/lending/src/lib.rs lines 8-9. Preserve the existing Clone, Eq, and
PartialEq derives while ensuring host builds retain Debug and Wasm builds do
not.

Comment on lines +64 to +67
BorrowerLoanCount(Address),
BorrowerLoanAt(Address, u32),
LenderLoanCount(Address),
LenderLoanAt(Address, u32),

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | sed -n '1,200p'

echo
echo "Target file outline:"
ast-grep outline contracts/lending/src/lib.rs || true

echo
echo "Relevant target file lines:"
sed -n '1,220p' contracts/lending/src/lib.rs

echo
echo "Search DataKey/LoanCount/LenderLoanAt and migrations:"
rg -n "DataKey|BorrowerLoanCount|BorrowerLoanAt|LenderLoanCount|LenderLoanAt|MIG|migration|migrate|StorageKey|borr|lend|Address" contracts/lending/src -S

Repository: thisisouvik/trustlend-stellar

Length of output: 30191


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Relevant storage operations:"
sed -n '250,565p' contracts/lending/src/lib.rs

echo
echo "Search for old borrower/lender index symbols and migrations across contracts/lending:"
rg -n "Vec<|loan_count|borrower_loan|lender_loan|Migration|migrate|MIG|Version|VERSION|Borrow|Lender|StorageKey|persistent\(\)" contracts/lending --glob 'contracts/lending/src/*' -S

echo
echo "Search contract version/migration constants in repository:"
rg -n "Migration|migration|migrate|MIG|Version|VERSION|StorageKey|DataKey" contracts -S | sed -n '1,240p'

Repository: thisisouvik/trustlend-stellar

Length of output: 25171


Migrate existing borrower and lender indexes before switching keys.

DataKey now stores borrower/lender history at count+index keys, and the lending contract only creates instances starting from new LoanCount. Any deployed/initialized contract that already used the previous per-user vector/index keys will expose get_borrower_loan_count/get_lender_loan_count as 0 and make get_*_loan_at fail for existing loans unless those legacy entries are migrated before or as part of upgrade paths. Add the migration and/or keep the old keys behind a versioned/lazy migration path that preserves order.

🤖 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 `@contracts/lending/src/lib.rs` around lines 64 - 67, Implement a migration for
existing borrower and lender loan indexes before relying exclusively on the
count-plus-index DataKey variants BorrowerLoanCount, BorrowerLoanAt,
LenderLoanCount, and LenderLoanAt. Preserve each user’s existing loan ordering
and make get_borrower_loan_count, get_lender_loan_count, and get_*_loan_at
continue returning legacy loans after upgrade, using an upgrade-time or
versioned lazy migration path.

Comment thread contracts/rust-toolchain.toml
@thisisouvik

Copy link
Copy Markdown
Owner

Fix the cargo test issue! @deslawson
Preferred fix (code-level): reduce argument count with a request struct
Refactor create_loan_request to take one struct argument for the loan inputs.

Rust
#[contracttype]
#[derive(Clone)]
pub struct LoanRequestInput {
pub amount: i128,
pub duration_days: u32,
pub interest_rate_bps: u32,
pub max_loan_amount: i128,
pub collateral_asset: Address,
pub collateral_amount: i128,
}
Then change signature:

Rust
pub fn create_loan_request(
env: Env,
borrower: Address,
input: LoanRequestInput,
) -> u32 {
borrower.require_auth();

if input.amount <= 0 {
    panic!("Loan amount must be positive");
}
if input.amount > input.max_loan_amount {
    panic!("Amount exceeds reputation-based limit");
}
if input.duration_days == 0 || input.duration_days > 365 {
    panic!("Duration must be between 1 and 365 days");
}
if input.collateral_amount <= 0 {
    panic!("Collateral amount must be positive");
}
if !env.storage().instance().has(&DataKey::WhitelistedAsset(input.collateral_asset.clone())) {
    panic!("Collateral asset is not whitelisted");
}

let interest = Self::calculate_interest(input.amount, input.interest_rate_bps, input.duration_days);
// ...continue replacing old vars with input.*

}
This keeps behavior intact while satisfying Clippy.

Alternative fix (policy-level): allow this lint in CI
If you intentionally want broader function signatures for Soroban ABI clarity, relax CI linting:

YAML
run: cargo clippy --all-targets -- -D warnings
-A clippy::inconsistent_digit_grouping
-A clippy::too_many_arguments
This is quicker, but it suppresses a real maintainability lint globally for the job.

Reference links

Failing workflow: https://github.com/thisisouvik/trustlend-stellar/blob/11fe3ebfdcc9bcc0c19f1466bf859f56f37d0a19/.github/workflows/contract-security.yml
Failing contract file: https://github.com/thisisouvik/trustlend-stellar/blob/11fe3ebfdcc9bcc0c19f1466bf859f56f37d0a19/contracts/lending/src/lib.rs

Removed Debug derives from all contracttype enums (excluded from WASM builds via cfg_attr), replaced O(n) Vec<u32> storage serialization in the lending contract with O(1) counter-based key storage, pinned the Rust toolchain, configured wasm32 build flags, and added wasm-opt post-build scripts. All 5 contracts compile cleanly on dev, test, and wasm32-release targets with zero new warnings.

Closes thisisouvik#105
@thisisouvik

Copy link
Copy Markdown
Owner

@deslawson fix this and gain give pull request.

@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

🤖 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 @.github/workflows/ci.yml:
- Around line 69-74: Update the “Deploy to Vercel” workflow step to invoke the
locally installed CLI explicitly with npx --no-install and include --yes for CI.
Add Vercel as a pinned dependency in the project manifests and lockfile so the
command is available without relying on a globally installed executable.

In @.github/workflows/contract-security.yml:
- Around line 42-47: Update the workflow’s cargo-audit step to use the committed
contracts/Cargo.lock: remove the “Generate lockfile” step and invoke cargo audit
with --locked or --frozen from the contracts working directory, preserving the
existing dependency versions under review.

In `@refactor.js`:
- Around line 4-17: The migration regexes in refactor.js lines 4-17 and
refactor.py lines 28-33 must support the legacy InterestRateModel::Fixed
argument. Update both scripts’ call-matching patterns to consume and discard
that argument while preserving the existing six-field LoanRequestInput
transformation, or remove both completed one-off scripts.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e80b2d2f-f73e-41ae-886e-c70eb7b31c99

📥 Commits

Reviewing files that changed from the base of the PR and between 11fe3eb and 21ee9c4.

📒 Files selected for processing (10)
  • .github/workflows/ci.yml
  • .github/workflows/contract-security.yml
  • contracts/borrower_reputation/src/lib.rs
  • contracts/default_management/src/lib.rs
  • contracts/escrow/src/lib.rs
  • contracts/governance/src/lib.rs
  • contracts/lending/src/lib.rs
  • contracts/lending/src/test.rs
  • refactor.js
  • refactor.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • contracts/escrow/src/lib.rs
  • contracts/default_management/src/lib.rs
  • contracts/governance/src/lib.rs
  • contracts/borrower_reputation/src/lib.rs
  • contracts/lending/src/lib.rs

Comment thread .github/workflows/ci.yml
Comment on lines +69 to +74

- name: Deploy to Vercel
run: vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

node -e "const p=require('./package.json'); console.log(p.devDependencies?.vercel ?? p.dependencies?.vercel ?? 'vercel dependency missing')"
test -x node_modules/.bin/vercel

Repository: thisisouvik/trustlend-stellar

Length of output: 193


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "## workflow excerpt"
sed -n '1,130p' .github/workflows/ci.yml | cat -n

echo
echo "## package manifests"
for f in package.json package-lock.json pnpm-lock.yaml yarn.lock bun.lockb bun.lock; do
  if [ -f "$f" ]; then
    echo "### $f"
    if [ "$f" != "bun.lockb" ]; then
      sed -n '1,220p' "$f" | grep -n -E '"vercel"|vercel@|/.bin/vercel|packages/vercel|node_modules/\.bin/vercel|dependencies|devDependencies|workspaces' || true
    else
      file "$f"
      ls -l "$f"
    fi
  fi
done

echo
echo "## dependency mentions"
rg -n '"vercel"|vercel@|/node_modules/\.bin/vercel|\.bin/vercel|actions/setup-node|npm ci|npm install' -S . --glob '!node_modules' --glob '!dist' --glob '!build' | head -200

Repository: thisisouvik/trustlend-stellar

Length of output: 3335


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "## package.json"
cat -n package.json

echo
echo "## package-lock.json relevant sections"
sed -n '1,240p' package-lock.json | cat -n
echo
echo "## exact vercel mentions in package files"
rg -n '\bvercel\b|vercel@' package.json package-lock.json || true

Repository: thisisouvik/trustlend-stellar

Length of output: 12963


Make the Vercel CLI executable explicit.

Line [71] invokes bare vercel, but the workflow only installs npm dependencies and vercel is not in package.json/package-lock.json. This can fail with command not found on the runner; add Vercel as a pinned dependency and invoke it as npx --no-install vercel ... with --yes for CI.

🤖 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 @.github/workflows/ci.yml around lines 69 - 74, Update the “Deploy to Vercel”
workflow step to invoke the locally installed CLI explicitly with npx
--no-install and include --yes for CI. Add Vercel as a pinned dependency in the
project manifests and lockfile so the command is available without relying on a
globally installed executable.

Comment on lines 42 to +47
- name: Install cargo-audit
run: cargo install cargo-audit --locked

- name: Generate lockfile
working-directory: ./contracts
run: cargo generate-lockfile

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

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

test -f contracts/Cargo.lock
git ls-files --error-unmatch contracts/Cargo.lock
git diff --exit-code -- contracts/Cargo.lock

Repository: thisisouvik/trustlend-stellar

Length of output: 188


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
sed -n '1,80p' .github/workflows/contract-security.yml 2>/dev/null || true

echo
echo "== contracts Cargo.lock entry from git ls-files =="
git ls-files -s -- contracts/Cargo.lock || true

echo
echo "== search for contract audit / cargo lock mentions =="
rg -n "contract-security|cargo-audit|cargo audit|generate-lockfile|Cargo.lock" .github contracts Cargo.toml 2>/dev/null || true

Repository: thisisouvik/trustlend-stellar

Length of output: 159


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repository files relevant =="
git ls-files | rg '(^\.github/workflows/|Cargo\.lock$|^Cargo\.toml$|^contracts/)' | sed -n '1,160p'

echo
echo "== workflow file presence/size =="
if [ -f .github/workflows/contract-security.yml ]; then
  wc -l .github/workflows/contract-security.yml
  sed -n '1,90p' .github/workflows/contract-security.yml
else
  echo "missing .github/workflows/contract-security.yml"
fi

echo
echo "== lockfile tracked and diff status =="
git ls-files --error-unmatch contracts/Cargo.lock
git status --short -- contracts/Cargo.lock || true
git diff --stat -- contracts/Cargo.lock
git diff --exit-code -- contracts/Cargo.lock || true

echo
echo "== audit/cargo lock references =="
rg -n "contract-security|cargo-audit|cargo audit|generate-lockfile|Cargo.lock|cargo check|cargo clippy" .github contracts Cargo.toml 2>/dev/null | sed -n '1,160p' || true

Repository: thisisouvik/trustlend-stellar

Length of output: 159


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== target workflow =="
test -f .github/workflows/contract-security.yml
wc -l .github/workflows/contract-security.yml
awk '{printf "%4d  %s\n", NR, $0}' .github/workflows/contract-security.yml

echo
echo "== contracts/Cargo.lock tracked status =="
git ls-files --error-unmatch contracts/Cargo.lock
git status --short -- contracts/Cargo.lock || true
git diff --stat -- contracts/Cargo.lock || true

echo
echo "== lockfile/head hash metadata =="
git ls-files -s -- contracts/Cargo.lock Cargo.lock
git rev-parse HEAD:contracts/Cargo.lock 2>/dev/null | head -c 48
printf '\n'
git rev-parse HEAD:Cargo.lock 2>/dev/null | head -c 48 | sed 's/$/ (root Cargo.lock)/' || true

Repository: thisisouvik/trustlend-stellar

Length of output: 1953


🌐 Web query:

docs.rust-lang.org/cargo/commands/cargo-generate-lockfile Cargo.lock rebuild updated dependencies

💡 Result:

Yes, the cargo generate-lockfile command will rebuild your Cargo.lock file with the latest available versions of all dependencies [1][2]. If a Cargo.lock file already exists, this command performs a full resolution and updates the entries to the newest compatible versions allowed by your Cargo.toml [1][3]. Key points regarding this command: - Functionality: It generates a new Cargo.lock file or recreates an existing one by recalculating the dependency graph, effectively updating all packages to their latest eligible versions [1][3]. - Comparison with cargo update: While both commands can update dependencies, cargo update is the standard command for updating the lockfile, as it provides more granular control—such as updating only specific dependencies or performing conservative updates [4][5]. - Behavior: Unlike building your project (e.g., cargo build), which attempts to keep dependencies locked to the existing Cargo.lock versions [5], cargo generate-lockfile actively seeks to update the entire lockfile to the latest versions [1][2]. If you wish to maintain deterministic builds or prevent these updates, you should use the --locked or --frozen flags, which cause Cargo to error out if the lockfile needs modification [1][3].

Citations:


Audit the committed contracts/Cargo.lock instead of regenerating it.

contracts/Cargo.lock is tracked, but cargo generate-lockfile rebuilds it at resolution time, so this workflow can audit dependency versions different from what the PR committed. Remove this step and run cargo audit --locked (or cargo audit --frozen) against the committed lockfile.

🤖 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 @.github/workflows/contract-security.yml around lines 42 - 47, Update the
workflow’s cargo-audit step to use the committed contracts/Cargo.lock: remove
the “Generate lockfile” step and invoke cargo audit with --locked or --frozen
from the contracts working directory, preserving the existing dependency
versions under review.

Comment thread refactor.js
Comment on lines +4 to +17
const pattern = /(.*?)\bclient\.create_loan_request\s*\(\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^,]+),\s*([^,)]+)\)/gs;

content = content.replace(pattern, (match, prefix, borrower, amount, duration, rate, max_loan, asset, collateral) => {
return `${prefix}client.create_loan_request(
${borrower.trim()},
&LoanRequestInput {
amount: ${amount.trim().replace(/^&/, '')},
duration_days: ${duration.trim().replace(/^&/, '')},
interest_rate_bps: ${rate.trim().replace(/^&/, '')},
max_loan_amount: ${max_loan.trim().replace(/^&/, '')},
collateral_asset: ${asset.trim().replace(/^&/, '')},
collateral_amount: ${collateral.trim().replace(/^&/, '')},
}
)`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make both migration scripts match the legacy call shape. The old API included InterestRateModel::Fixed in addition to the six fields now stored in LoanRequestInput; neither regex accepts that extra argument.

  • refactor.js#L4-L17: consume and discard the legacy interest-model argument, or delete the completed one-off script.
  • refactor.py#L28-L33: apply the same correction or remove the duplicate script.
📍 Affects 2 files
  • refactor.js#L4-L17 (this comment)
  • refactor.py#L28-L33
🤖 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 `@refactor.js` around lines 4 - 17, The migration regexes in refactor.js lines
4-17 and refactor.py lines 28-33 must support the legacy
InterestRateModel::Fixed argument. Update both scripts’ call-matching patterns
to consume and discard that argument while preserving the existing six-field
LoanRequestInput transformation, or remove both completed one-off scripts.

@thisisouvik

Copy link
Copy Markdown
Owner

@deslawson Close the commits, fix the workflow problems and merge conflicts, and submit a fresh PR.

@thisisouvik
thisisouvik merged commit 51713e1 into thisisouvik:main Jul 29, 2026
1 of 8 checks passed
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.

[Smart Contracts] Gas Optimization and Contract Size Reduction in Soroban

2 participants