Skip to content

Commit 551490b

Browse files
consider empty cell as null priceupdates (#462)
* consider empty cell as null priceupdates * refactor a bit and test * Update contracts/contracts/ccip/offramp/contract.tolk Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent 020c385 commit 551490b

File tree

2 files changed

+78
-24
lines changed

2 files changed

+78
-24
lines changed

contracts/contracts/ccip/offramp/contract.tolk

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fun onInternalMessage(in:InMessage) {
3434
match(msg) {
3535
// Sender must be OCR transmitter
3636
OffRamp_Commit => {
37-
onCommit(msg, in.senderAddress, in.valueCoins)
37+
onCommit(msg, in.senderAddress, in.valueCoins)
3838
}
3939
// Sender must be OCR transmitter
4040
OffRamp_Execute => {
@@ -428,31 +428,37 @@ fun onCommit(msg: OffRamp_Commit, sender: address, value: coins) {
428428
initMsg.send(SEND_MODE_REGULAR);
429429
}
430430

431-
// update token/gas prices if any
431+
// Update token/gas prices if there are any updates.
432+
// Don't send the UpdatePrices message if both tokenPriceUpdates and gasPriceUpdates are empty.
433+
432434
if (report.priceUpdates != null) {
433-
// extract OCR sequence number from report context (matches EVM implementation)
434-
val ocrSequenceNumber = msg.reportContext.sequenceBytes;
435-
436-
// check for price staleness based on the OCR sequence number
437-
if (st.latestPriceSequenceNumber < ocrSequenceNumber) {
438-
// if prices are not stale, update the latest sequence number
439-
st.latestPriceSequenceNumber = ocrSequenceNumber;
440-
441-
// and update the prices in the fee quoter
442-
443-
val updatePricesMsg = createMessage({
444-
bounce: true,
445-
value: FeeQuoter_Costs.updatePrices(),
446-
dest: st.feeQuoter,
447-
body: FeeQuoter_UpdatePrices {
448-
updates: report.priceUpdates!.load(),
449-
sendExcessesTo: sender,
450-
}
451-
});
452-
updatePricesMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
435+
val priceUpdates = report.priceUpdates!.load();
436+
437+
// Ignore price updates if both are empty
438+
if (!(priceUpdates.tokenPriceUpdates.empty() && priceUpdates.gasPriceUpdates.empty())) {
439+
// extract OCR sequence number from report context (matches EVM implementation)
440+
val ocrSequenceNumber = msg.reportContext.sequenceBytes;
441+
442+
// check for price staleness based on the OCR sequence number
443+
if (st.latestPriceSequenceNumber < ocrSequenceNumber) {
444+
// if prices are not stale, update the latest sequence number
445+
st.latestPriceSequenceNumber = ocrSequenceNumber;
446+
447+
// and update the prices in the fee quoter
448+
449+
val updatePricesMsg = createMessage({
450+
bounce: true,
451+
value: FeeQuoter_Costs.updatePrices(),
452+
dest: st.feeQuoter,
453+
body: FeeQuoter_UpdatePrices {
454+
updates: report.priceUpdates!.load(),
455+
sendExcessesTo: sender,
456+
}
457+
});
458+
updatePricesMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);
459+
}
453460
}
454461
}
455-
456462
// store updated state (latestPriceSequenceNumber and sourceChainConfigs)
457463
st.store();
458464

@@ -464,7 +470,6 @@ fun onCommit(msg: OffRamp_Commit, sender: address, value: coins) {
464470
report.toCell(),
465471
msg.signatures
466472
);
467-
468473
emit(
469474
TOPIC_COMMIT_REPORT_ACCEPTED,
470475
CommitReportAccepted { merkleRoot: root, priceUpdates: report.priceUpdates }

contracts/tests/ccip/OffRamp.spec.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2486,6 +2486,55 @@ describe('OffRamp - Unit Tests', () => {
24862486
expect(expectedSourceChainConfigs.sort()).toEqual(result.sort())
24872487
})
24882488

2489+
it('price updates are not sent to feequoter if they are empty', async () => {
2490+
await setupOCRConfig()
2491+
const priceUpdates: PriceUpdates = {
2492+
tokenPriceUpdates: [],
2493+
gasPriceUpdates: [],
2494+
}
2495+
const result = await commitReport([], toNano('0.5'), 0x01, priceUpdates)
2496+
expect(result.transactions).not.toHaveTransaction({
2497+
from: offRamp.address,
2498+
to: feeQuoter.address,
2499+
})
2500+
2501+
//should send update if only one of the updates is non-empty
2502+
const priceUpdates2: PriceUpdates = {
2503+
tokenPriceUpdates: [
2504+
{
2505+
sourceToken: generateMockTonAddress(),
2506+
usdPerToken: 12345678n,
2507+
},
2508+
],
2509+
gasPriceUpdates: [],
2510+
}
2511+
2512+
const result2 = await commitReport([], toNano('0.5'), 0x02, priceUpdates2)
2513+
expect(result2.transactions).toHaveTransaction({
2514+
from: offRamp.address,
2515+
to: feeQuoter.address,
2516+
})
2517+
2518+
//test with other combination
2519+
const priceUpdates3: PriceUpdates = {
2520+
tokenPriceUpdates: [],
2521+
gasPriceUpdates: [
2522+
{
2523+
destChainSelector: CHAINSEL_EVM_TEST_90000001,
2524+
executionGasPrice: 1n,
2525+
dataAvailabilityGasPrice: 1n,
2526+
},
2527+
],
2528+
}
2529+
2530+
const result3 = await commitReport([], toNano('0.5'), 0x03, priceUpdates3)
2531+
expect(result3.transactions).toHaveTransaction({
2532+
from: offRamp.address,
2533+
to: feeQuoter.address,
2534+
success: true,
2535+
})
2536+
})
2537+
24892538
afterAll(async () => {
24902539
if (process.env['COVERAGE'] === 'true') {
24912540
const testSuitePrefix = 'offramp_suite'

0 commit comments

Comments
 (0)