1+ ;; Simple library keeper
2+
3+ #include "stdlib.func";
4+
5+ const int DEFAULT_DURATION = 3600 * 24 * 365 * 10;
6+ const int ONE_TON = 1000000000;
7+
8+ const int op::register_library = 0x7f567a32;
9+ const int op::upgrade_code = 0x3a6a2217;
10+ const int op::excesses = 0xd53276db;
11+
12+ () set_lib_code(cell code, int mode) impure asm "SETLIBCODE";
13+
14+ (int, int) get_current_masterchain_storage_prices() method_id {
15+ (_, slice latest_prices, _) = config_param(18).udict_get_max?(32);
16+ throw_unless(101, latest_prices~load_uint(8) == 0xcc);
17+ latest_prices~skip_bits(32 + 64 + 64); ;; tag, base_bits, base_cells
18+ return (latest_prices~load_uint(64),latest_prices~load_uint(64));
19+ }
20+
21+ int get_library_payment_period() method_id {
22+ var pp_cell = config_param(75);
23+ if(pp_cell.cell_null?()) {
24+ pp_cell = config_param(-75);
25+ }
26+ if(pp_cell.cell_null?()) {
27+ return DEFAULT_DURATION;
28+ }
29+ var pp = pp_cell.begin_parse();
30+ return pp~load_uint(64);
31+ }
32+
33+ () send_message_back(addr, ans_tag, query_id, amount, mode) impure inline_ref {
34+ ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress -> 011000
35+ var msg = begin_cell()
36+ .store_uint(0x18, 6)
37+ .store_slice(addr)
38+ .store_grams(amount)
39+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
40+ .store_uint(ans_tag, 32)
41+ .store_uint(query_id, 64);
42+ send_raw_message(msg.end_cell(), mode);
43+ }
44+
45+ slice get_sender(cell in_msg_full) inline_ref {
46+ slice cs = in_msg_full.begin_parse();
47+ cs~skip_bits(4);
48+ return cs~load_msg_addr();
49+ }
50+
51+
52+ slice make_address(int wc, int addr) inline {
53+ return begin_cell()
54+ .store_uint(4, 3).store_int(wc, 8).store_uint(addr, 256).end_cell().begin_parse();
55+ }
56+
57+ slice config_address() inline {
58+ int config = config_param(0).begin_parse().preload_uint(256);
59+ return make_address(-1, config);
60+ }
61+
62+ cell get_fundamental_addresses() inline {
63+ slice cs = config_param(31).begin_parse();
64+ return cs~load_dict();
65+ }
66+
67+ (int, slice) get_blackhole_address() inline {
68+ cell burning_config = config_param(5);
69+ if(burning_config.cell_null?()) {
70+ return (false, null());
71+ }
72+ slice cs = burning_config.begin_parse();
73+ ifnot(cs~load_int(1)) {
74+ return (false, null());
75+ }
76+ return (true, make_address(-1, cs~load_uint(256)));
77+ }
78+
79+ () recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
80+ if (in_msg_body.slice_empty?()) { ;; ignore empty messages
81+ return ();
82+ }
83+ slice cs = in_msg_full.begin_parse();
84+ int flags = cs~load_uint(4);
85+
86+ if (flags & 1) { ;; ignore all bounced messages
87+ return ();
88+ }
89+ slice sender = cs~load_msg_addr();
90+
91+ int op = in_msg_body~load_uint(32);
92+ int query_id = in_msg_body~load_uint(64);
93+ if(op == op::register_library) {
94+ int max_cells = in_msg_body~load_uint(32);
95+ cell code = in_msg_body~load_ref();
96+ var (cells, bits, _) = compute_data_size(code, max_cells);
97+ var (bit_price, cell_price) = get_current_masterchain_storage_prices();
98+ int payment_period = get_library_payment_period();
99+ int payment = (bit_price * bits + cell_price * cells) * payment_period >> 16;
100+ msg_value -= payment;
101+ throw_unless(102, msg_value >= 0);
102+ set_lib_code(code, 2);
103+ send_message_back(sender, op::excesses, query_id, msg_value, 0);
104+ } elseif(op == op::upgrade_code) {
105+ throw_unless(103, equal_slice_bits(sender, config_address()));
106+ cell code = in_msg_body~load_ref();
107+ set_code(code);
108+ } else {
109+ throw(0xffff);
110+ }
111+ cell fundamental = get_fundamental_addresses();
112+ (int my_wc, int my_addr_hash) = parse_std_addr(my_address());
113+ if(my_wc == -1) {
114+ (int blackhole_active, slice blackhole) = get_blackhole_address();
115+ if(blackhole_active) {
116+ (_, int found?) = fundamental.udict_get?(256, my_addr_hash);
117+ if(found?) {
118+ ;; send everything except one ton, ignore errors
119+ raw_reserve(ONE_TON, 2);
120+ send_message_back(blackhole, op::excesses, query_id, 0, 2 | 128);
121+ }
122+ }
123+ }
124+ }
0 commit comments