Last active
April 5, 2025 06:07
-
-
Save tvorogme/fdb174ac0740b6a52d1dbdf85f4ddc63 to your computer and use it in GitHub Desktop.
TON deploy smart contract
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/fift -s | |
"TonUtil.fif" include | |
"Asm.fif" include | |
// If you dont know about stack-base languages | |
// Please read something before read comments and trying to understand what is going on here :) | |
5 :$1..n // parse arguments | |
$1 parse-workchain-id =: wc // set workchain id from command line argument | |
$2 parse-int =: subwallet-id // set subwallet id | |
$3 =: file-base // set file path, we will save public key, boc, addr with this base | |
$4 =: fif-code // set fif code path | |
// Include fif-code compiled from func | |
// It will create cell for our code | |
// We will save it to stack | |
fif-code include | |
// Create data cell builder for wallet | |
// Data will be loaded on line 13 in func file of our smart contract | |
<b // Builder will now in top of stack | |
// https://newton-blockchain.github.io/docs/fiftbase.pdf - 5.2 Builder primitives, page 44 | |
// seqno, https://newton-blockchain.github.io/docs/tblkch.pdf - 1.3. Consistency conditions, page 12 | |
0 32 u, | |
// subwallet-id | |
subwallet-id 32 u, | |
// generate public / private key, save private key to file (in stack private and pub) | |
file-base +".pk" load-generate-keypair | |
constant wallet_pk // save wallet private key to constant | |
B, // add bin public key to cell | |
b> // Transform cell builder to cell | |
null // lib cell | |
// in stack now: (code, data, lib) cells | |
// Generate initialize message (StateInit), it's very hard to understand, but: | |
// https://newton-blockchain.github.io/docs/tblkch.pdf | |
// 1.7.3. Initializing smart contracts by constructor messages, page 27 | |
// 3.1.7. Message layout, page 56 | |
// TL-B schema of init message - https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L141 | |
// To understand TL-B - 3.3.4. Brief explanation of TL-B schemes., page 38 | |
<b | |
// _ split_depth:(Maybe (## 5)) special:(Maybe TickTock) | |
// code:(Maybe ^Cell) data:(Maybe ^Cell) | |
// library:(HashmapE 256 SimpleLib) = StateInit; | |
// split_depth - because of Maybe - 0 (more info about split_depth in 4.1. Accounts and their states, page 72: https://newton-blockchain.github.io/docs/tblkch.pdf | |
// special - because of Maybe - 0 (more info about 4.2. Transactions, page 77) | |
// code cell ref - 1 | |
// data cell ref - 1 | |
// library has HashmapE type it will defined after data in the end of builder | |
b{0011} s, | |
// code cell reference | |
3 roll ref, | |
// data cell reference | |
rot ref, | |
// library - by default its null dict (HashmapE type) examples of lib usage can be founded in: | |
// https://github.com/akifoq/ton-samples/blob/742dcaf3167a15b2f8c57c1699fbee28640523da/libs/new-lib.fif#L15 | |
swap dict, | |
b> | |
// The hash of the code and of the data | |
// contained in the constructor message must coincide with the address η of the | |
// smart contract; otherwise, it is rejected. | |
dup hashu // get sha256 hash of init message cell | |
wc // get workchain id (parsed in top of file) | |
swap // swap, because valid address scheme workchain id : sha256 | |
2dup 2constant wallet_addr // save address to wallet_addr and duplicate to stack | |
."new wallet address = " // print message to console | |
2dup // duplicate wallet address | |
.addr // print wallet address <workchain>:<account> (TonUtil.fif:40) | |
cr // endline print | |
2dup // duplicate wallet address again | |
file-base +".addr" // generate path for saving file | |
save-address-verbose // save address to file | |
// print addreses to console | |
."Non-bounceable address (for init): " 2dup 7 .Addr cr | |
."Bounceable address (for later access): " 6 .Addr cr | |
// Now in stack we have StateInit message | |
// Generate fist init message | |
<b // Will be loaded on line 10 in func file of our smart contract | |
subwallet-id 32 u, // subwallet id | |
-1 32 i, // valid_until | |
0 32 u, // msg_seqno | |
b> | |
// Console.log external message | |
dup ."signing message: " <s csr. cr | |
// In stack: StateInit, external message | |
// We need sign first message: | |
// https://newton-blockchain.github.io/docs/tblkch.pdf 1.2. Principal components of a block and the blockchain state, page 7 | |
dup hashu // get sha256 hash of external message | |
wallet_pk ed25519_sign_uint // sign sha256 with our private key | |
rot // get StateInit message back to top | |
// now in stack: "first external message, signed message, StateInit" | |
// Generate final external message | |
// External message scheme can be found: | |
// https://github.com/newton-blockchain/ton/blob/master/crypto/block/block.tlb#L147 | |
// message$_ {X:Type} info:CommonMsgInfo | |
// init:(Maybe (Either StateInit ^StateInit)) | |
// body:(Either X ^X) = Message X; | |
// | |
<b | |
// First we need to define info which is CommonMsgInfo | |
// You can Cntrl+F `CommonMsgInfo` in block.tlb, but: | |
// it can be: (int_msg_info$0 / ext_in_msg_info$10 / ext_out_msg_info$11) | |
// We need to take ext_in_msg_info$10 so our first bits will be => `10` | |
// You can find more information about it in 3.1.7. Message layout, page 56 | |
// When we chose CommonMsgInfo as ext_in_msg_info$10 | |
// | |
// https://github.com/newton-blockchain/ton/blob/master/crypto/block/block.tlb#L127 | |
// ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt | |
// import_fee:Grams = CommonMsgInfo; | |
// | |
// We need to define: src address, dest address, import fee | |
// So you can find in block.tlb MsgAddressExt: | |
// addr_none$00 = MsgAddressExt; | |
// addr_extern$01 len:(## 9) external_address:(bits len) | |
// = MsgAddressExt; | |
// https://newton-blockchain.github.io/docs/tblkch.pdf, 3.1.3. External addresses., page 54 | |
// We need to take none - so => `00` | |
// | |
// Next - dest address now it will be MsgAddressInt, we need addr_std$10 so - `10` | |
// Finally import_fee - set it to nothing => `0` | |
// Concat all bits - 1000100 | |
b{1000100} s, // write constructor | |
wallet_addr addr, // Define external address as wallet (contract) address (it is addr_std$10) | |
b{000010} s, // ??? | |
swap <s s, // StateInit | |
b{0} s, // ??? | |
swap B, // Append signed sha256 of our init message | |
swap <s s, // Append our init message | |
b> | |
// Generate boc | |
// 2 - it's a mode, checkout explanation: | |
// https://newton-blockchain.github.io/docs/fiftbase.pdf 5.6. Binary file I/O and Bytes manipulation, page 50 | |
2 boc+>B | |
// Console.log boc | |
."BOC: " dup Bx. cr | |
// Save boc to file! | |
file-base +".boc" tuck B>file | |
."(Saved wallet creating query to file " type .")" cr |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Simple wallet smart contract | |
() recv_internal(slice in_msg) impure { | |
;; do nothing for internal messages | |
} | |
() recv_external(slice in_msg) impure { | |
var signature = in_msg~load_bits(512); | |
var cs = in_msg; | |
var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32)); | |
throw_if(35, valid_until <= now()); | |
var ds = get_data().begin_parse(); | |
var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256)); | |
ds.end_parse(); | |
throw_unless(33, msg_seqno == stored_seqno); | |
throw_unless(34, subwallet_id == stored_subwallet); | |
throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key)); | |
accept_message(); | |
cs~touch(); | |
while (cs.slice_refs()) { | |
var mode = cs~load_uint(8); | |
send_raw_message(cs~load_ref(), mode); | |
} | |
set_data(begin_cell() | |
.store_uint(stored_seqno + 1, 32) | |
.store_uint(stored_subwallet, 32) | |
.store_uint(public_key, 256) | |
.end_cell()); | |
} | |
;; Get methods | |
int seqno() method_id { | |
return get_data().begin_parse().preload_uint(32); | |
} | |
int get_public_key() method_id { | |
var cs = get_data().begin_parse(); | |
cs~load_uint(64); | |
return cs.preload_uint(256); | |
} | |
int hello_world() method_id { | |
return 1234567890; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment