diff --git a/reports/llms-report.json b/reports/llms-report.json index 0ed858d2f18..84689f01051 100644 --- a/reports/llms-report.json +++ b/reports/llms-report.json @@ -1,22 +1,22 @@ { - "startedAt": "2025-12-10T23:13:13.756Z", + "startedAt": "2025-12-11T12:22:09.628Z", "siteBase": "https://docs.chain.link", "sections": [ { "section": "cre-go", - "pagesProcessed": 83, + "pagesProcessed": 84, "outputPath": "src/content/cre/llms-full-go.txt", - "bytes": 656030, - "prevBytes": 656030, + "bytes": 667067, + "prevBytes": 667067, "deltaBytes": 0 }, { "section": "cre-ts", - "pagesProcessed": 78, + "pagesProcessed": 79, "outputPath": "src/content/cre/llms-full-ts.txt", - "bytes": 612048, - "prevBytes": 612048, - "deltaBytes": 0 + "bytes": 623424, + "prevBytes": 623539, + "deltaBytes": -115 }, { "section": "vrf", @@ -123,5 +123,5 @@ "deltaBytes": 0 } ], - "finishedAt": "2025-12-10T23:13:17.715Z" + "finishedAt": "2025-12-11T12:22:14.025Z" } diff --git a/src/config/sidebar.ts b/src/config/sidebar.ts index c70e3d9195a..d9cadf64fc9 100644 --- a/src/config/sidebar.ts +++ b/src/config/sidebar.ts @@ -418,6 +418,11 @@ export const SIDEBAR: Partial> = { title: "TypeScript Runtime Environment", url: "cre/concepts/typescript-wasm-runtime", }, + { + title: "Finality & Confidence Levels", + url: "cre/concepts/finality", + highlightAsCurrent: ["cre/concepts/finality-go", "cre/concepts/finality-ts"], + }, ], }, { diff --git a/src/content/cre/concepts/finality-go.mdx b/src/content/cre/concepts/finality-go.mdx new file mode 100644 index 00000000000..662e0ce9b17 --- /dev/null +++ b/src/content/cre/concepts/finality-go.mdx @@ -0,0 +1,117 @@ +--- +section: cre +title: "Finality and Confidence Levels" +date: Last Modified +sdkLang: "go" +pageId: "concepts-finality" +metadata: + description: "Understand how CRE handles blockchain finality across different chains, including confidence levels, finality tags, and block depth configurations." + datePublished: "2025-12-10" + lastModified: "2025-12-10" +--- + +import { Aside, CopyText } from "@components" + +Finality determines when a blockchain transaction is considered irreversible. Until a block is finalized, it could be reorganized (replaced by a different block if the chain temporarily forks), which means any data you read from it might change. + +Different blockchains achieve finality in different ways and at different speeds. CRE abstracts these differences through **confidence levels**, allowing you to specify your finality requirements without needing to know the underlying chain-specific implementation. + +## Understanding CRE's finality model + +CRE provides three confidence levels for reading blockchain data and monitoring events. These levels work consistently across all supported chains. + +### The three confidence levels + +| Confidence Level | Description | Use Case | +| ---------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| **`LATEST`** | The most recent block. No finality guarantees—the block could still be reorganized. | Non-critical, time-sensitive operations where speed matters more than certainty. | +| **`SAFE`** | A block that is unlikely to be reorganized, but not yet fully finalized. | A balance between speed and security for most operations. | +| **`FINALIZED`** | A block that is considered irreversible. This is the safest option. | Critical operations where you need absolute certainty the data won't change. | + +**Choosing the right level:** + +- **`FINALIZED`** — Use for financial transactions, critical state updates, or when incorrect data could cause significant issues +- **`SAFE`** — Use when you need reasonable confidence without waiting for full finality (good for most monitoring/alerting) +- **`LATEST`** — Use for real-time dashboards or displays where speed matters more than guaranteed accuracy + +### How confidence levels map to chains + +**SAFE and LATEST:** + +CRE uses the chain's native `safe` and `latest` block tags respectively for all supported chains. + +**FINALIZED:** + +When you specify `FINALIZED` in your workflow, CRE automatically maps this to a native finality tag or a block depth threshold depending on the chain. + +| Chain | Finality Method | Block Depth | +| ------------------------------- | ---------------------------- | ----------- | +| Arbitrum One / Arbitrum Sepolia | Native `finalized` tag | — | +| Avalanche / Avalanche Fuji | Native `finalized` tag | — | +| Base / Base Sepolia | Native `finalized` tag | — | +| BNB Chain / BNB Testnet | Native `finalized` tag | — | +| Ethereum / Ethereum Sepolia | Native `finalized` tag | — | +| OP Mainnet / OP Sepolia | Native `finalized` tag | — | +| Polygon / Polygon Amoy | Block depth (500 blocks ago) | 500 | + +## Finality for chain reads + +Chain read operations ([`CallContract`](/cre/reference/sdk/evm-client-go#callcontract), [`BalanceAt`](/cre/reference/sdk/evm-client-go#balanceat), [`FilterLogs`](/cre/reference/sdk/evm-client-go#filterlogs), etc.) support confidence levels and custom block depths. + +### Using confidence levels + +For most read operations, use the standard confidence levels by passing `-2` (latest) or `-3` (finalized) as the `BlockNumber` parameter. If you don't specify a block number, CRE defaults to `LATEST`. + +**Note:** The `SAFE` confidence level is not available for chain reads—only `LATEST` and `FINALIZED` are supported. + +### Custom block depths + +For use cases requiring fixed confirmation thresholds or historical state verification, you can specify **any explicit block number** instead of using the predefined confidence levels. This enables you to: + +- Implement custom finality rules tailored to your risk profile (e.g., "always wait 1,000 blocks") +- Meet regulatory requirements that mandate fixed, auditable confirmation thresholds +- Query historical state at specific past block heights for analysis or verification + +**When to use custom block depths:** + +- **Regulatory compliance** — Your interactions require provable, fixed confirmation thresholds for auditors +- **Changing chain parameters** — The chain's finality definition may change, but your security model must remain constant +- **Historical verification** — You need to verify state at a specific moment + +**Implementation:** + +You can pass any `*big.Int` directly as the `BlockNumber` parameter. The SDK accepts both special values (like `-2` for latest, `-3` for finalized) and positive integers for explicit block heights. See [Onchain Read](/cre/guides/workflow/using-evm-client/onchain-read-go#custom-block-depths) for examples. + +## Finality for chain writes + +Chain write operations return a [`WriteReportReply`](/cre/reference/sdk/evm-client-go#evmwritereportreply) when the transaction is included in a block, not when it reaches finality. + +### What a successful response means + +When [`WriteReportReply`](/cre/reference/sdk/evm-client-go#evmwritereportreply) returns with `TxStatus` equal to `SUCCESS`: + +- Your transaction was **included in a block** +- The transaction is **not necessarily finalized** yet + +The reply is returned as soon as the transaction appears in a block, not when the block reaches finality. This is important for time-sensitive workflows, but it means the transaction could still be reorganized. + +### Reorg handling + +If a block containing your transaction is reorganized: + +- CRE's Transaction Manager (TXM) automatically resubmits your transaction +- Gas bumping is applied as needed to ensure the transaction is included +- **Important:** The transaction hash may change during resubmission +- You are not automatically notified if the hash changes + + + +## Finality for event triggers + +EVM Log Triggers must use the three confidence levels (`LATEST`, `SAFE`, or `FINALIZED`). Custom block depths are not supported for triggers. + +By default, triggers use `SAFE` if no confidence level is specified. For details on configuring trigger confidence levels, see [EVM Log Trigger](/cre/reference/sdk/triggers/evm-log-trigger-go#evmfilterlogtriggerrequest). diff --git a/src/content/cre/concepts/finality-ts.mdx b/src/content/cre/concepts/finality-ts.mdx new file mode 100644 index 00000000000..b1f71c0ea63 --- /dev/null +++ b/src/content/cre/concepts/finality-ts.mdx @@ -0,0 +1,117 @@ +--- +section: cre +title: "Finality and Confidence Levels" +date: Last Modified +sdkLang: "ts" +pageId: "concepts-finality" +metadata: + description: "Understand how CRE handles blockchain finality across different chains, including confidence levels, finality tags, and block depth configurations." + datePublished: "2025-12-10" + lastModified: "2025-12-10" +--- + +import { Aside, CopyText } from "@components" + +Finality determines when a blockchain transaction is considered irreversible. Until a block is finalized, it could be reorganized (replaced by a different block if the chain temporarily forks), which means any data you read from it might change. + +Different blockchains achieve finality in different ways and at different speeds. CRE abstracts these differences through **confidence levels**, allowing you to specify your finality requirements without needing to know the underlying chain-specific implementation. + +## Understanding CRE's finality model + +CRE provides three confidence levels for reading blockchain data and monitoring events. These levels work consistently across all supported chains. + +### The three confidence levels + +| Confidence Level | Description | Use Case | +| ---------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| **`LATEST`** | The most recent block. No finality guarantees—the block could still be reorganized. | Non-critical, time-sensitive operations where speed matters more than certainty. | +| **`SAFE`** | A block that is unlikely to be reorganized, but not yet fully finalized. | A balance between speed and security for most operations. | +| **`FINALIZED`** | A block that is considered irreversible. This is the safest option. | Critical operations where you need absolute certainty the data won't change. | + +**Choosing the right level:** + +- **`FINALIZED`** — Use for financial transactions, critical state updates, or when incorrect data could cause significant issues +- **`SAFE`** — Use when you need reasonable confidence without waiting for full finality (good for most monitoring/alerting) +- **`LATEST`** — Use for real-time dashboards or displays where speed matters more than guaranteed accuracy + +### How confidence levels map to chains + +**SAFE and LATEST:** + +CRE uses the chain's native `safe` and `latest` block tags respectively for all supported chains. + +**FINALIZED:** + +When you specify `FINALIZED` in your workflow, CRE automatically maps this to its finality method—whether it uses the native finality tag or block depth (with the number of blocks specified for block depth). + +| Chain | Finality Method | +| ------------------------------- | ------------------------ | +| Arbitrum One / Arbitrum Sepolia | Native `finalized` tag | +| Avalanche / Avalanche Fuji | Native `finalized` tag | +| Base / Base Sepolia | Native `finalized` tag | +| BNB Chain / BNB Testnet | Native `finalized` tag | +| Ethereum / Ethereum Sepolia | Native `finalized` tag | +| OP Mainnet / OP Sepolia | Native `finalized` tag | +| Polygon / Polygon Amoy | Block depth (500 blocks) | + +## Finality for chain reads + +Chain read operations ([`CallContract`](/cre/reference/sdk/evm-client-ts#callcontract), [`BalanceAt`](/cre/reference/sdk/evm-client-ts#balanceat), [`FilterLogs`](/cre/reference/sdk/evm-client-ts#filterlogs), etc.) support confidence levels and custom block depths. + +### Using confidence levels + +For most read operations, use the standard confidence levels by passing [`LATEST_BLOCK_NUMBER`](/cre/reference/sdk/evm-client-ts#latest_block_number) or [`LAST_FINALIZED_BLOCK_NUMBER`](/cre/reference/sdk/evm-client-ts#last_finalized_block_number) as the `blockNumber` parameter. If you don't specify a block number, CRE defaults to `LATEST`. + +**Note:** The `SAFE` confidence level is not available for chain reads—only `LATEST` and `FINALIZED` are supported. + +### Custom block depths + +For use cases requiring fixed confirmation thresholds or historical state verification, you can specify **any explicit block number** instead of using the predefined confidence levels. This enables you to: + +- Implement custom finality rules tailored to your risk profile (e.g., "always wait 1,000 blocks") +- Meet regulatory requirements that mandate fixed, auditable confirmation thresholds +- Query historical state at specific past block heights for analysis or verification + +**When to use custom block depths:** + +- **Regulatory compliance** — Your interactions require provable, fixed confirmation thresholds for auditors +- **Changing chain parameters** — The chain's finality definition may change, but your security model must remain constant +- **Historical verification** — You need to verify state at a specific moment + +**Implementation:** + +Block numbers must be provided as `BigIntJson` objects. See [Onchain Read](/cre/guides/workflow/using-evm-client/onchain-read-ts#custom-block-depths) for the conversion pattern and examples. + +## Finality for chain writes + +Chain write operations return a [`WriteReportReply`](/cre/reference/sdk/evm-client-ts#writereportreply) when the transaction is included in a block, not when it reaches finality. + +### What a successful response means + +When [`WriteReportReply`](/cre/reference/sdk/evm-client-ts#writereportreply) returns with `txStatus` equal to `TX_STATUS_SUCCESS`: + +- Your transaction was **included in a block** +- The transaction is **not necessarily finalized** yet + +The reply is returned as soon as the transaction appears in a block, not when the block reaches finality. This is important for time-sensitive workflows, but it means the transaction could still be reorganized. + +### Reorg handling + +If a block containing your transaction is reorganized: + +- CRE's Transaction Manager (TXM) automatically resubmits your transaction +- Gas bumping is applied as needed to ensure the transaction is included +- **Important:** The transaction hash may change during resubmission +- You are not automatically notified if the hash changes + + + +## Finality for event triggers + +EVM Log Triggers must use the three confidence levels (`LATEST`, `SAFE`, or `FINALIZED`). Custom block depths are not supported for triggers. + +By default, triggers use `SAFE` if no confidence level is specified. For details on configuring trigger confidence levels, see [EVM Log Trigger](/cre/reference/sdk/triggers/evm-log-trigger-ts#configuration). diff --git a/src/content/cre/guides/workflow/using-evm-client/onchain-read-go.mdx b/src/content/cre/guides/workflow/using-evm-client/onchain-read-go.mdx index 69e189775b5..20d9f6e0228 100644 --- a/src/content/cre/guides/workflow/using-evm-client/onchain-read-go.mdx +++ b/src/content/cre/guides/workflow/using-evm-client/onchain-read-go.mdx @@ -7,7 +7,7 @@ date: Last Modified metadata: description: "Read data from smart contracts in Go: learn to call view functions and fetch verified blockchain state in your workflows." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2025-12-10" --- import { Aside } from "@components" @@ -153,28 +153,73 @@ When calling contract read methods, you must specify a block number. There are t ### Using magic numbers -- **Finalized block**: Use `big.NewInt(-3)` to read from the latest finalized block +- **Finalized block**: Use `big.NewInt(-3)` to read from the latest finalized block (recommended for production) - **Latest block**: Use `big.NewInt(-2)` to read from the latest block -- **Specific block**: Use `big.NewInt(blockNumber)` to read from a specific block -### Using rpc constants (alternative) +For explicit block numbers, see [Custom block depths](#custom-block-depths) below. -You can also use constants from the `go-ethereum/rpc` package for better readability: +### Custom block depths + +For use cases requiring fixed confirmation thresholds (e.g., regulatory compliance) or historical state verification, you can specify an exact block number. + +**Example 1 - Read from a specific historical block**: + +```go +// Read from block 12345678 +specificBlock := big.NewInt(12345678) +value, err := storageContract.Get(runtime, specificBlock).Await() +if err != nil { + return nil, fmt.Errorf("failed to read from specific block: %w", err) +} +``` + +**Example 2 - Read from 500 blocks ago from latest block**: ```go import ( - "math/big" - "github.com/ethereum/go-ethereum/rpc" + pb "github.com/smartcontractkit/chainlink-protos/cre/go/values/pb" ) -// For latest block -reqBlockNumber := big.NewInt(rpc.LatestBlockNumber.Int64()) +// Helper to convert protobuf BigInt to standard library big.Int +func pbBigIntToBigInt(pb *pb.BigInt) *big.Int { + if pb == nil { + return nil + } + result := new(big.Int).SetBytes(pb.AbsVal) + if pb.Sign < 0 { + result.Neg(result) + } + return result +} + +// Get the latest block number +latestHeader, err := evmClient.HeaderByNumber(runtime, &evm.HeaderByNumberRequest{}).Await() +if err != nil { + return nil, fmt.Errorf("failed to get latest block: %w", err) +} + +// Convert protobuf BigInt to standard library big.Int +latestBlockNum := pbBigIntToBigInt(latestHeader.Header.BlockNumber) +customDepth := big.NewInt(500) +customBlock := new(big.Int).Sub(latestBlockNum, customDepth) -// For finalized block -reqBlockNumber := big.NewInt(rpc.FinalizedBlockNumber.Int64()) +// Use the custom block number with the contract binding +value, err := storageContract.Get(runtime, customBlock).Await() +if err != nil { + return nil, fmt.Errorf("failed to read from custom block: %w", err) +} ``` -Both approaches are equivalent - use whichever you find more readable in your code. +**Understanding the conversion:** + +The `pbBigIntToBigInt` helper converts the SDK's protobuf `*pb.BigInt` type (which stores the value as `AbsVal []byte` and `Sign int64`) to Go's standard library `*big.Int`. This allows you to perform arithmetic operations like subtracting 500 blocks. + + + +See [Finality and Confidence Levels](/cre/concepts/finality-go) for more details on when to use custom block depths. ## Complete example diff --git a/src/content/cre/guides/workflow/using-evm-client/onchain-read-ts.mdx b/src/content/cre/guides/workflow/using-evm-client/onchain-read-ts.mdx index 5634f0b6af8..cfbab411819 100644 --- a/src/content/cre/guides/workflow/using-evm-client/onchain-read-ts.mdx +++ b/src/content/cre/guides/workflow/using-evm-client/onchain-read-ts.mdx @@ -7,7 +7,7 @@ date: Last Modified metadata: description: "Read data from smart contracts in TypeScript: learn to call view functions and fetch verified blockchain state in your workflows." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2025-12-10" --- import { Aside } from "@components" @@ -168,7 +168,7 @@ When calling `callContract()`, you can specify which block to read from: - **`LAST_FINALIZED_BLOCK_NUMBER`**: Read from the last finalized block (recommended for production) - **`LATEST_BLOCK_NUMBER`**: Read from the latest block -- **Specific block**: Use an object with `{ absVal: "base64EncodedNumber", sign: "1" }` format +- **Custom block number**: Use a `BigIntJson` object for custom finality depths or historical queries ```typescript import { LAST_FINALIZED_BLOCK_NUMBER, LATEST_BLOCK_NUMBER } from "@chainlink/cre-sdk" @@ -186,6 +186,54 @@ const contractCall = evmClient.callContract(runtime, { }).result() ``` +#### Custom block depths + +For use cases requiring fixed confirmation thresholds (e.g., regulatory compliance) or historical state verification, you can specify an exact block number. + +**Example 1 - Read from a specific historical block**: + +```typescript +import { blockNumber } from '@chainlink/cre-sdk' + +const historicalBlock = 9767655n +const contractCall = evmClient.callContract(runtime, { + call: encodeCallMsg({...}), + blockNumber: blockNumber(historicalBlock), +}).result() +``` + +**Example 2 - Read from 500 blocks ago for custom finality**: + +```typescript +import { protoBigIntToBigint, blockNumber } from '@chainlink/cre-sdk' + +// Get the latest block number +const latestHeader = evmClient.headerByNumber(runtime, {}).result() +if (!latestHeader.header?.blockNumber) { + throw new Error("Failed to get latest block number") +} + +// Convert protobuf BigInt to native bigint and calculate custom block +const latestBlockNum = protoBigIntToBigint(latestHeader.header.blockNumber) +const customBlock = latestBlockNum - 500n + +// Call the contract at the custom block height +const contractCall = evmClient.callContract(runtime, { + call: encodeCallMsg({...}), + blockNumber: blockNumber(customBlock), +}).result() +``` + +**Helper functions:** + +The SDK provides two helper functions for working with block numbers: + +- **`protoBigIntToBigint(pb)`** — Converts a protobuf `BigInt` (returned by SDK methods like `headerByNumber`) to a native JavaScript `bigint`. Use this when you need to perform arithmetic on block numbers. + +- **`blockNumber(n)`** — Converts a native `bigint`, `number`, or `string` to the protobuf `BigInt` JSON format required by SDK methods. This is an alias for `bigintToProtoBigInt`. + +See [Finality and Confidence Levels](/cre/concepts/finality-ts) for more details on when to use custom block depths. + ### Encoding call messages with `encodeCallMsg()` The `encodeCallMsg()` helper converts your hex-formatted call data into the base64 format required by the EVM capability: diff --git a/src/content/cre/llms-full-go.txt b/src/content/cre/llms-full-go.txt index 7afe0b87947..5488008f646 100644 --- a/src/content/cre/llms-full-go.txt +++ b/src/content/cre/llms-full-go.txt @@ -8323,6 +8323,116 @@ cre version v1.0.2 --- +# Finality and Confidence Levels +Source: https://docs.chain.link/cre/concepts/finality-go +Last Updated: 2025-12-10 + +Finality determines when a blockchain transaction is considered irreversible. Until a block is finalized, it could be reorganized (replaced by a different block if the chain temporarily forks), which means any data you read from it might change. + +Different blockchains achieve finality in different ways and at different speeds. CRE abstracts these differences through **confidence levels**, allowing you to specify your finality requirements without needing to know the underlying chain-specific implementation. + +## Understanding CRE's finality model + +CRE provides three confidence levels for reading blockchain data and monitoring events. These levels work consistently across all supported chains. + +### The three confidence levels + +| Confidence Level | Description | Use Case | +| ---------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| **`LATEST`** | The most recent block. No finality guarantees—the block could still be reorganized. | Non-critical, time-sensitive operations where speed matters more than certainty. | +| **`SAFE`** | A block that is unlikely to be reorganized, but not yet fully finalized. | A balance between speed and security for most operations. | +| **`FINALIZED`** | A block that is considered irreversible. This is the safest option. | Critical operations where you need absolute certainty the data won't change. | + +**Choosing the right level:** + +- **`FINALIZED`** — Use for financial transactions, critical state updates, or when incorrect data could cause significant issues +- **`SAFE`** — Use when you need reasonable confidence without waiting for full finality (good for most monitoring/alerting) +- **`LATEST`** — Use for real-time dashboards or displays where speed matters more than guaranteed accuracy + +### How confidence levels map to chains + +**SAFE and LATEST:** + +CRE uses the chain's native `safe` and `latest` block tags respectively for all supported chains. + +**FINALIZED:** + +When you specify `FINALIZED` in your workflow, CRE automatically maps this to a native finality tag or a block depth threshold depending on the chain. + +| Chain | Finality Method | Block Depth | +| ------------------------------- | ---------------------------- | ----------- | +| Arbitrum One / Arbitrum Sepolia | Native `finalized` tag | — | +| Avalanche / Avalanche Fuji | Native `finalized` tag | — | +| Base / Base Sepolia | Native `finalized` tag | — | +| BNB Chain / BNB Testnet | Native `finalized` tag | — | +| Ethereum / Ethereum Sepolia | Native `finalized` tag | — | +| OP Mainnet / OP Sepolia | Native `finalized` tag | — | +| Polygon / Polygon Amoy | Block depth (500 blocks ago) | 500 | + +## Finality for chain reads + +Chain read operations ([`CallContract`](/cre/reference/sdk/evm-client-go#callcontract), [`BalanceAt`](/cre/reference/sdk/evm-client-go#balanceat), [`FilterLogs`](/cre/reference/sdk/evm-client-go#filterlogs), etc.) support confidence levels and custom block depths. + +### Using confidence levels + +For most read operations, use the standard confidence levels by passing `-2` (latest) or `-3` (finalized) as the `BlockNumber` parameter. If you don't specify a block number, CRE defaults to `LATEST`. + +**Note:** The `SAFE` confidence level is not available for chain reads—only `LATEST` and `FINALIZED` are supported. + +### Custom block depths + +For use cases requiring fixed confirmation thresholds or historical state verification, you can specify **any explicit block number** instead of using the predefined confidence levels. This enables you to: + +- Implement custom finality rules tailored to your risk profile (e.g., "always wait 1,000 blocks") +- Meet regulatory requirements that mandate fixed, auditable confirmation thresholds +- Query historical state at specific past block heights for analysis or verification + +**When to use custom block depths:** + +- **Regulatory compliance** — Your interactions require provable, fixed confirmation thresholds for auditors +- **Changing chain parameters** — The chain's finality definition may change, but your security model must remain constant +- **Historical verification** — You need to verify state at a specific moment + +**Implementation:** + +You can pass any `*big.Int` directly as the `BlockNumber` parameter. The SDK accepts both special values (like `-2` for latest, `-3` for finalized) and positive integers for explicit block heights. See [Onchain Read](/cre/guides/workflow/using-evm-client/onchain-read-go#custom-block-depths) for examples. + +## Finality for chain writes + +Chain write operations return a [`WriteReportReply`](/cre/reference/sdk/evm-client-go#evmwritereportreply) when the transaction is included in a block, not when it reaches finality. + +### What a successful response means + +When [`WriteReportReply`](/cre/reference/sdk/evm-client-go#evmwritereportreply) returns with `TxStatus` equal to `SUCCESS`: + +- Your transaction was **included in a block** +- The transaction is **not necessarily finalized** yet + +The reply is returned as soon as the transaction appears in a block, not when the block reaches finality. This is important for time-sensitive workflows, but it means the transaction could still be reorganized. + +### Reorg handling + +If a block containing your transaction is reorganized: + +- CRE's Transaction Manager (TXM) automatically resubmits your transaction +- Gas bumping is applied as needed to ensure the transaction is included +- **Important:** The transaction hash may change during resubmission +- You are not automatically notified if the hash changes + + + +## Finality for event triggers + +EVM Log Triggers must use the three confidence levels (`LATEST`, `SAFE`, or `FINALIZED`). Custom block depths are not supported for triggers. + +By default, triggers use `SAFE` if no confidence level is specified. For details on configuring trigger confidence levels, see [EVM Log Trigger](/cre/reference/sdk/triggers/evm-log-trigger-go#evmfilterlogtriggerrequest). + +--- + # Avoiding Non-Determinism in Workflows Source: https://docs.chain.link/cre/concepts/non-determinism-go Last Updated: 2025-11-04 @@ -10023,7 +10133,7 @@ func main() { # Onchain Read Source: https://docs.chain.link/cre/guides/workflow/using-evm-client/onchain-read-go -Last Updated: 2025-11-04 +Last Updated: 2025-12-10 This guide explains how to read data from a smart contract from within your CRE workflow. The process uses [generated bindings](/cre/guides/workflow/using-evm-client/generating-bindings) and the SDK's [`evm.Client`](/cre/reference/sdk/evm-client) to create a simple, type-safe developer experience. @@ -10166,28 +10276,73 @@ When calling contract read methods, you must specify a block number. There are t ### Using magic numbers -- **Finalized block**: Use `big.NewInt(-3)` to read from the latest finalized block +- **Finalized block**: Use `big.NewInt(-3)` to read from the latest finalized block (recommended for production) - **Latest block**: Use `big.NewInt(-2)` to read from the latest block -- **Specific block**: Use `big.NewInt(blockNumber)` to read from a specific block -### Using rpc constants (alternative) +For explicit block numbers, see [Custom block depths](#custom-block-depths) below. + +### Custom block depths + +For use cases requiring fixed confirmation thresholds (e.g., regulatory compliance) or historical state verification, you can specify an exact block number. + +**Example 1 - Read from a specific historical block**: + +```go +// Read from block 12345678 +specificBlock := big.NewInt(12345678) +value, err := storageContract.Get(runtime, specificBlock).Await() +if err != nil { + return nil, fmt.Errorf("failed to read from specific block: %w", err) +} +``` -You can also use constants from the `go-ethereum/rpc` package for better readability: +**Example 2 - Read from 500 blocks ago from latest block**: ```go import ( - "math/big" - "github.com/ethereum/go-ethereum/rpc" + pb "github.com/smartcontractkit/chainlink-protos/cre/go/values/pb" ) -// For latest block -reqBlockNumber := big.NewInt(rpc.LatestBlockNumber.Int64()) +// Helper to convert protobuf BigInt to standard library big.Int +func pbBigIntToBigInt(pb *pb.BigInt) *big.Int { + if pb == nil { + return nil + } + result := new(big.Int).SetBytes(pb.AbsVal) + if pb.Sign < 0 { + result.Neg(result) + } + return result +} + +// Get the latest block number +latestHeader, err := evmClient.HeaderByNumber(runtime, &evm.HeaderByNumberRequest{}).Await() +if err != nil { + return nil, fmt.Errorf("failed to get latest block: %w", err) +} + +// Convert protobuf BigInt to standard library big.Int +latestBlockNum := pbBigIntToBigInt(latestHeader.Header.BlockNumber) +customDepth := big.NewInt(500) +customBlock := new(big.Int).Sub(latestBlockNum, customDepth) -// For finalized block -reqBlockNumber := big.NewInt(rpc.FinalizedBlockNumber.Int64()) +// Use the custom block number with the contract binding +value, err := storageContract.Get(runtime, customBlock).Await() +if err != nil { + return nil, fmt.Errorf("failed to read from custom block: %w", err) +} ``` -Both approaches are equivalent - use whichever you find more readable in your code. +**Understanding the conversion:** + +The `pbBigIntToBigInt` helper converts the SDK's protobuf `*pb.BigInt` type (which stores the value as `AbsVal []byte` and `Sign int64`) to Go's standard library `*big.Int`. This allows you to perform arithmetic operations like subtracting 500 blocks. + + + +See [Finality and Confidence Levels](/cre/concepts/finality-go) for more details on when to use custom block depths. ## Complete example @@ -13462,10 +13617,10 @@ func (c *Client) CallContract(runtime cre.Runtime, input *CallContractRequest) c This is the main input object for the `CallContract` function. It acts as a wrapper for the call message and an optional block number. -| Field | Type | Description | -| ------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `Call` | `*evm.CallMsg` | Contains the actual details of the function call you want to make. | -| `BlockNumber` | `*pb.BigInt` | Optional. The block number to query. Defaults to `latest`. Use `-2` for `latest` (the most recent block, which may be subject to re-orgs) or `-3` for `finalized` (a block that is considered immutable and safe from re-orgs). | +| Field | Type | Description | +| ------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Call` | `*evm.CallMsg` | Contains the actual details of the function call you want to make. | +| `BlockNumber` | `*pb.BigInt` | Optional. The block number to query. Accepts:
• `nil` or `-2` (default): `latest` — the most recent block
• `-3`: `finalized` — an immutable block
• **Any positive integer**: an explicit block height (see [Custom Block Depths](/cre/guides/workflow/using-evm-client/onchain-read-go#custom-block-depths) for examples)

See [Finality and Confidence Levels](/cre/concepts/finality-go) for finality strategies. | #### `evm.CallMsg` @@ -13497,10 +13652,10 @@ func (c *Client) BalanceAt(runtime cre.Runtime, input *BalanceAtRequest) cre.Pro #### `evm.BalanceAtRequest` -| Field | Type | Description | -| ------------- | ------------ | ---------------------------------------------------------- | -| `Account` | `[]byte` | The 20-byte address of the account to query. | -| `BlockNumber` | `*pb.BigInt` | Optional. The block number to query. Defaults to `latest`. | +| Field | Type | Description | +| ------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | `[]byte` | The 20-byte address of the account to query. | +| `BlockNumber` | `*pb.BigInt` | Optional. The block number to query. Accepts `nil` or `-2` for `latest` (default), `-3` for `finalized`, or any positive integer for an explicit block height (see [Custom Block Depths](/cre/guides/workflow/using-evm-client/onchain-read-go#custom-block-depths)). See [Finality and Confidence Levels](/cre/concepts/finality-go). | #### `evm.BalanceAtReply` @@ -13586,9 +13741,9 @@ func (c *Client) HeaderByNumber(runtime cre.Runtime, input *HeaderByNumberReques #### `evm.HeaderByNumberRequest` -| Field | Type | Description | -| ------------- | ------------ | -------------------------------------------------------------------------- | -| `BlockNumber` | `*pb.BigInt` | The number of the block to retrieve. If `nil`, retrieves the latest block. | +| Field | Type | Description | +| ------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `BlockNumber` | `*pb.BigInt` | The number of the block to retrieve. Accepts `nil` for `latest` (default), `-2` for `latest`, `-3` for `finalized`, or any positive integer for an explicit block height (see [Custom Block Depths](/cre/guides/workflow/using-evm-client/onchain-read-go#custom-block-depths)). See [Finality and Confidence Levels](/cre/concepts/finality-go). | #### `evm.HeaderByNumberReply` @@ -13652,10 +13807,11 @@ func (c *Client) WriteReport(runtime cre.Runtime, input *WriteCreReportRequest) A **chain selector** is a unique identifier for a blockchain network used throughout the CRE platform. The same chain can be referenced in three different ways depending on the context. All three formats are equivalent and refer to the same blockchain. + ### Understanding the three formats @@ -14213,9 +14369,9 @@ The configuration struct for the EVM log trigger. | `Topics` | `[]*evm.TopicValues` | A fixed 4-element array to filter event topics. The first element contains event signatures, and the next three elements contain indexed argument values. An empty array element acts as a wildcard. | | `Confidence` | `ConfidenceLevel` | The block confirmation level to monitor. Can be: | - -