Skip to content

Comments

JS SDK resource budget padding guide#2280

Closed
briwylde08 wants to merge 1 commit intomainfrom
padding
Closed

JS SDK resource budget padding guide#2280
briwylde08 wants to merge 1 commit intomainfrom
padding

Conversation

@briwylde08
Copy link
Contributor

Addresses: #2278

Copilot AI review requested due to automatic review settings February 24, 2026 17:32
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

This pull request adds documentation for handling JS SDK resource budget padding when contract CPU instruction usage approaches network limits. The JS SDK automatically adds ~23% padding to CPU instruction budgets, which can cause transactions to be rejected when simulated usage is near the network's hard limit.

Changes:

  • Added a new guide explaining the padding issue and providing a workaround
  • Updated the simulateTransaction deep dive to cross-reference the new guide
  • Added the new route to the routes configuration

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 11 comments.

File Description
routes.txt Adds route for the new resource budget padding guide
docs/build/guides/transactions/simulateTransaction-Deep-Dive.mdx Adds note about SDK padding behavior with link to detailed guide
docs/build/guides/transactions/resource-budget-padding.mdx New guide documenting the padding issue and providing workaround code

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

const data = assembled.transactionData.build();
const resources = data.resources();

if (resources.instructions() > 400_000_000) {
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The 400_000_000 instruction limit used in this conditional check conflicts with the official resource limits documentation at docs/networks/resource-limits-fees.mdx, which specifies "Max CPU instructions: 100 million" for per-transaction limits. This threshold should match the documented network limit.

Copilot uses AI. Check for mistakes.

if (resources.instructions() > 400_000_000) {
assembled.transactionData = new SorobanDataBuilder(data.toXDR()).setResources(
400_000_000, // cap to the network hard limit
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The comment uses 400_000_000 as the network hard limit, which conflicts with the official resource limits documentation at docs/networks/resource-limits-fees.mdx (specifies 100 million instructions). This value should match the documented network limit.

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +55
// Simulate the transaction
const simResult = await server.simulateTransaction(tx);

// Assemble using the simulation result
const assembled = StellarRpc.assembleTransaction(tx, simResult);

// Check if SDK padding pushed instructions over the network hard limit
const data = assembled.transactionData.build();
const resources = data.resources();

if (resources.instructions() > 400_000_000) {
assembled.transactionData = new SorobanDataBuilder(data.toXDR()).setResources(
400_000_000, // cap to the network hard limit
resources.diskReadBytes(),
resources.writeBytes(),
);
}

// Sign and submit as normal
const signedTx = assembled.build();
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The tx variable is used but not declared or shown in this code example. The example should either show how to construct the transaction or clarify that this code assumes a pre-existing transaction object.

Suggested change
// Simulate the transaction
const simResult = await server.simulateTransaction(tx);
// Assemble using the simulation result
const assembled = StellarRpc.assembleTransaction(tx, simResult);
// Check if SDK padding pushed instructions over the network hard limit
const data = assembled.transactionData.build();
const resources = data.resources();
if (resources.instructions() > 400_000_000) {
assembled.transactionData = new SorobanDataBuilder(data.toXDR()).setResources(
400_000_000, // cap to the network hard limit
resources.diskReadBytes(),
resources.writeBytes(),
);
}
// Sign and submit as normal
const signedTx = assembled.build();
// Assume `tx` is a pre-built Transaction and `server` is an RPC server instance.
// This helper shows how to cap the instruction budget near the network limit.
export async function submitWithInstructionCap(tx, server) {
// Simulate the transaction
const simResult = await server.simulateTransaction(tx);
// Assemble using the simulation result
const assembled = StellarRpc.assembleTransaction(tx, simResult);
// Check if SDK padding pushed instructions over the network hard limit
const data = assembled.transactionData.build();
const resources = data.resources();
if (resources.instructions() > 400_000_000) {
assembled.transactionData = new SorobanDataBuilder(data.toXDR()).setResources(
400_000_000, // cap to the network hard limit
resources.diskReadBytes(),
resources.writeBytes(),
);
}
// Sign and submit as normal
const signedTx = assembled.build();
return signedTx;
}

Copilot uses AI. Check for mistakes.

When the Stellar JavaScript SDK assembles a transaction from a simulation result, it automatically pads the CPU instruction budget by approximately 23% above what the simulation reported. This safety margin protects against minor undercounting between simulation and on-chain execution — for most contracts using 50M or 100M instructions, the padding is invisible.

However, if your simulated instruction usage is already close to the network's hard limit of **400 million instructions**, that padding will push the declared budget over the limit. The network rejects the transaction immediately, even though the actual on-chain execution would have succeeded.
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The stated limit of 400 million instructions conflicts with the official resource limits documentation at docs/networks/resource-limits-fees.mdx, which specifies "Max CPU instructions: 100 million" for per-transaction limits. This discrepancy needs to be resolved. Please verify the correct current network limit and ensure consistency across documentation. If the limit has been increased to 400 million, the resource-limits-fees.mdx file should be updated accordingly.

Copilot uses AI. Check for mistakes.

:::caution

Only apply this cap when your simulated instruction count is genuinely under 400M. Removing the SDK padding eliminates the guard against simulation undercounting. If actual on-chain execution costs more than the capped value, the transaction will still fail.
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The reference to "400M" conflicts with the official resource limits documentation at docs/networks/resource-limits-fees.mdx, which specifies "Max CPU instructions: 100 million" for per-transaction limits. This value should be consistent with the documented network limit.

Copilot uses AI. Check for mistakes.

:::note

In the JS SDK, `assembleTransaction` adds approximately 23% padding to the CPU instruction budget as a safety margin. If your contract's simulated instruction usage is already near the network's 400M hard limit, this padding can cause the transaction to be rejected. See [Adjusting resource budget padding near network limits](./resource-budget-padding.mdx) for how to handle this case.
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The reference to "400M hard limit" conflicts with the official resource limits documentation at docs/networks/resource-limits-fees.mdx, which specifies "Max CPU instructions: 100 million" for per-transaction limits. This should reference the correct documented network limit.

Suggested change
In the JS SDK, `assembleTransaction` adds approximately 23% padding to the CPU instruction budget as a safety margin. If your contract's simulated instruction usage is already near the network's 400M hard limit, this padding can cause the transaction to be rejected. See [Adjusting resource budget padding near network limits](./resource-budget-padding.mdx) for how to handle this case.
In the JS SDK, `assembleTransaction` adds approximately 23% padding to the CPU instruction budget as a safety margin. If your contract's simulated instruction usage is already near the network's 100M hard limit, this padding can cause the transaction to be rejected. See [Adjusting resource budget padding near network limits](./resource-budget-padding.mdx) for how to handle this case.

Copilot uses AI. Check for mistakes.

```javascript
import { SorobanDataBuilder, rpc as StellarRpc } from "@stellar/stellar-sdk";

Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The server variable is used but not declared or imported in this code example. The example should either import and initialize the server (e.g., const server = new Server(rpcUrl);) or clarify that this code assumes a pre-existing server instance.

Suggested change
const rpcUrl = "https://soroban-rpc.example.org"; // replace with your Soroban RPC endpoint
const server = new StellarRpc.Server(rpcUrl);

Copilot uses AI. Check for mistakes.
if (resources.instructions() > 400_000_000) {
assembled.transactionData = new SorobanDataBuilder(data.toXDR()).setResources(
400_000_000, // cap to the network hard limit
resources.diskReadBytes(),
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The method diskReadBytes() may be incorrect. In the Stellar XDR structure (SorobanResources), the field is named readBytes, not diskReadBytes. This should be verified against the actual JS SDK API documentation. If the SDK method is indeed readBytes() rather than diskReadBytes(), this will cause a runtime error.

Suggested change
resources.diskReadBytes(),
resources.readBytes(),

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +51
assembled.transactionData = new SorobanDataBuilder(data.toXDR()).setResources(
400_000_000, // cap to the network hard limit
resources.diskReadBytes(),
resources.writeBytes(),
);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The setResources() method signature and usage should be verified. No other documentation in the codebase shows this method being called with three positional parameters (instructions, readBytes, writeBytes). Please verify this matches the actual SorobanDataBuilder API in the JS SDK. The method signature may be different or may not exist.

Copilot uses AI. Check for mistakes.

| | Instructions |
| ----------------------- | -------------------- |
| Network hard limit | 400,000,000 |
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The 400,000,000 instruction limit conflicts with the official resource limits documentation at docs/networks/resource-limits-fees.mdx, which specifies "Max CPU instructions: 100 million" for per-transaction limits. This value should be consistent with the documented network limit.

Copilot uses AI. Check for mistakes.
@briwylde08 briwylde08 marked this pull request as draft February 24, 2026 17:41
@stellar-jenkins
Copy link

@briwylde08 briwylde08 closed this Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants