diff --git a/contracts/contracts/ccip/fee_quoter/contract.tolk b/contracts/contracts/ccip/fee_quoter/contract.tolk index b076d9e06..30aee35a5 100644 --- a/contracts/contracts/ccip/fee_quoter/contract.tolk +++ b/contracts/contracts/ccip/fee_quoter/contract.tolk @@ -533,7 +533,8 @@ fun sendExcessesTo(sendExcessesTo: address?, sender: address) { dest: receiver, body: createEmptyCell(), }); - returnExcesses.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); + reserveToncoinsOnBalance(0, RESERVE_MODE_INCREASE_BY_ORIGINAL_BALANCE); + returnExcesses.send(SEND_MODE_CARRY_ALL_BALANCE); } get fun tokenPrice(token: address): TimestampedPrice { diff --git a/contracts/contracts/ccip/fee_quoter/messages.tolk b/contracts/contracts/ccip/fee_quoter/messages.tolk index 4a76ffa2a..14d59268d 100644 --- a/contracts/contracts/ccip/fee_quoter/messages.tolk +++ b/contracts/contracts/ccip/fee_quoter/messages.tolk @@ -80,5 +80,5 @@ fun FeeQuoter_Costs.GetValidatedFee(): int { fun FeeQuoter_Costs.updatePrices(): int { // when we support token transfers the message value amount should depend on the quantity of supported tokens - return ton("0.01"); + return ton("0.03"); } diff --git a/contracts/tests/ccip/feequoter/FeeQuoter.updatePrices.spec.ts b/contracts/tests/ccip/feequoter/FeeQuoter.updatePrices.spec.ts index 24fcfe087..6d0d957fe 100644 --- a/contracts/tests/ccip/feequoter/FeeQuoter.updatePrices.spec.ts +++ b/contracts/tests/ccip/feequoter/FeeQuoter.updatePrices.spec.ts @@ -1,6 +1,6 @@ import '@ton/test-utils' -import { toNano } from '@ton/core' +import { Address, toNano } from '@ton/core' import { FeeQuoterSetup } from './FeeQuoterSetup' import * as feeQuoter from '../../../wrappers/ccip/FeeQuoter' @@ -319,6 +319,50 @@ describe('FeeQuoter UpdatePrices', () => { }) }) + it('should not end up with lower balance than initial balance after returning excess', async () => { + const contract = await blockchain.getContract(setup.bind.feeQuoter.address) + const initialBalance = contract.balance + + const priceUpdates: feeQuoter.PriceUpdates = { + tokenPricesUpdates: [{ token: FeeQuoterSetup.NATIVE_TON.token, price: 4000000000000000000n }], + gasPricesUpdates: [], + } + + const updateResult = await setup.bind.feeQuoter.sendUpdatePrices(setup.acc.owner.getSender(), { + value: toNano('0.03'), + msg: { updates: priceUpdates, sendExcessesTo: setup.acc.deployer.address }, + }) + + expect(updateResult.transactions).toHaveTransaction({ + to: setup.bind.feeQuoter.address, + success: true, + }) + + expect(updateResult.transactions).toHaveTransaction({ + from: setup.bind.feeQuoter.address, + to: setup.acc.deployer.address, + success: true, + }) + + const tx = updateResult.transactions.find( + (tx) => + tx.inMessage && + tx.inMessage.info.src && + tx.inMessage.info.src instanceof Address && + tx.inMessage.info.src.equals(setup.acc.owner.address) && + tx.inMessage.info.dest && + tx.inMessage.info.dest instanceof Address && + tx.inMessage.info.dest.equals(setup.bind.feeQuoter.address), + ) + if (!tx || tx.description.type != 'generic') { + throw new Error('Expected an internal message') + } + const storageFees = tx.description.storagePhase?.storageFeesCollected || toNano('0') + + const finalBalance = (await blockchain.getContract(setup.bind.feeQuoter.address)).balance + expect(finalBalance).toEqual(initialBalance - storageFees) + }) + afterAll(async () => { if (process.env['COVERAGE'] === 'true') { const testSuitePrefix = 'feeQuoter_update_prices_suite' diff --git a/pkg/ccip/ocr/config.go b/pkg/ccip/ocr/config.go index 35a5630f6..54855ca81 100644 --- a/pkg/ccip/ocr/config.go +++ b/pkg/ccip/ocr/config.go @@ -16,8 +16,8 @@ type Config struct { } var DefaultConfigSet = Config{ - CommitPriceUpdateOnlyCostTON: 0.03, - CommitPriceAndRootCostTON: 0.05, + CommitPriceUpdateOnlyCostTON: 0.05, + CommitPriceAndRootCostTON: 0.07, ExecuteCostTON: 0.085, }