Skip to content

Commit 20a68e4

Browse files
authored
MockKeystoneForwarder/Permissioning in simulation clarifications (smartcontractkit#3167)
* MockForwarder override clarifications * clarifications
1 parent 4899cb8 commit 20a68e4

File tree

6 files changed

+200
-101
lines changed

6 files changed

+200
-101
lines changed

reports/llms-report.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
{
2-
"startedAt": "2025-11-12T18:56:10.721Z",
2+
"startedAt": "2025-11-13T13:44:50.973Z",
33
"siteBase": "https://docs.chain.link",
44
"sections": [
55
{
66
"section": "cre-go",
77
"pagesProcessed": 84,
88
"outputPath": "src/content/cre/llms-full-go.txt",
9-
"bytes": 631240,
10-
"prevBytes": 631240,
11-
"deltaBytes": 0
9+
"bytes": 632740,
10+
"prevBytes": 631974,
11+
"deltaBytes": 766
1212
},
1313
{
1414
"section": "cre-ts",
1515
"pagesProcessed": 79,
1616
"outputPath": "src/content/cre/llms-full-ts.txt",
17-
"bytes": 586661,
18-
"prevBytes": 586661,
19-
"deltaBytes": 0
17+
"bytes": 588161,
18+
"prevBytes": 587395,
19+
"deltaBytes": 766
2020
},
2121
{
2222
"section": "vrf",
@@ -31,8 +31,8 @@
3131
"pagesProcessed": 243,
3232
"outputPath": "src/content/ccip/llms-full.txt",
3333
"bytes": 2625022,
34-
"prevBytes": 2639701,
35-
"deltaBytes": -14679
34+
"prevBytes": 2625022,
35+
"deltaBytes": 0
3636
},
3737
{
3838
"section": "data-feeds",
@@ -123,5 +123,5 @@
123123
"deltaBytes": 0
124124
}
125125
],
126-
"finishedAt": "2025-11-12T18:56:14.180Z"
126+
"finishedAt": "2025-11-13T13:44:55.838Z"
127127
}

src/content/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts.mdx

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ This guide explains how to build a consumer contract that can securely receive a
1919
- [Core Concepts: The Onchain Data Flow](#1-core-concepts-the-onchain-data-flow)
2020
- [The IReceiver Standard](#2-the-ireceiver-standard)
2121
- [Using IReceiverTemplate](#3-using-ireceivertemplate)
22-
- [Advanced Usage](#4-advanced-usage-optional)
23-
- [Complete Examples](#5-complete-examples)
22+
- [Working with Simulation](#4-working-with-simulation)
23+
- [Advanced Usage](#5-advanced-usage-optional)
24+
- [Complete Examples](#6-complete-examples)
2425

2526
## 1. Core Concepts: The Onchain Data Flow
2627

@@ -181,8 +182,6 @@ abstract contract IReceiverTemplate is IReceiver, Ownable {
181182

182183
### 3.3 Quick Start
183184

184-
**Step 1: Inherit and implement your business logic**
185-
186185
The simplest way to use `IReceiverTemplate` is to inherit from it and implement the `_processReport` function:
187186

188187
```solidity
@@ -206,12 +205,15 @@ contract MyConsumer is IReceiverTemplate {
206205
}
207206
```
208207

209-
### 3.4 Configuring Security
210-
211-
**Step 2: Configure permissions (optional)**
208+
### 3.4 Configuring Permissions
212209

213210
After deploying your contract, the owner can enable any combination of security checks using the setter functions.
214211

212+
{/* prettier-ignore */}
213+
<Aside type="caution" title="For simulation">
214+
When using `cre workflow simulate`, **do not configure metadata-based validation checks** (`setExpectedWorkflowId`, `setExpectedAuthor`, `setExpectedWorkflowName`). The simulation uses a `MockForwarder` that doesn't provide this metadata. See [Working with Simulation](#4-working-with-simulation) for details.
215+
</Aside>
216+
215217
{/* prettier-ignore */}
216218
<Aside type="tip" title="Finding forwarder addresses">
217219
For a complete list of `KeystoneForwarder` contract addresses on all supported networks, see [Supported Networks](/cre/guides/workflow/using-evm-client/supported-networks).
@@ -254,9 +256,58 @@ myConsumer.setExpectedWorkflowName(bytes10(0));
254256
- Your business logic in `_processReport`
255257
- (Optional) Configure permissions after deployment using setter functions
256258

257-
## 4. Advanced Usage (Optional)
259+
## 4. Working with Simulation
260+
261+
When you run `cre workflow simulate`, your workflow interacts with a **`MockKeystoneForwarder`** contract that does not provide workflow metadata (`workflow_name`, `workflow_owner`).
262+
263+
<Aside type="caution" title="Temporary limitation">
264+
This is a **temporary limitation** until the `MockKeystoneForwarder` is updated to provide full metadata.
265+
</Aside>
266+
267+
### Forwarder address validation
268+
269+
You **can** configure the forwarder address check during simulation:
270+
271+
```solidity
272+
// Optional: Validate the MockKeystoneForwarder address during simulation
273+
myConsumer.setForwarderAddress(0xMockForwarderAddress);
274+
```
275+
276+
{/* prettier-ignore */}
277+
<Aside type="caution" title="Important: Different addresses for simulation vs production">
278+
The `MockKeystoneForwarder` address used during simulation is **different** from the `KeystoneForwarder` address used by deployed workflows. If you configure the forwarder address for simulation, remember to update it to the production `KeystoneForwarder` address after deploying. See [Supported Networks](/cre/guides/workflow/using-evm-client/supported-networks) for forwarder addresses.
279+
</Aside>
280+
281+
### Metadata-based validation
282+
283+
**Do not configure these validation checks** during simulation - they require metadata that `MockKeystoneForwarder` doesn't provide:
284+
285+
- `setExpectedWorkflowId()`
286+
- `setExpectedAuthor()`
287+
- `setExpectedWorkflowName()`
288+
289+
Setting any of these will cause your simulation to fail.
258290

259-
### 4.1 Custom Validation Logic
291+
### After deployment
292+
293+
Once you deploy your workflow:
294+
295+
1. Update the forwarder address to the real `KeystoneForwarder` (if you configured it for simulation)
296+
1. Configure additional metadata-based validation as needed
297+
298+
```solidity
299+
// Update to production KeystoneForwarder address
300+
myConsumer.setForwarderAddress(0xF8344CFd5c43616a4366C34E3EEE75af79a74482); // Example: Ethereum Sepolia
301+
302+
// Now you can enable metadata-based validation
303+
myConsumer.setExpectedWorkflowId(0xYourWorkflowId);
304+
```
305+
306+
See [Configuring Permissions](#34-configuring-permissions) for complete details.
307+
308+
## 5. Advanced Usage (Optional)
309+
310+
### 5.1 Custom Validation Logic
260311

261312
You can override `onReport` to add your own validation logic before or after the standard checks:
262313

@@ -295,7 +346,7 @@ contract AdvancedConsumer is IReceiverTemplate {
295346
}
296347
```
297348

298-
### 4.2 Using Metadata Fields in Your Logic
349+
### 5.2 Using Metadata Fields in Your Logic
299350

300351
The `_decodeMetadata` helper function is available for use in your `_processReport` implementation. This allows you to access workflow metadata for custom business logic:
301352

@@ -323,25 +374,7 @@ contract MetadataAwareConsumer is IReceiverTemplate {
323374
For production systems requiring even more sophisticated access control (such as role-based permissions or two-step ownership transfer), consider extending the template to use OpenZeppelin's `AccessControl` instead of `Ownable`, or implementing a custom ownership transfer pattern.
324375
</Aside>
325376

326-
### 4.3 Working with Simulation
327-
328-
When you run `cre workflow simulate`, your workflow interacts with a **`MockForwarder`** contract that does not provide the `workflow_name` or `workflow_owner` metadata. This means consumer contracts with `IReceiverTemplate`'s default validation **will fail during simulation**.
329-
330-
**To test your consumer contract with simulation:**
331-
332-
Override the `onReport` function to bypass validation checks:
333-
334-
```solidity
335-
function onReport(bytes calldata, bytes calldata report) external override {
336-
_processReport(report); // Skips validation checks
337-
}
338-
```
339-
340-
**For deployed workflows:**
341-
342-
Deployed workflows use the real **`KeystoneForwarder`** contract, which provides full metadata. You can enable all permission checks (forwarder address, workflow ID, owner, name) for production deployments.
343-
344-
## 5. Complete Examples
377+
## 6. Complete Examples
345378

346379
### Example 1: Simple Consumer Contract
347380

src/content/cre/guides/workflow/using-evm-client/supported-networks-go.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ CRE workflows support EVM read and write operations on the following blockchain
3333

3434
Learn more: [Onchain Write Overview](/cre/guides/workflow/using-evm-client/onchain-write/overview)
3535

36-
**Permissioning with the Forwarder address**: You can optionally use the forwarder address to add an extra security layer to your consumer contracts by restricting the `onReport()` function to only accept calls from the trusted forwarder. See [Permissioning by Forwarder Address](/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts#permissioning-by-forwarder-address) for implementation details.
36+
**Permissioning with the Forwarder address**: You can optionally use the forwarder address to add an extra security layer to your consumer contracts by restricting the `onReport()` function to only accept calls from the trusted forwarder. See [Configuring Permissions](/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts#34-configuring-permissions) for implementation details.
3737

3838
</Aside>
3939

src/content/cre/guides/workflow/using-evm-client/supported-networks-ts.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ CRE workflows support EVM read and write operations on the following blockchain
3333

3434
Learn more: [Onchain Write Overview](/cre/guides/workflow/using-evm-client/onchain-write/overview)
3535

36-
**Permissioning with the Forwarder address**: You can optionally use the forwarder address to add an extra security layer to your consumer contracts by restricting the `onReport()` function to only accept calls from the trusted forwarder. See [Permissioning by Forwarder Address](/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts#permissioning-by-forwarder-address) for implementation details.
36+
**Permissioning with the Forwarder address**: You can optionally use the forwarder address to add an extra security layer to your consumer contracts by restricting the `onReport()` function to only accept calls from the trusted forwarder. See [Configuring Permissions](/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts#34-configuring-permissions) for implementation details.
3737

3838
</Aside>
3939

src/content/cre/llms-full-go.txt

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,8 +2336,9 @@ This guide explains how to build a consumer contract that can securely receive a
23362336
- [Core Concepts: The Onchain Data Flow](#1-core-concepts-the-onchain-data-flow)
23372337
- [The IReceiver Standard](#2-the-ireceiver-standard)
23382338
- [Using IReceiverTemplate](#3-using-ireceivertemplate)
2339-
- [Advanced Usage](#4-advanced-usage-optional)
2340-
- [Complete Examples](#5-complete-examples)
2339+
- [Working with Simulation](#4-working-with-simulation)
2340+
- [Advanced Usage](#5-advanced-usage-optional)
2341+
- [Complete Examples](#6-complete-examples)
23412342

23422343
## 1. Core Concepts: The Onchain Data Flow
23432344

@@ -2498,8 +2499,6 @@ abstract contract IReceiverTemplate is IReceiver, Ownable {
24982499

24992500
### 3.3 Quick Start
25002501

2501-
**Step 1: Inherit and implement your business logic**
2502-
25032502
The simplest way to use `IReceiverTemplate` is to inherit from it and implement the `_processReport` function:
25042503

25052504
```solidity
@@ -2523,13 +2522,16 @@ contract MyConsumer is IReceiverTemplate {
25232522
}
25242523
```
25252524

2526-
### 3.4 Configuring Security
2527-
2528-
**Step 2: Configure permissions (optional)**
2525+
### 3.4 Configuring Permissions
25292526

25302527
After deploying your contract, the owner can enable any combination of security checks using the setter functions.
25312528

25322529

2530+
<Aside type="caution" title="For simulation">
2531+
When using `cre workflow simulate`, **do not configure metadata-based validation checks** (`setExpectedWorkflowId`, `setExpectedAuthor`, `setExpectedWorkflowName`). The simulation uses a `MockForwarder` that doesn't provide this metadata. See [Working with Simulation](#4-working-with-simulation) for details.
2532+
</Aside>
2533+
2534+
25332535
<Aside type="tip" title="Finding forwarder addresses">
25342536
For a complete list of `KeystoneForwarder` contract addresses on all supported networks, see [Supported Networks](/cre/guides/workflow/using-evm-client/supported-networks).
25352537
</Aside>
@@ -2571,9 +2573,58 @@ myConsumer.setExpectedWorkflowName(bytes10(0));
25712573
- Your business logic in `_processReport`
25722574
- (Optional) Configure permissions after deployment using setter functions
25732575

2574-
## 4. Advanced Usage (Optional)
2576+
## 4. Working with Simulation
2577+
2578+
When you run `cre workflow simulate`, your workflow interacts with a **`MockKeystoneForwarder`** contract that does not provide workflow metadata (`workflow_name`, `workflow_owner`).
2579+
2580+
<Aside type="caution" title="Temporary limitation">
2581+
This is a **temporary limitation** until the `MockKeystoneForwarder` is updated to provide full metadata.
2582+
</Aside>
2583+
2584+
### Forwarder address validation
2585+
2586+
You **can** configure the forwarder address check during simulation:
2587+
2588+
```solidity
2589+
// Optional: Validate the MockKeystoneForwarder address during simulation
2590+
myConsumer.setForwarderAddress(0xMockForwarderAddress);
2591+
```
2592+
2593+
2594+
<Aside type="caution" title="Important: Different addresses for simulation vs production">
2595+
The `MockKeystoneForwarder` address used during simulation is **different** from the `KeystoneForwarder` address used by deployed workflows. If you configure the forwarder address for simulation, remember to update it to the production `KeystoneForwarder` address after deploying. See [Supported Networks](/cre/guides/workflow/using-evm-client/supported-networks) for forwarder addresses.
2596+
</Aside>
2597+
2598+
### Metadata-based validation
2599+
2600+
**Do not configure these validation checks** during simulation - they require metadata that `MockKeystoneForwarder` doesn't provide:
2601+
2602+
- `setExpectedWorkflowId()`
2603+
- `setExpectedAuthor()`
2604+
- `setExpectedWorkflowName()`
2605+
2606+
Setting any of these will cause your simulation to fail.
25752607

2576-
### 4.1 Custom Validation Logic
2608+
### After deployment
2609+
2610+
Once you deploy your workflow:
2611+
2612+
1. Update the forwarder address to the real `KeystoneForwarder` (if you configured it for simulation)
2613+
2. Configure additional metadata-based validation as needed
2614+
2615+
```solidity
2616+
// Update to production KeystoneForwarder address
2617+
myConsumer.setForwarderAddress(0xF8344CFd5c43616a4366C34E3EEE75af79a74482); // Example: Ethereum Sepolia
2618+
2619+
// Now you can enable metadata-based validation
2620+
myConsumer.setExpectedWorkflowId(0xYourWorkflowId);
2621+
```
2622+
2623+
See [Configuring Permissions](#34-configuring-permissions) for complete details.
2624+
2625+
## 5. Advanced Usage (Optional)
2626+
2627+
### 5.1 Custom Validation Logic
25772628

25782629
You can override `onReport` to add your own validation logic before or after the standard checks:
25792630

@@ -2612,7 +2663,7 @@ contract AdvancedConsumer is IReceiverTemplate {
26122663
}
26132664
```
26142665

2615-
### 4.2 Using Metadata Fields in Your Logic
2666+
### 5.2 Using Metadata Fields in Your Logic
26162667

26172668
The `_decodeMetadata` helper function is available for use in your `_processReport` implementation. This allows you to access workflow metadata for custom business logic:
26182669

@@ -2640,25 +2691,7 @@ contract MetadataAwareConsumer is IReceiverTemplate {
26402691
For production systems requiring even more sophisticated access control (such as role-based permissions or two-step ownership transfer), consider extending the template to use OpenZeppelin's `AccessControl` instead of `Ownable`, or implementing a custom ownership transfer pattern.
26412692
</Aside>
26422693

2643-
### 4.3 Working with Simulation
2644-
2645-
When you run `cre workflow simulate`, your workflow interacts with a **`MockForwarder`** contract that does not provide the `workflow_name` or `workflow_owner` metadata. This means consumer contracts with `IReceiverTemplate`'s default validation **will fail during simulation**.
2646-
2647-
**To test your consumer contract with simulation:**
2648-
2649-
Override the `onReport` function to bypass validation checks:
2650-
2651-
```solidity
2652-
function onReport(bytes calldata, bytes calldata report) external override {
2653-
_processReport(report); // Skips validation checks
2654-
}
2655-
```
2656-
2657-
**For deployed workflows:**
2658-
2659-
Deployed workflows use the real **`KeystoneForwarder`** contract, which provides full metadata. You can enable all permission checks (forwarder address, workflow ID, owner, name) for production deployments.
2660-
2661-
## 5. Complete Examples
2694+
## 6. Complete Examples
26622695

26632696
### Example 1: Simple Consumer Contract
26642697

@@ -10134,7 +10167,7 @@ CRE workflows support EVM read and write operations on the following blockchain
1013410167

1013510168
Learn more: [Onchain Write Overview](/cre/guides/workflow/using-evm-client/onchain-write/overview)
1013610169

10137-
**Permissioning with the Forwarder address**: You can optionally use the forwarder address to add an extra security layer to your consumer contracts by restricting the `onReport()` function to only accept calls from the trusted forwarder. See [Permissioning by Forwarder Address](/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts#permissioning-by-forwarder-address) for implementation details.
10170+
**Permissioning with the Forwarder address**: You can optionally use the forwarder address to add an extra security layer to your consumer contracts by restricting the `onReport()` function to only accept calls from the trusted forwarder. See [Configuring Permissions](/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts#34-configuring-permissions) for implementation details.
1013810171
</Aside>
1013910172

1014010173
## Testnets

0 commit comments

Comments
 (0)