Skip to content

Commit

Permalink
feature(target_chains/ton): add upgrade standard (#1939)
Browse files Browse the repository at this point in the history
* add execute_upgrade_contract

* add upgrade feature

* precommit
  • Loading branch information
cctdaniel authored Sep 23, 2024
1 parent 0fc2579 commit fd354ae
Show file tree
Hide file tree
Showing 17 changed files with 535 additions and 377 deletions.
568 changes: 209 additions & 359 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions target_chains/ton/contracts/contracts/Main.fc
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@

;; * A 32-bit (big-endian) unsigned integer `op`, identifying the `operation` to be performed, or the `method` of the smart contract to be invoked.
int op = in_msg_body~load_uint(32);
;; * A 64-bit (big-endian) unsigned integer `query_id`, used in all query-response internal messages to indicate that a response is related to a query (the `query_id` of a response must be equal to the `query_id` of the corresponding query). If `op` is not a query-response method (e.g., it invokes a method that is not expected to send an answer), then `query_id` may be omitted.
int query_id = in_msg_body~load_uint(64);
cell data = in_msg_body~load_ref();
slice data_slice = data.begin_parse();

;; * The remainder of the message body is specific for each supported value of `op`.
if (op == OP_UPDATE_GUARDIAN_SET) {
update_guardian_set(in_msg_body);
update_guardian_set(data_slice);
} elseif (op == OP_EXECUTE_GOVERNANCE_ACTION) {
execute_governance_action(in_msg_body);
execute_governance_action(data_slice);
} elseif (op == OP_UPGRADE_CONTRACT) {
execute_upgrade_contract(data);
} else {
throw(0xffff); ;; Throw exception for unknown op
}
Expand Down
25 changes: 21 additions & 4 deletions target_chains/ton/contracts/contracts/Pyth.fc
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,25 @@ int apply_decimal_expo(int value, int expo) {
return result;
}

() execute_upgrade_contract(slice payload) impure {
;; TODO: Implement
() execute_upgrade_contract(cell new_code) impure {
load_data();
int hash_code = cell_hash(new_code);
throw_unless(ERROR_INVALID_CODE_HASH, upgrade_code_hash == hash_code);

;; Set the new code
set_code(new_code);

;; Set the code continuation to the new code
set_c3(new_code.begin_parse().bless());

;; Throw an exception to end the current execution
;; The contract will be restarted with the new code
throw(0);
}

() execute_authorize_upgrade_contract(slice payload) impure {
int code_hash = payload~load_uint(256);
upgrade_code_hash = code_hash;
}

() execute_authorize_governance_data_source_transfer(slice payload) impure {
Expand Down Expand Up @@ -317,8 +334,8 @@ int apply_decimal_expo(int value, int expo) {
}

() execute_governance_payload(int action, slice payload) impure {
if (action == UPGRADE_CONTRACT) {
execute_upgrade_contract(payload);
if (action == AUTHORIZE_UPGRADE_CONTRACT) {
execute_authorize_upgrade_contract(payload);
} elseif (action == AUTHORIZE_GOVERNANCE_DATA_SOURCE_TRANSFER) {
execute_authorize_governance_data_source_transfer(payload);
} elseif (action == SET_DATA_SOURCES) {
Expand Down
3 changes: 2 additions & 1 deletion target_chains/ton/contracts/contracts/common/errors.fc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const int ERROR_OLD_GOVERNANCE_MESSAGE = 1033;
const int ERROR_INVALID_GOVERNANCE_TARGET = 1034;
const int ERROR_INVALID_GOVERNANCE_MAGIC = 1035;
const int ERROR_INVALID_GOVERNANCE_MODULE = 1036;
const int ERROR_INVALID_CODE_HASH = 1037;

;; Common
const int ERROR_INSUFFICIENT_GAS = 1037;
const int ERROR_INSUFFICIENT_GAS = 1038;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const int UPGRADE_CONTRACT = 0;
const int AUTHORIZE_UPGRADE_CONTRACT = 0;
const int AUTHORIZE_GOVERNANCE_DATA_SOURCE_TRANSFER = 1;
const int SET_DATA_SOURCES = 2;
const int SET_FEE = 3;
Expand Down
1 change: 1 addition & 0 deletions target_chains/ton/contracts/contracts/common/op.fc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const int OP_UPDATE_GUARDIAN_SET = 1;
const int OP_UPDATE_PRICE_FEEDS = 2;
const int OP_EXECUTE_GOVERNANCE_ACTION = 3;
const int OP_UPGRADE_CONTRACT = 4;
3 changes: 3 additions & 0 deletions target_chains/ton/contracts/contracts/common/storage.fc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ global int single_update_fee;
global cell data_sources; ;; Dictionary of DataSource tuples, keyed by u8
global int num_data_sources;
global cell is_valid_data_source; ;; Dictionary of int (0 as false, -1 as true), keyed by DataSource cell_hash
global int upgrade_code_hash; ;; 256-bit unsigned integer


;; Wormhole
Expand Down Expand Up @@ -54,6 +55,7 @@ global int governance_data_source_index; ;; u32
.store_ref(governance_data_source)
.store_uint(last_executed_governance_sequence, 64)
.store_uint(governance_data_source_index, 32)
.store_uint(upgrade_code_hash, 256)
.end_cell();

begin_cell()
Expand Down Expand Up @@ -94,6 +96,7 @@ global int governance_data_source_index; ;; u32
governance_data_source = governance_slice~load_ref();
last_executed_governance_sequence = governance_slice~load_uint(64);
governance_data_source_index = governance_slice~load_uint(32);
upgrade_code_hash = governance_slice~load_uint(256);

ds.end_parse();
}
9 changes: 6 additions & 3 deletions target_chains/ton/contracts/contracts/tests/PythTest.fc
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@

int op = in_msg_body~load_uint(32);
cell data = in_msg_body~load_ref();
slice data_slice = data.begin_parse();
if (op == OP_UPDATE_GUARDIAN_SET) {
update_guardian_set(data.begin_parse());
update_guardian_set(data_slice);
} elseif (op == OP_UPDATE_PRICE_FEEDS) {
update_price_feeds(msg_value, data.begin_parse());
update_price_feeds(msg_value, data_slice);
} elseif (op == OP_EXECUTE_GOVERNANCE_ACTION) {
execute_governance_action(data.begin_parse());
execute_governance_action(data_slice);
} elseif (op == OP_UPGRADE_CONTRACT) {
execute_upgrade_contract(data);
} else {
throw(0xffff); ;; Throw exception for unknown op
}
Expand Down
78 changes: 78 additions & 0 deletions target_chains/ton/contracts/contracts/tests/PythTestUpgraded.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{-
This test contract is an upgraded version of PythTest.fc. This is used to test the upgrade functionality of the Pyth contract.
-}

#include "../imports/stdlib.fc";
#include "../Pyth.fc";
#include "../Wormhole.fc";
#include "../common/op.fc";

() recv_internal(int balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
if (in_msg_body.slice_empty?()) {
return ();
}

int op = in_msg_body~load_uint(32);
cell data = in_msg_body~load_ref();
slice data_slice = data.begin_parse();
if (op == OP_UPDATE_GUARDIAN_SET) {
update_guardian_set(data_slice);
} elseif (op == OP_UPDATE_PRICE_FEEDS) {
update_price_feeds(msg_value, data_slice);
} elseif (op == OP_EXECUTE_GOVERNANCE_ACTION) {
execute_governance_action(data_slice);
} elseif (op == OP_UPGRADE_CONTRACT) {
execute_upgrade_contract(data);
} else {
throw(0xffff); ;; Throw exception for unknown op
}
}

(int, int, int, int) test_get_price_unsafe(int price_feed_id) method_id {
return get_price_unsafe(price_feed_id);
}

(int, int, int, int) test_get_price_no_older_than(int time_period, int price_feed_id) method_id {
return get_price_no_older_than(time_period, price_feed_id);
}

(int, int, int, int) test_get_ema_price_unsafe(int price_feed_id) method_id {
return get_ema_price_unsafe(price_feed_id);
}

(int, int, int, int) test_get_ema_price_no_older_than(int time_period, int price_feed_id) method_id {
return get_ema_price_no_older_than(time_period, price_feed_id);
}

(int) test_get_update_fee(slice in_msg_body) method_id {
return get_update_fee(in_msg_body);
}

(int) test_get_single_update_fee() method_id {
return get_single_update_fee();
}

(int) test_get_chain_id() method_id {
return get_chain_id();
}

(int) test_get_last_executed_governance_sequence() method_id {
return get_last_executed_governance_sequence();
}

(int) test_get_governance_data_source_index() method_id {
return get_governance_data_source_index();
}

(cell) test_get_governance_data_source() method_id {
return get_governance_data_source();
}

(int) test_get_is_valid_data_source(cell data_source) method_id {
return get_is_valid_data_source(data_source);
}

;; Add a new function to demonstrate the upgrade
(int) test_new_function() method_id {
return 1;
}
3 changes: 2 additions & 1 deletion target_chains/ton/contracts/contracts/tests/WormholeTest.fc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@

int op = in_msg_body~load_uint(32);
cell data = in_msg_body~load_ref();
slice data_slice = data.begin_parse();
if (op == OP_UPDATE_GUARDIAN_SET) {
update_guardian_set(data.begin_parse());
update_guardian_set(data_slice);
} else {
throw(0xffff); ;; Throw exception for unknown op
}
Expand Down
1 change: 1 addition & 0 deletions target_chains/ton/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@ton/ton": "^13.11.2",
"@types/jest": "^29.5.12",
"@types/node": "^20.14.10",
"@wormhole-foundation/sdk-definitions": "^0.10.7",
"jest": "^29.7.0",
"prettier": "^3.3.2",
"ts-jest": "^29.2.0",
Expand Down
Loading

0 comments on commit fd354ae

Please sign in to comment.