-
Notifications
You must be signed in to change notification settings - Fork 6
/
generic.tz
91 lines (85 loc) · 3.3 KB
/
generic.tz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
parameter (or (unit %default)
(pair %main
(pair :payload
(nat %counter) # counter, used to prevent replay attacks
(or :action # payload to sign, represents the requested action
(lambda %operation unit (list operation))
(pair %change_keys # change the keys controlling the multisig
(nat %threshold) # new threshold
(list %keys key)))) # new list of keys
(list %sigs (option signature)))); # signatures
storage (pair (nat %stored_counter) (pair (nat %threshold) (list %keys key))) ;
code
{
UNPAIR ;
IF_LEFT
{ # Default entry point: do nothing
# This entry point can be used to send tokens to this contract
DROP ; NIL operation ; PAIR }
{ # Main entry point
# Assert no token was sent:
# to send tokens, the default entry point should be used
PUSH mutez 0 ; AMOUNT ; ASSERT_CMPEQ ;
SWAP ; DUP ; DIP { SWAP } ;
DIP
{
UNPAIR ;
# pair the payload with the current contract address, to ensure signatures
# can't be replayed accross different contracts if a key is reused.
DUP ; SELF ; ADDRESS ; CHAIN_ID ; PAIR ; PAIR ;
PACK ; # form the binary payload that we expect to be signed
DIP { UNPAIR @counter ; DIP { SWAP } } ; SWAP
} ;
# Check that the counters match
UNPAIR @stored_counter; DIP { SWAP };
ASSERT_CMPEQ ;
# Compute the number of valid signatures
DIP { SWAP } ; UNPAIR @threshold @keys;
DIP
{
# Running count of valid signatures
PUSH @valid nat 0; SWAP ;
ITER
{
DIP { SWAP } ; SWAP ;
IF_CONS
{
IF_SOME
{ SWAP ;
DIP
{
SWAP ; DIIP { DUUP } ;
# Checks signatures, fails if invalid
{ DUUUP; DIP {CHECK_SIGNATURE}; SWAP; IF {DROP} {FAILWITH} };
PUSH nat 1 ; ADD @valid } }
{ SWAP ; DROP }
}
{
# There were fewer signatures in the list
# than keys. Not all signatures must be present, but
# they should be marked as absent using the option type.
FAIL
} ;
SWAP
}
} ;
# Assert that the threshold is less than or equal to the
# number of valid signatures.
ASSERT_CMPLE ;
# Assert no unchecked signature remains
IF_CONS {FAIL} {} ;
DROP ;
# Increment counter and place in storage
DIP { UNPAIR ; PUSH nat 1 ; ADD @new_counter ; PAIR} ;
# We have now handled the signature verification part,
# produce the operation requested by the signers.
IF_LEFT
{ # Get operation
UNIT ; EXEC
}
{
# Change set of signatures
DIP { CAR } ; SWAP ; PAIR ; NIL operation
};
PAIR }
}