Skip to content

Commit 8519d3b

Browse files
committed
Add Librarian contract/wrapper
1 parent dcddc59 commit 8519d3b

File tree

3 files changed

+138
-2
lines changed

3 files changed

+138
-2
lines changed

contracts/librarian.func

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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+
}

wrappers/Librarian.compile.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { CompilerConfig } from '@ton-community/blueprint';
2+
3+
export const compile:CompilerConfig = {
4+
targets: ['contracts/stdlib.func', 'contracts/librarian.func']
5+
};

wrappers/Librarian.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ export function librarianConfigToCell(config: LibrarianConfig): Cell {
1313
export class Librarian implements Contract {
1414
constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}
1515

16+
async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
17+
await provider.internal(via, {
18+
value,
19+
sendMode: SendMode.PAY_GAS_SEPARATELY
20+
});
21+
}
22+
1623
static createFromAddress(address: Address) {
1724
return new Librarian(address);
1825
}
@@ -23,14 +30,14 @@ export class Librarian implements Contract {
2330
return new Librarian(contractAddress(workchain, init), init);
2431
}
2532

26-
async sendAddLibrary(provider: ContractProvider, via: Sender, code:Cell, value:bigint = toNano('50')) {
33+
async sendAddLibrary(provider: ContractProvider, via: Sender, code:Cell, value:bigint = toNano('250')) {
2734
await provider.internal(via, {
2835
value: value,
2936
sendMode: SendMode.PAY_GAS_SEPARATELY,
3037
body: beginCell()
3138
.storeUint(0x7f567a32, 32) // op = top up
3239
.storeUint(0, 64) // query id
33-
.storeUint(2000, 32) // query id
40+
.storeUint(2000, 32) // max_cells
3441
.storeRef(code)
3542
.endCell(),
3643
});

0 commit comments

Comments
 (0)