Skip to content

Add test contract comparing u32 vs U256 costs#398

Closed
leighmcculloch wants to merge 1 commit intomainfrom
u32-vs-u256-costs
Closed

Add test contract comparing u32 vs U256 costs#398
leighmcculloch wants to merge 1 commit intomainfrom
u32-vs-u256-costs

Conversation

@leighmcculloch
Copy link
Member

What

Add a test contract that demonstrates the cost differences between using u32 and U256 token IDs. The contract includes functions to store, load, and emit events for both types. A Makefile target deploys to testnet and records fee metrics to a CSV file.

Why

Needed to understand the affect of using U256 for token IDs instead of U32.

Results

Benchmarks show U256 token IDs cost ~13% more for storage operations (32531 vs 28785 stroops) and ~2% more for events (10490 vs 10332 stroops).

@socket-security
Copy link

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedsoroban-sdk@​23.5.18210093100100

View full report

@socket-security
Copy link

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
License policy violation: cargo unicode-ident under Unicode-3.0

License: Unicode-3.0 - the applicable license policy does not allow this license (4) (unicode-ident-1.0.22/Cargo.toml)

License: Unicode-3.0 - the applicable license policy does not allow this license (4) (unicode-ident-1.0.22/Cargo.toml)

License: Unicode-3.0 - the applicable license policy does not allow this license (4) (unicode-ident-1.0.22/LICENSE-UNICODE)

From: ?cargo/soroban-sdk@23.5.1cargo/unicode-ident@1.0.22

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore cargo/unicode-ident@1.0.22. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@leighmcculloch leighmcculloch deleted the u32-vs-u256-costs branch February 3, 2026 12:28
@leighmcculloch leighmcculloch changed the title Add text contract comparing u32 vs U256 costs Add test contract comparing u32 vs U256 costs Feb 3, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a small Soroban benchmark contract and tooling to compare runtime fees for u32 vs U256 token IDs (storage + event emission), along with recorded sample cost output.

Changes:

  • Introduces TokenIdContract with store/load/event functions for both u32 and U256 token IDs.
  • Adds Rust unit tests for the contract functions.
  • Adds a deploy-and-cost Makefile target and a checked-in costs.csv containing sample fee metrics.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
nft/src/lib.rs New contract implementing storage + event APIs for u32 and U256 token IDs.
nft/src/test.rs Unit tests exercising store/load and event methods for both ID types.
nft/Makefile Build/test targets plus deploy+invoke cost-capture automation into CSV.
nft/costs.csv Sample captured fee metrics intended to document observed costs.
nft/Cargo.toml New crate metadata and Soroban SDK dependencies.
nft/Cargo.lock New lockfile capturing resolved dependency versions for the crate.

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

Comment on lines +17 to +24
fn test_event_u32() {
let env = Env::default();
let contract_id = env.register(TokenIdContract, ());
let client = TokenIdContractClient::new(&env, &contract_id);

client.event_u32(&123);
// Event was published (no assertion needed, just verify it doesn't panic)
}
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The event tests currently only check that invoking the method doesn’t panic. This won’t catch regressions where the event schema/topic/value changes or the event isn’t emitted. Consider asserting against env.events().all() (via soroban_sdk::testutils::Events) to verify the expected event was published for event_u32.

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +46
fn test_event_u256() {
let env = Env::default();
let contract_id = env.register(TokenIdContract, ());
let client = TokenIdContractClient::new(&env, &contract_id);

let token_id = U256::from_u32(&env, 456);
client.event_u256(&token_id);
// Event was published (no assertion needed, just verify it doesn't panic)
}
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

Same as test_event_u32: this test doesn’t assert anything about the emitted event. Adding an assertion on env.events().all() would ensure event_u256 actually publishes the correct event payload.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +25
# Deploy to testnet and invoke each function with --cost, recording to CSV
deploy-and-cost: build
@echo "=== Deploying ==="
stellar contract deploy \
--wasm target/wasm32v1-none/release/soroban_nft_contract.wasm \
--alias token-id-contract
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The comment says this target deploys to testnet, but the deploy command doesn’t specify a network. This can accidentally deploy to whatever network is configured locally. Consider explicitly passing --network testnet (and, if needed, --source ...) or otherwise making the intended network selection deterministic within the target.

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +50
INCLUSION_FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Inclusion Fee Charged:" | sed 's/.*Inclusion Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
NON_REFUNDABLE_CHARGED=$$(echo "$$OUTPUT" | grep "Non-Refundable Charged:" | sed 's/.*Non-Refundable Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
REFUNDABLE_CHARGED=$$(echo "$$OUTPUT" | grep "Refundable Charged:" | sed 's/.*Refundable Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
RESOURCE_FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Resource Fee Charged:" | sed 's/.*Resource Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Fee Charged:" | sed 's/.*Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The CSV output shows values like 100100 for inclusion_fee_charged and very large fee_charged numbers, which is consistent with multiple matching lines being concatenated (these assignments don’t use head -1/tail -1). To make parsing robust, select a single match (e.g., tail -1) or use a more precise extractor (awk/json output if available) for the *CHARGED fields.

Suggested change
INCLUSION_FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Inclusion Fee Charged:" | sed 's/.*Inclusion Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
NON_REFUNDABLE_CHARGED=$$(echo "$$OUTPUT" | grep "Non-Refundable Charged:" | sed 's/.*Non-Refundable Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
REFUNDABLE_CHARGED=$$(echo "$$OUTPUT" | grep "Refundable Charged:" | sed 's/.*Refundable Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
RESOURCE_FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Resource Fee Charged:" | sed 's/.*Resource Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Fee Charged:" | sed 's/.*Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
INCLUSION_FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Inclusion Fee Charged:" | tail -1 | sed 's/.*Inclusion Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
NON_REFUNDABLE_CHARGED=$$(echo "$$OUTPUT" | grep "Non-Refundable Charged:" | tail -1 | sed 's/.*Non-Refundable Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
REFUNDABLE_CHARGED=$$(echo "$$OUTPUT" | grep "Refundable Charged:" | tail -1 | sed 's/.*Refundable Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
RESOURCE_FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Resource Fee Charged:" | tail -1 | sed 's/.*Resource Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \
FEE_CHARGED=$$(echo "$$OUTPUT" | grep "Fee Charged:" | tail -1 | sed 's/.*Fee Charged: *\([0-9]*\).*/\1/' | tr -d '\n'); \

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +7
store_u32,28885,100,28785,5872,22913,100100,5872,11507,17379,1001737917479,11406
load_u32,,,,,,,,,,,
event_u32,13398,100,13298,2966,10332,100100,2966,567,3533,10035333633,9765
store_u256,32631,100,32531,6042,26489,100100,6042,14618,20660,1002066020760,11871
load_u256,,,,,,,,,,,
event_u256,13680,100,13580,3090,10490,100100,3090,704,3794,10037943894,9786
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The committed benchmark output appears internally inconsistent: inclusion_fee_charged is 100100 (looks like concatenated matches), fee_charged values are implausibly large, and the load_u32/load_u256 rows have all empty fee fields. If this CSV is meant to be a reference artifact, it should be regenerated after fixing the parsing in the Makefile (or removed from version control if it’s intended to be generated locally).

Suggested change
store_u32,28885,100,28785,5872,22913,100100,5872,11507,17379,1001737917479,11406
load_u32,,,,,,,,,,,
event_u32,13398,100,13298,2966,10332,100100,2966,567,3533,10035333633,9765
store_u256,32631,100,32531,6042,26489,100100,6042,14618,20660,1002066020760,11871
load_u256,,,,,,,,,,,
event_u256,13680,100,13580,3090,10490,100100,3090,704,3794,10037943894,9786

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +3
name = "soroban-nft-contract"
description = "SEP-50 Non-Fungible Token contract"
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

description says this is a “SEP-50 Non-Fungible Token contract”, but the crate currently only contains a small cost-comparison contract for u32 vs U256 token IDs. Consider updating the package name/description to reflect its actual purpose to avoid confusion for readers/users.

Suggested change
name = "soroban-nft-contract"
description = "SEP-50 Non-Fungible Token contract"
name = "soroban-nft-id-cost-comparison"
description = "Cost comparison Soroban contract for u32 vs U256 NFT token IDs (not a full SEP-50 implementation)"

Copilot uses AI. Check for mistakes.
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