Created
October 21, 2019 02:06
-
-
Save rainydio/a86a29d7e880d818597731000cedc5ef to your computer and use it in GitHub Desktop.
Rather simple 2/3 multi-sig wallet. Intended to be used by a single person.
This file contains 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
"Asm.fif" include | |
"TonUtil.fif" include | |
16 @Sreg s16 | |
-1 constant MSG_TYPE_EXTERNAL | |
101 constant EXT_MSG_ORDER | |
100 constant EXT_MSG_ORDER_CANCEL | |
206 constant STATE_WAIT_ORDER | |
210 constant STATE_WAIT_CONFIRMATION | |
0 constant OK | |
30 constant ERR_MSG_INVALID | |
31 constant ERR_MSG_TYPE_INVALID | |
32 constant ERR_MSG_SIGNATURE_INVALID | |
33 constant ERR_MSG_SEQNO_INVALID | |
34 constant ERR_MSG_EXP_INVALID | |
35 constant ERR_MSG_ORDER_INVALID | |
<{ // s_msg, msg_type | |
SETCP0 | |
DUP MSG_TYPE_EXTERNAL INT EQUAL <{ // s_msg, msg_type_external | |
DROP // s_msg | |
PUSHROOT CTOS // s_msg, s_root | |
32 LDU // state_seqno // s_msg, state_seqno, s_root | |
OVER ISZERO <{ | |
// zero state, contract constructor | |
// just set state_seqno to 1 and put the rest of the root back | |
1 INT NEWC 32 STU STSLICE ENDC POPROOT | |
2DROP | |
}> PUSHCONT IFJMP | |
// 3 keys | |
256 LDU 256 LDU 256 LDU | |
// out_ttl_min | |
32 LDU | |
DUP 42 INT 1 INT SCHKBITREFSQ <{ | |
// wait confirmation state | |
// expiration, sendrawmsg parameters, and key no that created order | |
// out_exp, out_mode, out_ref, order_key_no | |
32 LDU 8 LDU LDREF 2 LDU ENDS | |
9 0 REVERSE | |
STATE_WAIT_CONFIRMATION INT | |
// put s_msg on top | |
10 ROLL | |
}> PUSHCONT <{ | |
ENDS | |
5 0 REVERSE | |
STATE_WAIT_ORDER INT | |
// put s_msg on top | |
6 ROLL | |
}> PUSHCONT IFELSE | |
// signature | |
512 INT LDSLICEX | |
// msg_hash, intended recipient is included in signature (700 gas ouch) | |
DUP MYADDR NEWC STSLICE STSLICE ENDC HASHCU SWAP | |
// msg_seqno, msg_exp, msg_mode, msg_ref | |
32 LDU 32 LDU 8 LDU LDREF | |
// put msg_seqno on top | |
4 1 REVERSE | |
DUP 1 INT SCHKBITSQ <{ | |
// order cancelation msg has additional bit set to 1 at the end | |
1 LDU ENDS | |
DUP 1 INT EQUAL | |
ERR_MSG_INVALID THROWIFNOT | |
EXT_MSG_ORDER_CANCEL INT | |
}> PUSHCONT <{ | |
ENDS | |
EXT_MSG_ORDER INT | |
}> PUSHCONT IFELSE | |
// 16 order_key_no | |
// 15 out_ref | |
// 14 out_mode | |
// 13 out_exp | |
// (wait confirmation) | |
// | |
// 12 out_ttl_min | |
// 11 key3 | |
// 10 key2 | |
// 09 key1 | |
// 08 state_seqno | |
// 07 state_type | |
// | |
// 06 msg_signature | |
// 05 msg_hash | |
// 04 msg_ref | |
// 03 msg_mode | |
// 02 msg_exp | |
// 01 msg_seqno | |
// 00 msg_type | |
s7 PUSH STATE_WAIT_CONFIRMATION INT EQUAL <{ | |
s13 PUSH NOW LESS <{ | |
// wait order transition | |
4 13 BLKSWAP 4 BLKDROP | |
STATE_WAIT_ORDER INT | |
s8 s0 XCHG DROP | |
}> PUSHCONT IF | |
}> PUSHCONT IF | |
s7 PUSH STATE_WAIT_ORDER INT EQUAL <{ | |
DUP EXT_MSG_ORDER INT EQUAL | |
ERR_MSG_TYPE_INVALID THROWIFNOT | |
// wait confirmation transition | |
// msg_seqno = state_seqno | |
s1 s8 PUSH2 EQUAL | |
ERR_MSG_SEQNO_INVALID THROWIFNOT | |
8 ROLL INC 8 ROLLREV | |
// out_exp > now + out_ttl_min | |
s2 s12 PUSH2 NOW ADD GREATER | |
ERR_MSG_EXP_INVALID THROWIFNOT | |
s2 PUSH 13 ROLLREV | |
// out_mode | |
s3 PUSH 14 ROLLREV | |
// out_ref | |
s4 PUSH 15 ROLLREV | |
// order_key_no | |
s5 s6 s9 PUSH3 CHKSIGNU <{ 1 INT }> PUSHCONT <{ | |
s5 s6 s10 PUSH3 CHKSIGNU <{ 2 INT }> PUSHCONT <{ | |
s5 s6 s11 PUSH3 CHKSIGNU <{ 3 INT }> PUSHCONT <{ | |
0 INT | |
}> PUSHCONT IFELSE | |
}> PUSHCONT IFELSE | |
}> PUSHCONT IFELSE | |
DUP ISZERO NOT | |
ERR_MSG_SIGNATURE_INVALID THROWIFNOT | |
16 ROLLREV | |
8 BLKDROP | |
NEWC 32 STU 256 STU 256 STU 256 STU 32 STU 32 STU 8 STU STREF 2 STU ENDC | |
POPROOT | |
ACCEPT | |
}> PUSHCONT IFJMP | |
s7 PUSH STATE_WAIT_CONFIRMATION INT EQUAL <{ | |
// expecting previous seqno | |
s1 s8 PUSH2 DEC EQUAL | |
ERR_MSG_SEQNO_INVALID THROWIFNOT | |
// out_exp = msg_exp | |
s2 s13 PUSH2 EQUAL | |
ERR_MSG_ORDER_INVALID THROWIFNOT | |
// out_mode = msg_mode | |
s3 s14 PUSH2 EQUAL | |
ERR_MSG_ORDER_INVALID THROWIFNOT | |
// out_ref = msg_ref | |
s4 s15 PUSH2 HASHCU SWAP HASHCU EQUAL | |
ERR_MSG_ORDER_INVALID THROWIFNOT | |
s16 PUSH FALSE | |
// not order_key_no | |
OVER 1 INT NEQ <{ | |
s7 s8 s11 PUSH3 CHKSIGNU OR | |
}> PUSHCONT IF | |
// ... and not found second signature already | |
OVER 2 INT NEQ OVER NOT AND <{ | |
s7 s8 s12 PUSH3 CHKSIGNU OR | |
}> PUSHCONT IF | |
OVER 3 INT NEQ OVER NOT AND <{ | |
s7 s8 s13 PUSH3 CHKSIGNU OR | |
}> PUSHCONT IF | |
ERR_MSG_SIGNATURE_INVALID THROWIFNOT | |
DROP | |
// order cancel is nop | |
DUP EXT_MSG_ORDER INT EQUAL <{ | |
// send out_ref with out_mode flags | |
s15 s14 PUSH2 SENDRAWMSG | |
}> PUSHCONT IF | |
// wait order transition | |
8 BLKDROP 4 4 BLKSWAP 4 BLKDROP | |
NEWC 32 STU 256 STU 256 STU 256 STU 32 STU ENDC | |
POPROOT | |
ACCEPT | |
}> PUSHCONT IFJMP | |
}> PUSHCONT IFJMP | |
}>c constant contract-code | |
{ // out_ttl_min, key1, key2, key3 | |
3 0 reverse // out_ttl_min, key3, key2, key1 | |
<b | |
0 32 u, // state_seqno | |
swap B, // key1 | |
swap B, // key2 | |
swap B, // key3 | |
swap 32 u, // out_ttl_min | |
// wait confirmation state: | |
// 32 u, // out_exp | |
// 8 u, // out_mode | |
// ref, // out_ref | |
// 2 u, // order_key_no | |
b> | |
} : contract-root | |
{ // state_seqno, out_exp, out_mode, out_ref | |
4 0 reverse <b swap 32 u, swap 32 u, swap 8 u, swap ref, b> | |
} : contract-order | |
{ // order | |
<b swap <s s, 1 1 u, b> | |
} : contract-cancel-order | |
{ // order, ad-,-dress, pvtkey | |
3 -roll // pvtkey, order, ad-,-dress | |
<b -rot addr, over <s s, b> hashu // pvtkey, order, order_hash | |
rot ed25519_sign_uint // order, signature | |
<b swap B, swap <s s, b> // signed_order | |
} : contract-order-sign | |
0 0xfcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260 | |
2constant test-address | |
{ // s_msg, msg_type | |
-1 | |
contract-code <s | |
3 roll | |
| 0 , 1 , 2 , now , 4 , 5 , 6 , 7 , <b test-address addr, b> <s , 1 tuple // s_msg, msg_type, root, c7 | |
runvmctx // (0,) code, root' | |
over 0= { swap } { -rot nip } cond // root', code | |
} : test-run | |
newkeypair drop constant key1 | |
newkeypair drop constant key2 | |
newkeypair drop constant key3 | |
90 | |
key1 priv>pub | |
key2 priv>pub | |
key3 priv>pub | |
contract-root | |
<b b> | |
<s test-run OK <> abort"init" | |
1 now 120 + 0 <b b> contract-order constant order1 | |
order1 test-address key1 contract-order-sign | |
<s test-run OK <> abort"order1" | |
order1 test-address key1 contract-order-sign | |
<s test-run ERR_MSG_SIGNATURE_INVALID <> abort"order1" | |
order1 test-address key2 contract-order-sign | |
<s test-run OK <> abort"order1" | |
order1 test-address key1 contract-order-sign | |
<s test-run ERR_MSG_SEQNO_INVALID <> abort"order1" | |
2 now 120 + 0 <b b> contract-order constant order2 | |
3 now 120 + 0 <b b> contract-order constant order3 | |
order2 test-address key2 contract-order-sign | |
<s test-run OK <> abort"order2" | |
order3 test-address key3 contract-order-sign | |
<s test-run ERR_MSG_SEQNO_INVALID <> abort"order3" | |
order2 test-address key1 contract-order-sign | |
<s test-run OK <> abort"order2" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment