Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions contract_manager/src/contracts/ton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { TokenQty } from "../token";
import { DataSource } from "@pythnetwork/xc-admin-common";
import { Address, OpenedContract } from "@ton/ton";
import {
BASE_UPDATE_PRICE_FEEDS_FEE,
calculateUpdatePriceFeedsFee,
PythContract,
} from "@pythnetwork/pyth-ton-js";

Expand Down Expand Up @@ -237,7 +237,7 @@ export class TonPriceFeedContract extends PriceFeedContract {
await contract.sendUpdatePriceFeeds(
sender,
vaa,
BASE_UPDATE_PRICE_FEEDS_FEE + BigInt(fee)
calculateUpdatePriceFeedsFee(BigInt(fee)) + BigInt(fee)
);
}

Expand Down
7 changes: 5 additions & 2 deletions target_chains/ton/contracts/contracts/Pyth.fc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ slice read_and_verify_header(slice data) {
throw_if(ERROR_INVALID_MINOR_VERSION, minor_version < MINIMUM_ALLOWED_MINOR_VERSION);
int trailing_header_size = data~load_uint(8);
;; skip trailing headers
data~skip_bits(trailing_header_size);
data~skip_bits(trailing_header_size * 8);
int update_type = data~load_uint(8);
throw_unless(ERROR_INVALID_UPDATE_DATA_TYPE, update_type == WORMHOLE_MERKLE_UPDATE_TYPE);
return data;
Expand Down Expand Up @@ -172,7 +172,10 @@ int parse_pyth_payload_in_wormhole_vm(slice payload) impure {

int num_updates = cs~load_uint(8);
int update_fee = single_update_fee * num_updates;
int compute_fee = get_compute_fee(WORKCHAIN, UPDATE_PRICE_FEEDS_GAS);
int compute_fee = get_compute_fee(
WORKCHAIN,
UPDATE_PRICE_FEEDS_BASE_GAS + (UPDATE_PRICE_FEEDS_PER_UPDATE_GAS * num_updates)
);
throw_unless(ERROR_INSUFFICIENT_GAS, msg_value >= compute_fee);
int remaining_msg_value = msg_value - compute_fee;

Expand Down
13 changes: 11 additions & 2 deletions target_chains/ton/contracts/contracts/common/gas.fc
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
int get_compute_fee(int workchain, int gas_used) asm(gas_used workchain) "GETGASFEE";

;; The actual gas used for the transaction is 350166 but we add ~10% (385182.6) and round up (390000) to be on the safe side because the amount of gas used can vary based on the current state of the blockchain
const int UPDATE_PRICE_FEEDS_GAS = 390000;
;; 1 update: 262,567 gas
;; 2 updates: 347,791 (+85,224)
;; 3 updates: 431,504 (+83,713)
;; 4 updates: 514,442 (+82,938)
;; 5 updates: 604,247 (+89,805)
;; 6 updates: 683,113 (+78,866)
;; 10 updates: 947,594
;; Upper bound gas increase per additional update: ~90,000
;; Base cost (1 update): ~262,567 gas
const UPDATE_PRICE_FEEDS_BASE_GAS = 300000; ;; Base cost + 10% safety margin rounded up because the amount of gas used can vary based on the current state of the blockchain
const UPDATE_PRICE_FEEDS_PER_UPDATE_GAS = 90000; ;; Per update cost
19 changes: 16 additions & 3 deletions target_chains/ton/contracts/tests/PythTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
serialize,
} from "@wormhole-foundation/sdk-definitions";
import { mocks } from "@wormhole-foundation/sdk-definitions/testing";
import { BASE_UPDATE_PRICE_FEEDS_FEE } from "@pythnetwork/pyth-ton-js";
import { calculateUpdatePriceFeedsFee } from "@pythnetwork/pyth-ton-js";

const TIME_PERIOD = 60;
const PRICE = new Price({
Expand Down Expand Up @@ -375,7 +375,7 @@ describe("PythTest", () => {

const updateData = Buffer.from(HERMES_BTC_ETH_UPDATE, "hex");

const result = await pythTest.sendUpdatePriceFeeds(
let result = await pythTest.sendUpdatePriceFeeds(
deployer.getSender(),
updateData,
toNano("0.1") // Insufficient gas
Expand All @@ -387,6 +387,19 @@ describe("PythTest", () => {
success: false,
exitCode: 3000, // ERROR_INSUFFICIENT_GAS
});

result = await pythTest.sendUpdatePriceFeeds(
deployer.getSender(),
updateData,
calculateUpdatePriceFeedsFee(1n) // Send enough gas for 1 update instead of 2
);

expect(result.transactions).toHaveTransaction({
from: deployer.address,
to: pythTest.address,
success: false,
exitCode: 3000, // ERROR_INSUFFICIENT_GAS
});
});

it("should fail to update price feeds with insufficient fee", async () => {
Expand All @@ -403,7 +416,7 @@ describe("PythTest", () => {
const result = await pythTest.sendUpdatePriceFeeds(
deployer.getSender(),
updateData,
BASE_UPDATE_PRICE_FEEDS_FEE + BigInt(insufficientFee)
calculateUpdatePriceFeedsFee(2n) + BigInt(insufficientFee)
);

// Check that the transaction did not succeed
Expand Down
3 changes: 2 additions & 1 deletion target_chains/ton/sdk/js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { HermesClient } from "@pythnetwork/hermes-client";
import {
PythContract,
PYTH_CONTRACT_ADDRESS_TESTNET,
calculateUpdatePriceFeedsFee,
} from "@pythnetwork/pyth-ton-js";

const BTC_PRICE_FEED_ID =
Expand Down Expand Up @@ -73,7 +74,7 @@ async function main() {
await contract.sendUpdatePriceFeeds(
provider.sender(key.secretKey),
updateData,
BASE_UPDATE_PRICE_FEEDS_FEE + BigInt(updateFee)
calculateUpdatePriceFeedsFee(1n) + BigInt(updateFee)
);
console.log("Price feeds updated successfully.");

Expand Down
13 changes: 10 additions & 3 deletions target_chains/ton/sdk/js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ import { ContractProvider } from "@ton/ton";
export const PYTH_CONTRACT_ADDRESS_TESTNET =
"EQDwGkJmcj7MMmWAHmhldnY-lAKI6hcTQ2tAEcapmwCnztQU";
// This is defined in target_chains/ton/contracts/common/gas.fc
export const UPDATE_PRICE_FEEDS_GAS = 390000n;
export const UPDATE_PRICE_FEEDS_BASE_GAS = 300000n;
export const UPDATE_PRICE_FEEDS_PER_UPDATE_GAS = 90000n;
// Current settings in basechain are as follows: 1 unit of gas costs 400 nanotons
export const GAS_PRICE_FACTOR = 400n;
export const BASE_UPDATE_PRICE_FEEDS_FEE =
UPDATE_PRICE_FEEDS_GAS * GAS_PRICE_FACTOR;

export interface DataSource {
emitterChain: number;
Expand Down Expand Up @@ -318,3 +317,11 @@ export function parseGuardianSetKeys(cell: Cell): string[] {
parseCell(cell);
return keys;
}

export function calculateUpdatePriceFeedsFee(numUpdates: bigint) {
return (
(UPDATE_PRICE_FEEDS_BASE_GAS +
UPDATE_PRICE_FEEDS_PER_UPDATE_GAS * numUpdates) *
GAS_PRICE_FACTOR
);
}
Loading