Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .cargo/audit.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# cargo-audit configuration
# https://docs.rs/cargo-audit/latest/cargo_audit/config/

[advisories]
# Ignore the lru unsound advisory - it comes from near-vm-runner which is
# locked to lru ^0.12.3 and cannot be updated to the fixed 0.16.3 version.
# The advisory relates to IterMut's Stacked Borrows violation, which does
# not affect our usage as we don't use IterMut directly.
# Tracked: https://github.com/near/nearcore/issues/XXXXX (upstream)
ignore = ["RUSTSEC-2026-0002"]
Comment on lines +5 to +10
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

RUSTSEC-2026-0002 lru upstream issue github

💡 Result:

RUSTSEC-2026-0002 is an unsoundness advisory for the Rust crate lru: its IterMut::next / next_back temporarily create an exclusive reference that violates Stacked Borrows by invalidating an internal pointer held by the HashMap. Affected versions are >= 0.9.0 and < 0.16.3; fixed in lru >= 0.16.3. [1][3]

Upstream GitHub fix (PR):

https://github.com/jeromefroe/lru-rs/pull/224

Merged January 7, 2026. [1][2]

Related alias: GHSA-rhfx-m35p-ff5j. [1][3]

Sources: [1] [2] [3]


Replace the placeholder upstream issue link with the actual upstream PR.

The ignore note references an issues/XXXXX placeholder. Link to the actual upstream fix: jeromefroe/lru-rs#224 (merged January 7, 2026).

🤖 Prompt for AI Agents
In @.cargo/audit.toml around lines 5 - 10, Update the placeholder upstream issue
link in the ignore note: replace "https://github.com/near/nearcore/issues/XXXXX
(upstream)" with the actual upstream PR URL
"https://github.com/jeromefroe/lru-rs/pull/224 (merged January 7, 2026)" so the
tracked line accurately references the upstream fix for the lru advisory in the
ignore comment near the ignore = ["RUSTSEC-2026-0002"] entry.

5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ jobs:
- name: Run Tests
env:
DEFUSE_MIGRATE_FROM_LEGACY: "true"
run: cargo make run-tests -- --show-output
run: cargo make run-tests-long -- --show-output

security_audit_report:
name: Security Audit - report
Expand All @@ -162,7 +162,8 @@ jobs:
with:
cache: false
- name: Install cargo-audit
run: cargo install cargo-audit --version "^0.21" --locked
# Require 0.22+ for CVSS 4.0 support (advisory-db now contains CVSS 4.0 entries)
run: cargo install cargo-audit --version "^0.22" --locked
Comment on lines +165 to +166
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate all cargo-audit installs in the CI file
rg -n "cargo install cargo-audit" .github/workflows/ci.yml

Repository: near/intents

Length of output: 168


🏁 Script executed:

#!/bin/bash
# Get context around cargo-audit installations and identify which job each belongs to
rg -B 5 "cargo install cargo-audit" .github/workflows/ci.yml

Repository: near/intents

Length of output: 589


Align cargo-audit version across audit jobs.

The deny job installs cargo-audit without version pinning while the report job pins it to ^0.22 for CVSS 4.0 support. This creates version drift between the two jobs. Update the deny job to match:

♻️ Suggested update for security_audit_deny
-      - name: Install Cargo Plugins
-        run: cargo install cargo-audit --locked
+      - name: Install Cargo Plugins
+        run: cargo install cargo-audit --version "^0.22" --locked
🤖 Prompt for AI Agents
In @.github/workflows/ci.yml around lines 165 - 166, The deny job currently
installs cargo-audit without version pinning causing drift vs the report job;
update the cargo install command in the security_audit_deny job to match the
report job by pinning cargo-audit to "^0.22" and keeping the --locked flag
(i.e., replace the unpinned install invocation with the same `cargo install
cargo-audit --version "^0.22" --locked` used in the report job).

- uses: rustsec/audit-check@v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ run_task = "run-tests"
command = "cargo"
args = ["test", "--workspace", "--all-targets", "${@}"]

[tasks.run-tests-long]
command = "cargo"
args = ["test", "--workspace", "--all-targets", "--features=long", "${@}"]
Comment on lines +211 to +213
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python - <<'PY'
import glob, pathlib, tomllib

root = pathlib.Path("Cargo.toml")
if not root.exists():
    raise SystemExit("Root Cargo.toml not found")

data = tomllib.loads(root.read_text())
members = data.get("workspace", {}).get("members", [])
if not members:
    print("No workspace.members found in Cargo.toml")
    raise SystemExit(0)

def expand(member):
    if any(ch in member for ch in "*?[]"):
        return [pathlib.Path(p) for p in glob.glob(member)]
    return [pathlib.Path(member)]

missing = []
for m in members:
    for path in expand(m):
        cargo = path / "Cargo.toml"
        if not cargo.exists():
            print(f"Missing {cargo}")
            continue
        pkg = tomllib.loads(cargo.read_text())
        features = pkg.get("features", {})
        if "long" not in features:
            missing.append(str(cargo))

if missing:
    print("Packages missing feature 'long':")
    print("\n".join(sorted(set(missing))))
else:
    print("All workspace packages define feature 'long'")
PY

Repository: near/intents

Length of output: 726


Fix run-tests-long task — most workspace members lack the long feature.

The command will fail when executed because 32 of 33 workspace members don't define the long feature (missing from admin-utils, auth-call, bitmap, borsh-utils, controller, core, crypto, deadline, decimal, defuse, erc191, escrow-swap, fees, io-utils, map-utils, near-utils, nep245, nep413, nep461, num-utils, poa-factory, poa-token, randomness, sandbox, sep53, serde-utils, test-utils, tip191, token-id, ton-connect, webauthn, wnear). Either add long feature definitions to all workspace crates, or scope the command to specific crates using -p <crate> or --package <crate>.

🤖 Prompt for AI Agents
In `@Makefile.toml` around lines 211 - 213, The run-tests-long cargo task
(tasks.run-tests-long) currently passes --features=long to the entire workspace,
which fails because most crates don't define a long feature; update the task to
either scope the cargo invocation to the crates that actually support the long
feature by adding package selectors (use -p or --package with the crate names
that define long) or remove the workspace-wide --features=long and instead run
cargo test with --features=long per-package for those crates; modify the args
array for tasks.run-tests-long to use targeted package flags (e.g., -p/<crate>)
or change the command to iterate only over the crates that expose the long
feature so the test run no longer fails.


# ============================================================================
# Cleanup tasks
# ============================================================================
Expand Down
4 changes: 2 additions & 2 deletions defuse/src/contract/tokens/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod nep245;

use super::Contract;
use defuse_core::{DefuseError, Result, token_id::TokenId};
use defuse_near_utils::{Lock, UnwrapOrPanic};
use defuse_near_utils::{Lock, REFUND_MEMO, UnwrapOrPanic};
use defuse_nep245::{MtBurnEvent, MtEvent, MtMintEvent};
use itertools::{Either, Itertools};
use near_sdk::{AccountId, AccountIdRef, Gas, env, json_types::U128, serde_json};
Expand Down Expand Up @@ -162,7 +162,7 @@ impl Contract {
authorized_id: None,
token_ids: Vec::with_capacity(tokens_count).into(),
amounts: Vec::with_capacity(tokens_count).into(),
memo: Some("refund".into()),
memo: Some(REFUND_MEMO.into()),
};

let Some(receiver) = self
Expand Down
4 changes: 2 additions & 2 deletions defuse/src/contract/tokens/nep141/withdraw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use defuse_core::{
DefuseError, Result, engine::StateView, intents::tokens::FtWithdraw,
token_id::nep141::Nep141TokenId,
};
use defuse_near_utils::UnwrapOrPanic;
use defuse_near_utils::{REFUND_MEMO, UnwrapOrPanic};
use defuse_wnear::{NEAR_WITHDRAW_GAS, ext_wnear};
use near_contract_standards::{
fungible_token::core::ext_ft_core, storage_management::ext_storage_management,
Expand Down Expand Up @@ -188,7 +188,7 @@ impl FungibleTokenWithdrawResolver for Contract {
self.deposit(
sender_id,
[(Nep141TokenId::new(token).into(), refund)],
Some("refund"),
Some(REFUND_MEMO),
)
.unwrap_or_panic();
}
Expand Down
4 changes: 2 additions & 2 deletions defuse/src/contract/tokens/nep171/withdraw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use defuse_core::{
intents::tokens::NftWithdraw,
token_id::{nep141::Nep141TokenId, nep171::Nep171TokenId},
};
use defuse_near_utils::UnwrapOrPanic;
use defuse_near_utils::{REFUND_MEMO, UnwrapOrPanic};
use defuse_wnear::{NEAR_WITHDRAW_GAS, ext_wnear};
use near_contract_standards::{
non_fungible_token::{self, core::ext_nft_core},
Expand Down Expand Up @@ -187,7 +187,7 @@ impl NonFungibleTokenWithdrawResolver for Contract {
self.deposit(
sender_id,
[(Nep171TokenId::new(token, token_id).into(), 1)],
Some("refund"),
Some(REFUND_MEMO),
)
.unwrap_or_panic();
}
Expand Down
7 changes: 5 additions & 2 deletions defuse/src/contract/tokens/nep245/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use defuse_core::{
DefuseError, Result, engine::StateView, intents::tokens::NotifyOnTransfer, token_id::TokenId,
};
use defuse_near_utils::{UnwrapOrPanic, UnwrapOrPanicError};
use defuse_nep245::{MtEvent, MtTransferEvent, MultiTokenCore, receiver::ext_mt_receiver};
use defuse_nep245::{
EmitChecked, MtEvent, MtTransferEvent, MultiTokenCore, receiver::ext_mt_receiver,
};
use near_plugins::{Pausable, pause};
use near_sdk::{
AccountId, AccountIdRef, Gas, NearToken, Promise, PromiseOrValue, assert_one_yocto, env,
Expand Down Expand Up @@ -209,7 +211,8 @@ impl Contract {
.as_slice()
.into(),
)
.emit();
.emit_with_refund_log_checked()
.unwrap_or_panic();

Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions defuse/src/contract/tokens/nep245/resolver.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::Cow;

use defuse_near_utils::{Lock, UnwrapOrPanic, UnwrapOrPanicError};
use defuse_near_utils::{Lock, REFUND_MEMO, UnwrapOrPanic, UnwrapOrPanicError};
use defuse_nep245::{
ClearedApproval, MtEventEmit, MtTransferEvent, TokenId, resolver::MultiTokenResolver,
};
Expand Down Expand Up @@ -109,7 +109,7 @@ impl MultiTokenResolver for Contract {
new_owner_id: Cow::Borrowed(&sender_id),
token_ids: refunded_token_ids.into(),
amounts: refunded_amounts.into(),
memo: Some("refund".into()),
memo: Some(REFUND_MEMO.into()),
}]
.as_slice(),
)
Expand Down
4 changes: 2 additions & 2 deletions defuse/src/contract/tokens/nep245/withdraw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use defuse_core::{
intents::tokens::MtWithdraw,
token_id::{nep141::Nep141TokenId, nep245::Nep245TokenId},
};
use defuse_near_utils::{UnwrapOrPanic, UnwrapOrPanicError};
use defuse_near_utils::{REFUND_MEMO, UnwrapOrPanic, UnwrapOrPanicError};
use defuse_nep245::ext_mt_core;
use defuse_wnear::{NEAR_WITHDRAW_GAS, ext_wnear};
use near_contract_standards::storage_management::ext_storage_management;
Expand Down Expand Up @@ -253,7 +253,7 @@ impl MultiTokenWithdrawResolver for Contract {
None
}
}),
Some("refund"),
Some(REFUND_MEMO),
)
.unwrap_or_panic();

Expand Down
7 changes: 7 additions & 0 deletions near-utils/src/event.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/// Maximum length of a single log entry in NEAR runtime.
/// See: <https://github.com/near/nearcore/blob/v2.5.0/runtime/near-vm-runner/src/logic/logic.rs#L42>
pub const TOTAL_LOG_LENGTH_LIMIT: usize = 16384;
Comment on lines +1 to +3
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

NEAR runtime TOTAL_LOG_LENGTH_LIMIT 16384

💡 Result:

"TOTAL_LOG_LENGTH_LIMIT = 16384" is the protocol/runtime limit on the total bytes of emitted logs for a single execution (a contract call/receipt). If a contract's logs exceed this (16,384 bytes) the runtime will fail the call with TotalLogLengthExceeded. This limit appears in the protocol/limit_config as max_total_log_length = 16384. [1][2]

Sources:

  • NEAR protocol config / RPC example showing max_total_log_length = 16384. [1]
  • Runtime error list including TotalLogLengthExceeded (the error raised when total log length exceeds the limit). [2]

🌐 Web query:

NEAR nearcore v2.5.0 logic.rs log length limit

💡 Result:

I couldn't find a specific reference to a "logic.rs" log-length limit in nearcore v2.5.0 from public docs or the nearcore repo with the search terms given. Could you paste the logic.rs snippet or point me to the file/line (GitHub URL or crate path) you mean? With that I can locate the exact limit and explain it.


🌐 Web query:

nearcore v2.5.0 runtime near-vm-runner logic.rs file structure

💡 Result:

Summary outline of logic.rs (runtime/near-vm-runner/src/logic/logic.rs) in nearcore v2.5.0 — high-level structure:

  • Top-level imports and feature flags. [1]
  • Type/enum definitions used by the runner (e.g., VMOutcome, PromiseResult, VMLogicError variants). [1]
  • Traits & key public items re-exported by the crate (CompiledContract, VM, PreparedContract). [1]
  • VMLogic implementation — the core struct that:
    • stores VMContext and External handle,
    • implements host-function handlers that expose near-vm-logic APIs to WASM (storage read/write, logs, promises, input/output, math/hash helpers, context getters, etc.). [2][3]
  • Helpers for memory/register management and conversion between WASM memory and runtime types (read/write registers, serialize/deserialize). [1][3]
  • Error types and conversion helpers (mapping VM/wasm traps to VMLogic errors). [1]
  • Compilation/preparation glue points referenced by the runner (prepare/compile/cache interactions). [1]
  • Unit tests for host functions and VM interactions (bottom of file or in nearby test modules). [1]

Sources / references:

  • near-vm-runner crate docs (module overview and exported logic module). [1]
  • Nomicon / Runtime spec describing near-vm-runner and VMLogic role. [2]
  • Implementation reference pointer to logic.rs in the nearcore repo. [3]

🌐 Web query:

github.com/near/nearcore blob v2.5.0 near-vm-runner

💡 Result:

The near-vm-runner crate for nearcore v2.5.0 is at runtime/near-vm-runner in the near/nearcore repo — e.g. GitHub blob path: https://github.com/near/nearcore/tree/v2.5.0/runtime/near-vm-runner. [1][2]

Sources:

  • near/nearcore repository. [1]
  • near-vm-runner crate docs (near-vm-runner). [2]

🌐 Web query:

site:github.com/near/nearcore/blob/v2.5.0 runtime/near-vm-runner src/logic logic.rs line 42

💡 Result:

I tried to fetch that file/line from GitHub but ran into an error accessing the repository file. Do you want me to try again (or paste the file contents here)?


🌐 Web query:

NEAR protocol specification max_total_log_length specification

💡 Result:

The NEAR protocol specification sets max_total_log_length = 16384 (bytes). [1][2]

Sources:
[1] NEAR RPC protocol config (limit_config -> max_total_log_length).
[2] NEAR Protocol / Nomicon parameter listing.


🌐 Web query:

NEAR runtime "single log entry" vs "total log length" difference

💡 Result:

Do you mean NEAR Protocol's runtime (smart contract) log limits/fields — e.g., RPC responses that show "single_log_entry" vs "total_log_length" — or something else (explorer, node logs, or an SDK/runtime API)? If you confirm which NEAR component and where you saw those terms (link or JSON snippet), I’ll look up the exact difference and cite sources.


🌐 Web query:

nearcore log length limit single entry total execution

💡 Result:

Short answer: nearcore enforces a maximum of 100 log entries per execution and a maximum total log bytes of 16,384 (i.e. ~16 KiB) across that execution — there is no separate hard limit for a single log entry beyond those totals, so a single log can be as large as the total log budget (subject to UTF‑8 and other limits). [1][2]

Sources:

  • NEAR protocol/nearcore limit_config showing max_number_logs = 100 and max_total_log_length = 16384. [1]
  • NEAR forum discussion noting the 100 logs-per-execution limit. [2]

🏁 Script executed:

cat -n near-utils/src/event.rs | head -10

Repository: near/intents

Length of output: 380


Fix documentation: 16384 is the total log length limit per execution, not per single log entry.

The constant value (16384 bytes) is correct per NEAR protocol spec, but the documentation comment is misleading. NEAR enforces a maximum of 100 log entries per execution with a combined total of 16,384 bytes — there is no separate hard limit on individual log entry size. Update the comment to clarify this is the total log budget for an entire execution:

/// Maximum total length of all log entries in a single execution (in bytes).
/// See: <https://github.com/near/nearcore/blob/v2.5.0/runtime/near-vm-runner/src/logic/logic.rs#L42>
🤖 Prompt for AI Agents
In `@near-utils/src/event.rs` around lines 1 - 3, Update the doc comment for the
constant TOTAL_LOG_LENGTH_LIMIT to state it is the maximum total length of all
log entries in a single execution (in bytes) rather than a per-entry limit;
locate the pub const TOTAL_LOG_LENGTH_LIMIT: usize = 16384; declaration in
event.rs and replace the misleading comment with a line like "Maximum total
length of all log entries in a single execution (in bytes)." and keep the
existing GitHub reference link.


/// Memo used for refund events.
pub const REFUND_MEMO: &str = "refund";

pub trait NearSdkLog {
fn to_near_sdk_log(&self) -> String;
}
2 changes: 1 addition & 1 deletion near-utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[cfg(feature = "digest")]
pub mod digest;
mod event;
pub use event::NearSdkLog;
pub use event::{NearSdkLog, REFUND_MEMO, TOTAL_LOG_LENGTH_LIMIT};
mod gas;
mod lock;
mod panic;
Expand Down
4 changes: 4 additions & 0 deletions nep245/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ repository.workspace = true
derive_more = { workspace = true, features = ["from"] }
near-sdk.workspace = true
defuse-near-utils.workspace = true
thiserror.workspace = true

[dev-dependencies]
near-sdk = { workspace = true, features = ["unit-testing"] }

[lints]
workspace = true
Loading
Loading