Skip to content

Commit 44836fa

Browse files
committed
Address review comments
1 parent 5539363 commit 44836fa

File tree

10 files changed

+106
-55
lines changed

10 files changed

+106
-55
lines changed

chains/solana/contracts/programs/ccip-offramp/src/context.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,13 @@ pub struct CloseExecutionReportBufferContext<'info> {
665665
)]
666666
pub execution_report_buffer: Account<'info, ExecutionReportBuffer>,
667667

668+
#[account(
669+
seeds = [seed::CONFIG],
670+
bump,
671+
constraint = valid_version(config.load()?.version, MAX_CONFIG_V) @ CcipOfframpError::InvalidVersion,
672+
)]
673+
pub config: AccountLoader<'info, Config>,
674+
668675
#[account(mut)]
669676
pub authority: Signer<'info>,
670677
pub system_program: Program<'info, System>,

chains/solana/contracts/programs/ccip-offramp/src/instructions/v1/buffering.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl Buffering for ExecutionReportBuffer {
2525
}
2626

2727
fn is_complete(&self) -> bool {
28-
self.is_initialized() && self.filled_chunks() == self.total_chunks
28+
self.is_initialized() && self.filled_chunks() == self.num_chunks
2929
}
3030

3131
fn bytes(&self) -> Result<&[u8]> {
@@ -62,6 +62,11 @@ impl Buffering for ExecutionReportBuffer {
6262
report_length as usize,
6363
CcipOfframpError::ExecutionReportBufferInvalidLength
6464
);
65+
require_eq!(
66+
self.num_chunks,
67+
num_chunks,
68+
CcipOfframpError::ExecutionReportBufferInvalidChunkNumber
69+
);
6570

6671
let chunk_mask = 1u64 << chunk_index;
6772
require!(
@@ -79,13 +84,13 @@ impl Buffering for ExecutionReportBuffer {
7984
// Only the terminator (last chunk) can be smaller than the others.
8085
require_eq!(
8186
chunk_index,
82-
self.total_chunks - 1,
87+
self.num_chunks - 1,
8388
CcipOfframpError::ExecutionReportBufferInvalidChunkSize
8489
);
8590
}
8691

8792
require_gt!(
88-
self.total_chunks,
93+
self.num_chunks,
8994
chunk_index,
9095
CcipOfframpError::ExecutionReportBufferInvalidChunkIndex
9196
);
@@ -116,7 +121,7 @@ impl ExecutionReportBuffer {
116121
CcipOfframpError::ExecutionReportBufferInvalidLength
117122
);
118123
require!(
119-
total_chunks < 64 && total_chunks > 0,
124+
total_chunks <= 64 && total_chunks > 0,
120125
CcipOfframpError::ExecutionReportBufferInvalidChunkSize
121126
);
122127

@@ -136,7 +141,7 @@ impl ExecutionReportBuffer {
136141
CcipOfframpError::ExecutionReportBufferInvalidLength,
137142
);
138143
self.chunk_length = global_chunk_length;
139-
self.total_chunks = total_chunks;
144+
self.num_chunks = total_chunks;
140145
self.data.resize(report_length as usize, 0);
141146

142147
Ok(())
@@ -177,7 +182,7 @@ mod tests {
177182
ExecutionReportBuffer {
178183
data: vec![],
179184
chunk_bitmap: 0,
180-
total_chunks: 0,
185+
num_chunks: 0,
181186
chunk_length: 0,
182187
version: 0,
183188
}

chains/solana/contracts/programs/ccip-offramp/src/instructions/v1/execute.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ fn internal_execute<'info>(
432432
pub struct ExecuteReportContextRemainingAccountsLayout<'a> {
433433
pub messaging_accounts: Option<ExecuteContextRemainingMessagingAccounts<'a>>,
434434
pub token_accounts_per_token: Vec<ExecuteContextRemainingTokenAccounts<'a>>,
435-
pub buffering_accounts: Option<ExecuteContextRemainingBufferingAccounts<'a>>,
435+
pub buffering_account: Option<ExecuteContextRemainingBufferingAccount<'a>>,
436436
}
437437

438438
pub struct ExecuteContextRemainingMessagingAccounts<'a> {
@@ -446,7 +446,7 @@ pub struct ExecuteContextRemainingTokenAccounts<'a> {
446446
pub accounts: &'a [AccountInfo<'a>],
447447
}
448448

449-
pub struct ExecuteContextRemainingBufferingAccounts<'a> {
449+
pub struct ExecuteContextRemainingBufferingAccount<'a> {
450450
pub execution_buffer_account: &'a AccountInfo<'a>,
451451
}
452452

@@ -505,10 +505,10 @@ impl<'a> ExecuteReportContextRemainingAccountsLayout<'a> {
505505

506506
// First, if the report is buffered, it means the last account is the buffering account.
507507
// We can simply remove it from consideration from now on.
508-
let (remaining_accounts_without_buffering, buffering_accounts) = if report_is_buffered {
508+
let (remaining_accounts_without_buffering, buffering_account) = if report_is_buffered {
509509
(
510510
&remaining_accounts[0..(remaining_accounts.len() - 1)],
511-
Some(ExecuteContextRemainingBufferingAccounts {
511+
Some(ExecuteContextRemainingBufferingAccount {
512512
execution_buffer_account: remaining_accounts
513513
.last()
514514
.ok_or(CcipOfframpError::ExecutionReportUnavailable)?,
@@ -603,7 +603,7 @@ impl<'a> ExecuteReportContextRemainingAccountsLayout<'a> {
603603
Ok(Self {
604604
messaging_accounts,
605605
token_accounts_per_token,
606-
buffering_accounts,
606+
buffering_account,
607607
})
608608
}
609609
}

chains/solana/contracts/programs/ccip-offramp/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,8 @@ pub enum CcipOfframpError {
745745
ExecutionReportBufferInvalidLength,
746746
#[msg("Chunk lies outside the execution report buffer")]
747747
ExecutionReportBufferInvalidChunkIndex,
748+
#[msg("Total number of chunks is not consistent")]
749+
ExecutionReportBufferInvalidChunkNumber,
748750
#[msg("Chunk size is too small")]
749751
ExecutionReportBufferChunkSizeTooSmall,
750752
#[msg("Invalid chunk size")]

chains/solana/contracts/programs/ccip-offramp/src/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub struct OnRampAddress {
105105
pub struct ExecutionReportBuffer {
106106
pub version: u8,
107107
pub chunk_bitmap: u64,
108-
pub total_chunks: u8,
108+
pub num_chunks: u8,
109109
pub chunk_length: u32,
110110
#[max_len(0)]
111111
pub data: Vec<u8>,

chains/solana/contracts/target/idl/ccip_offramp.json

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,11 @@
11341134
"isMut": true,
11351135
"isSigner": false
11361136
},
1137+
{
1138+
"name": "config",
1139+
"isMut": false,
1140+
"isSigner": false
1141+
},
11371142
{
11381143
"name": "authority",
11391144
"isMut": true,
@@ -1328,7 +1333,7 @@
13281333
"type": "u64"
13291334
},
13301335
{
1331-
"name": "totalChunks",
1336+
"name": "numChunks",
13321337
"type": "u8"
13331338
},
13341339
{
@@ -2533,21 +2538,26 @@
25332538
},
25342539
{
25352540
"code": 9061,
2541+
"name": "ExecutionReportBufferInvalidChunkNumber",
2542+
"msg": "Total number of chunks is not consistent"
2543+
},
2544+
{
2545+
"code": 9062,
25362546
"name": "ExecutionReportBufferChunkSizeTooSmall",
25372547
"msg": "Chunk size is too small"
25382548
},
25392549
{
2540-
"code": 9062,
2550+
"code": 9063,
25412551
"name": "ExecutionReportBufferInvalidChunkSize",
25422552
"msg": "Invalid chunk size"
25432553
},
25442554
{
2545-
"code": 9063,
2555+
"code": 9064,
25462556
"name": "ExecutionReportBufferIncomplete",
25472557
"msg": "Execution report buffer is not complete: chunks are missing"
25482558
},
25492559
{
2550-
"code": 9064,
2560+
"code": 9065,
25512561
"name": "ExecutionReportUnavailable",
25522562
"msg": "Execution report wasn't provided either directly or via buffer"
25532563
}

chains/solana/contracts/target/types/ccip_offramp.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,11 @@ export type CcipOfframp = {
11341134
"isMut": true,
11351135
"isSigner": false
11361136
},
1137+
{
1138+
"name": "config",
1139+
"isMut": false,
1140+
"isSigner": false
1141+
},
11371142
{
11381143
"name": "authority",
11391144
"isMut": true,
@@ -1328,7 +1333,7 @@ export type CcipOfframp = {
13281333
"type": "u64"
13291334
},
13301335
{
1331-
"name": "totalChunks",
1336+
"name": "numChunks",
13321337
"type": "u8"
13331338
},
13341339
{
@@ -2533,21 +2538,26 @@ export type CcipOfframp = {
25332538
},
25342539
{
25352540
"code": 9061,
2541+
"name": "ExecutionReportBufferInvalidChunkNumber",
2542+
"msg": "Total number of chunks is not consistent"
2543+
},
2544+
{
2545+
"code": 9062,
25362546
"name": "ExecutionReportBufferChunkSizeTooSmall",
25372547
"msg": "Chunk size is too small"
25382548
},
25392549
{
2540-
"code": 9062,
2550+
"code": 9063,
25412551
"name": "ExecutionReportBufferInvalidChunkSize",
25422552
"msg": "Invalid chunk size"
25432553
},
25442554
{
2545-
"code": 9063,
2555+
"code": 9064,
25462556
"name": "ExecutionReportBufferIncomplete",
25472557
"msg": "Execution report buffer is not complete: chunks are missing"
25482558
},
25492559
{
2550-
"code": 9064,
2560+
"code": 9065,
25512561
"name": "ExecutionReportUnavailable",
25522562
"msg": "Execution report wasn't provided either directly or via buffer"
25532563
}
@@ -3690,6 +3700,11 @@ export const IDL: CcipOfframp = {
36903700
"isMut": true,
36913701
"isSigner": false
36923702
},
3703+
{
3704+
"name": "config",
3705+
"isMut": false,
3706+
"isSigner": false
3707+
},
36933708
{
36943709
"name": "authority",
36953710
"isMut": true,
@@ -3884,7 +3899,7 @@ export const IDL: CcipOfframp = {
38843899
"type": "u64"
38853900
},
38863901
{
3887-
"name": "totalChunks",
3902+
"name": "numChunks",
38883903
"type": "u8"
38893904
},
38903905
{
@@ -5089,21 +5104,26 @@ export const IDL: CcipOfframp = {
50895104
},
50905105
{
50915106
"code": 9061,
5107+
"name": "ExecutionReportBufferInvalidChunkNumber",
5108+
"msg": "Total number of chunks is not consistent"
5109+
},
5110+
{
5111+
"code": 9062,
50925112
"name": "ExecutionReportBufferChunkSizeTooSmall",
50935113
"msg": "Chunk size is too small"
50945114
},
50955115
{
5096-
"code": 9062,
5116+
"code": 9063,
50975117
"name": "ExecutionReportBufferInvalidChunkSize",
50985118
"msg": "Invalid chunk size"
50995119
},
51005120
{
5101-
"code": 9063,
5121+
"code": 9064,
51025122
"name": "ExecutionReportBufferIncomplete",
51035123
"msg": "Execution report buffer is not complete: chunks are missing"
51045124
},
51055125
{
5106-
"code": 9064,
5126+
"code": 9065,
51075127
"name": "ExecutionReportUnavailable",
51085128
"msg": "Execution report wasn't provided either directly or via buffer"
51095129
}

chains/solana/contracts/tests/ccip/ccip_router_test.go

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"encoding/hex"
77
"fmt"
88
"maps"
9-
"math"
109
"math/big"
1110
"sort"
1211
"testing"
@@ -9571,10 +9570,6 @@ func TestCCIPRouter(t *testing.T) {
95719570
ix = sendChunk(t, 0, chunkSize, 4, data, bufferID, bufferPDA, transmitter)
95729571
result = testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{ix}, transmitter, config.DefaultCommitment)
95739572
totalSolSpentInFees += result.Meta.Fee
9574-
// Checking again after the terminator shuffling
9575-
ix = sendChunk(t, 3, terminatorSize, 4, data, bufferID, bufferPDA, transmitter)
9576-
result = testutils.SendAndFailWith(ctx, t, solanaGoClient, []solana.Instruction{ix}, transmitter, config.DefaultCommitment, []string{"Error Code: ExecutionReportBufferAlreadyContainsChunk"})
9577-
totalSolSpentInFees += result.Meta.Fee
95789573
ix = sendChunk(t, 1, terminatorSize, 4, data, bufferID, bufferPDA, transmitter)
95799574
result = testutils.SendAndFailWith(ctx, t, solanaGoClient, []solana.Instruction{ix}, transmitter, config.DefaultCommitment, []string{"Error Code: ExecutionReportBufferInvalidChunkSize"})
95809575
totalSolSpentInFees += result.Meta.Fee
@@ -9592,19 +9587,12 @@ func TestCCIPRouter(t *testing.T) {
95929587
rent := (initialLamports - finalLamportsBeforeClose) - totalSolSpentInFees
95939588

95949589
// We now close the buffer to recover the rent
9595-
closeIx, err := ccip_offramp.NewCloseExecutionReportBufferInstruction(bufferID[:], bufferPDA, transmitter.PublicKey(), solana.SystemProgramID).ValidateAndBuild()
9590+
closeIx, err := ccip_offramp.NewCloseExecutionReportBufferInstruction(bufferID[:], bufferPDA, config.OfframpConfigPDA, transmitter.PublicKey(), solana.SystemProgramID).ValidateAndBuild()
95969591
require.NoError(t, err)
95979592
result = testutils.SendAndConfirm(ctx, t, solanaGoClient, []solana.Instruction{closeIx}, transmitter, config.DefaultCommitment)
95989593
finalLamportsAfterClose := getLamports(transmitter.PublicKey())
95999594
closeDiff := finalLamportsAfterClose - finalLamportsBeforeClose
9600-
9601-
within10PercentOf := func(a int, b int) bool {
9602-
diff := math.Abs(float64(a - b))
9603-
return diff <= 0.1*math.Max(float64(a), float64(b))
9604-
}
9605-
9606-
// TODO work out exact math: the rent is being recovered but there's some slight drift in the fees.
9607-
require.True(t, within10PercentOf(int(rent), int(closeDiff-result.Meta.Fee)))
9595+
require.Equal(t, rent-result.Meta.Fee, closeDiff)
96089596
})
96099597

96109598
t.Run("When executing a report with oversized data, it fails, but it succeeds when buffered", func(t *testing.T) {
@@ -9794,7 +9782,7 @@ func TestCCIPRouter(t *testing.T) {
97949782
require.Equal(t, commitReport.MerkleRoot.MaxSeqNr, rootAccount.MaxMsgNr)
97959783
})
97969784

9797-
t.Run("Direct buffering execution, happy path", func(t *testing.T) {
9785+
t.Run("Buffered execution, happy path", func(t *testing.T) {
97989786
transmitter := getTransmitter()
97999787

98009788
msgAccounts := []solana.PublicKey{config.CcipLogicReceiver, config.ReceiverExternalExecutionConfigPDA, config.ReceiverTargetAccountPDA, solana.SystemProgramID}

0 commit comments

Comments
 (0)