Skip to content

Commit c720bf1

Browse files
authored
fix(target_chains/ton): fix ton contract checks (#2073)
* fix ton contract * make sure guardian set is not empty * precommit
1 parent 5bef389 commit c720bf1

File tree

4 files changed

+48
-39
lines changed

4 files changed

+48
-39
lines changed

target_chains/ton/contracts/contracts/Pyth.fc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ int apply_decimal_expo(int value, int expo) {
265265
;; Set the code continuation to the new code
266266
set_c3(new_code.begin_parse().bless());
267267

268+
;; Reset the upgrade code hash
269+
upgrade_code_hash = 0;
270+
268271
;; Throw an exception to end the current execution
269272
;; The contract will be restarted with the new code
270273
throw(0);

target_chains/ton/contracts/contracts/Wormhole.fc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ int governance_action_is_consumed(int hash) method_id {
8686
() verify_signatures(int hash, cell signatures, int signers_length, cell guardian_set_keys, int guardian_set_size) impure {
8787
slice cs = signatures.begin_parse();
8888
int i = 0;
89+
int last_signature_index = -1;
8990
int valid_signatures = 0;
9091

9192
while (i < signers_length) {
@@ -105,6 +106,7 @@ int governance_action_is_consumed(int hash) method_id {
105106

106107
slice sig_slice = sig_builder.end_cell().begin_parse();
107108
int guardian_index = sig_slice~load_uint(8);
109+
throw_if(ERROR_SIGNATURE_INDEX_NOT_INCREASING, guardian_index <= last_signature_index);
108110
int r = sig_slice~load_uint(256);
109111
int s = sig_slice~load_uint(256);
110112
int v = sig_slice~load_uint(8);
@@ -115,6 +117,7 @@ int governance_action_is_consumed(int hash) method_id {
115117
int guardian_address = guardian_key~load_uint(160);
116118
throw_unless(ERROR_INVALID_GUARDIAN_ADDRESS, parsed_address == guardian_address);
117119
valid_signatures += 1;
120+
last_signature_index = guardian_index;
118121
i += 1;
119122
}
120123

@@ -198,6 +201,8 @@ int governance_action_is_consumed(int hash) method_id {
198201
throw_unless(ERROR_NEW_GUARDIAN_SET_INDEX_IS_INVALID, new_guardian_set_index == (current_guardian_set_index + 1));
199202

200203
int guardian_length = payload~load_uint(8);
204+
throw_unless(ERROR_INVALID_GUARDIAN_SET_KEYS_LENGTH, guardian_length > 0);
205+
201206
cell new_guardian_set_keys = new_dict();
202207
int key_count = 0;
203208
while (key_count < guardian_length) {

target_chains/ton/contracts/contracts/common/errors.fc

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,28 @@ const int ERROR_INVALID_GUARDIAN_SET_UPGRADE_LENGTH = 1015;
2020
const int ERROR_INVALID_GOVERNANCE_CHAIN = 1016;
2121
const int ERROR_INVALID_GOVERNANCE_CONTRACT = 1017;
2222
const int ERROR_INVALID_GUARDIAN_ADDRESS = 1018;
23+
const int ERROR_SIGNATURE_INDEX_NOT_INCREASING = 1019;
2324

2425
;; Pyth
25-
const int ERROR_PRICE_FEED_NOT_FOUND = 1019;
26-
const int ERROR_OUTDATED_PRICE = 1020;
27-
const int ERROR_INVALID_MAGIC = 1021;
28-
const int ERROR_INVALID_MAJOR_VERSION = 1022;
29-
const int ERROR_INVALID_MINOR_VERSION = 1023;
30-
const int ERROR_UPDATE_DATA_SOURCE_NOT_FOUND = 1024;
31-
const int ERROR_INVALID_UPDATE_DATA_SOURCE = 1025;
32-
const int ERROR_DIGEST_MISMATCH = 1026;
33-
const int ERROR_INVALID_UPDATE_DATA_LENGTH = 1027;
34-
const int ERROR_INVALID_UPDATE_DATA_TYPE = 1028;
35-
const int ERROR_INVALID_MESSAGE_TYPE = 1029;
36-
const int ERROR_INSUFFICIENT_FEE = 1030;
37-
const int ERROR_INVALID_PROOF_SIZE = 1031;
38-
const int ERROR_INVALID_GOVERNANCE_DATA_SOURCE = 1032;
39-
const int ERROR_OLD_GOVERNANCE_MESSAGE = 1033;
40-
const int ERROR_INVALID_GOVERNANCE_TARGET = 1034;
41-
const int ERROR_INVALID_GOVERNANCE_MAGIC = 1035;
42-
const int ERROR_INVALID_GOVERNANCE_MODULE = 1036;
43-
const int ERROR_INVALID_CODE_HASH = 1037;
26+
const int ERROR_PRICE_FEED_NOT_FOUND = 2000;
27+
const int ERROR_OUTDATED_PRICE = 2001;
28+
const int ERROR_INVALID_MAGIC = 2002;
29+
const int ERROR_INVALID_MAJOR_VERSION = 2003;
30+
const int ERROR_INVALID_MINOR_VERSION = 2004;
31+
const int ERROR_UPDATE_DATA_SOURCE_NOT_FOUND = 2005;
32+
const int ERROR_INVALID_UPDATE_DATA_SOURCE = 2006;
33+
const int ERROR_DIGEST_MISMATCH = 2007;
34+
const int ERROR_INVALID_UPDATE_DATA_LENGTH = 2008;
35+
const int ERROR_INVALID_UPDATE_DATA_TYPE = 2009;
36+
const int ERROR_INVALID_MESSAGE_TYPE = 2010;
37+
const int ERROR_INSUFFICIENT_FEE = 2011;
38+
const int ERROR_INVALID_PROOF_SIZE = 2012;
39+
const int ERROR_INVALID_GOVERNANCE_DATA_SOURCE = 2013;
40+
const int ERROR_OLD_GOVERNANCE_MESSAGE = 2014;
41+
const int ERROR_INVALID_GOVERNANCE_TARGET = 2015;
42+
const int ERROR_INVALID_GOVERNANCE_MAGIC = 2016;
43+
const int ERROR_INVALID_GOVERNANCE_MODULE = 2017;
44+
const int ERROR_INVALID_CODE_HASH = 2018;
4445

4546
;; Common
46-
const int ERROR_INSUFFICIENT_GAS = 1038;
47+
const int ERROR_INSUFFICIENT_GAS = 3000;

target_chains/ton/contracts/tests/PythTest.spec.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ describe("PythTest", () => {
181181

182182
await expect(
183183
pythTest.getPriceNoOlderThan(TIME_PERIOD, BTC_PRICE_FEED_ID)
184-
).rejects.toThrow("Unable to execute get method. Got exit_code: 1020"); // ERROR_OUTDATED_PRICE = 1020
184+
).rejects.toThrow("Unable to execute get method. Got exit_code: 2001"); // ERROR_OUTDATED_PRICE = 2001
185185
});
186186

187187
it("should correctly get ema price no older than", async () => {
@@ -210,7 +210,7 @@ describe("PythTest", () => {
210210

211211
await expect(
212212
pythTest.getEmaPriceNoOlderThan(TIME_PERIOD, BTC_PRICE_FEED_ID)
213-
).rejects.toThrow("Unable to execute get method. Got exit_code: 1020"); // ERROR_OUTDATED_PRICE = 1020
213+
).rejects.toThrow("Unable to execute get method. Got exit_code: 2001"); // ERROR_OUTDATED_PRICE = 2001
214214
});
215215

216216
it("should correctly get ema price unsafe", async () => {
@@ -245,8 +245,8 @@ describe("PythTest", () => {
245245
expect(initialBtcPrice.price).not.toBe(HERMES_BTC_PRICE);
246246
// Expect an error for ETH price feed as it doesn't exist initially
247247
await expect(pythTest.getPriceUnsafe(ETH_PRICE_FEED_ID)).rejects.toThrow(
248-
"Unable to execute get method. Got exit_code: 1019"
249-
); // ERROR_PRICE_FEED_NOT_FOUND = 1019
248+
"Unable to execute get method. Got exit_code: 2000"
249+
); // ERROR_PRICE_FEED_NOT_FOUND = 2000
250250

251251
const updateData = Buffer.from(HERMES_BTC_ETH_UPDATE, "hex");
252252
const updateFee = await pythTest.getUpdateFee(updateData);
@@ -280,8 +280,8 @@ describe("PythTest", () => {
280280
const invalidUpdateData = Buffer.from("invalid data");
281281

282282
await expect(pythTest.getUpdateFee(invalidUpdateData)).rejects.toThrow(
283-
"Unable to execute get method. Got exit_code: 1021"
284-
); // ERROR_INVALID_MAGIC = 1021
283+
"Unable to execute get method. Got exit_code: 2002"
284+
); // ERROR_INVALID_MAGIC = 2002
285285
});
286286

287287
it("should fail to update price feeds with invalid data", async () => {
@@ -303,7 +303,7 @@ describe("PythTest", () => {
303303
from: deployer.address,
304304
to: pythTest.address,
305305
success: false,
306-
exitCode: 1021, // ERROR_INVALID_MAGIC
306+
exitCode: 2002, // ERROR_INVALID_MAGIC
307307
});
308308
});
309309

@@ -352,7 +352,7 @@ describe("PythTest", () => {
352352
from: deployer.address,
353353
to: pythTest.address,
354354
success: false,
355-
exitCode: 1024, // ERROR_UPDATE_DATA_SOURCE_NOT_FOUND
355+
exitCode: 2005, // ERROR_UPDATE_DATA_SOURCE_NOT_FOUND
356356
});
357357
});
358358

@@ -368,7 +368,7 @@ describe("PythTest", () => {
368368

369369
await expect(
370370
pythTest.getPriceNoOlderThan(TIME_PERIOD, BTC_PRICE_FEED_ID)
371-
).rejects.toThrow("Unable to execute get method. Got exit_code: 1020"); // ERROR_OUTDATED_PRICE = 1020
371+
).rejects.toThrow("Unable to execute get method. Got exit_code: 2001"); // ERROR_OUTDATED_PRICE = 2001
372372
});
373373

374374
it("should fail to update price feeds with insufficient gas", async () => {
@@ -387,7 +387,7 @@ describe("PythTest", () => {
387387
from: deployer.address,
388388
to: pythTest.address,
389389
success: false,
390-
exitCode: 1038, // ERROR_INSUFFICIENT_GAS
390+
exitCode: 3000, // ERROR_INSUFFICIENT_GAS
391391
});
392392
});
393393

@@ -413,7 +413,7 @@ describe("PythTest", () => {
413413
from: deployer.address,
414414
to: pythTest.address,
415415
success: false,
416-
exitCode: 1030, // ERROR_INSUFFICIENT_FEE = 1030
416+
exitCode: 2011, // ERROR_INSUFFICIENT_FEE = 2011
417417
});
418418
});
419419

@@ -425,15 +425,15 @@ describe("PythTest", () => {
425425

426426
await expect(
427427
pythTest.getPriceUnsafe(nonExistentPriceFeedId)
428-
).rejects.toThrow("Unable to execute get method. Got exit_code: 1019"); // ERROR_PRICE_FEED_NOT_FOUND = 1019
428+
).rejects.toThrow("Unable to execute get method. Got exit_code: 2000"); // ERROR_PRICE_FEED_NOT_FOUND = 2000
429429

430430
await expect(
431431
pythTest.getPriceNoOlderThan(TIME_PERIOD, nonExistentPriceFeedId)
432-
).rejects.toThrow("Unable to execute get method. Got exit_code: 1019"); // ERROR_PRICE_FEED_NOT_FOUND
432+
).rejects.toThrow("Unable to execute get method. Got exit_code: 2000"); // ERROR_PRICE_FEED_NOT_FOUND
433433

434434
await expect(
435435
pythTest.getEmaPriceUnsafe(nonExistentPriceFeedId)
436-
).rejects.toThrow("Unable to execute get method. Got exit_code: 1019"); // ERROR_PRICE_FEED_NOT_FOUND
436+
).rejects.toThrow("Unable to execute get method. Got exit_code: 2000"); // ERROR_PRICE_FEED_NOT_FOUND
437437
});
438438

439439
it("should correctly get chain ID", async () => {
@@ -735,7 +735,7 @@ describe("PythTest", () => {
735735
from: deployer.address,
736736
to: pythTest.address,
737737
success: false,
738-
exitCode: 1012, // ERROR_INVALID_GOVERNANCE_ACTION = 1012
738+
exitCode: 1012, // ERROR_INVALID_GOVERNANCE_ACTION
739739
});
740740

741741
// Verify that the governance data source index hasn't changed
@@ -773,7 +773,7 @@ describe("PythTest", () => {
773773
from: deployer.address,
774774
to: pythTest.address,
775775
success: false,
776-
exitCode: 1032, // ERROR_INVALID_GOVERNANCE_DATA_SOURCE
776+
exitCode: 2013, // ERROR_INVALID_GOVERNANCE_DATA_SOURCE
777777
});
778778
});
779779

@@ -809,7 +809,7 @@ describe("PythTest", () => {
809809
from: deployer.address,
810810
to: pythTest.address,
811811
success: false,
812-
exitCode: 1033, // ERROR_OLD_GOVERNANCE_MESSAGE
812+
exitCode: 2014, // ERROR_OLD_GOVERNANCE_MESSAGE
813813
});
814814
});
815815

@@ -839,7 +839,7 @@ describe("PythTest", () => {
839839
from: deployer.address,
840840
to: pythTest.address,
841841
success: false,
842-
exitCode: 1034, // ERROR_INVALID_GOVERNANCE_TARGET
842+
exitCode: 2015, // ERROR_INVALID_GOVERNANCE_TARGET
843843
});
844844
});
845845

@@ -976,7 +976,7 @@ describe("PythTest", () => {
976976
from: deployer.address,
977977
to: pythTest.address,
978978
success: false,
979-
exitCode: 1037, // ERROR_INVALID_CODE_HASH
979+
exitCode: 2018, // ERROR_INVALID_CODE_HASH
980980
});
981981

982982
// Verify that the contract has not been upgraded by attempting to call the new method

0 commit comments

Comments
 (0)