Skip to content

Instantly share code, notes, and snippets.

@rainydio
Created October 21, 2019 02:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rainydio/a86a29d7e880d818597731000cedc5ef to your computer and use it in GitHub Desktop.
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.
"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