What i refer to list(for simplicity) in this document, is in fact dictionary with sequentially ordered indexes.
All of such structures (signers
, proposers
, order
) should be checked for indexes order.
If list is not compliant with expected format, error::invalid_dictionary_sequence
should be thrown.
Signers is a list of wallet addresses of multiowner
wallet contract owners.
Each signer can create new order and vote for approval
Proposers is the list of wallet addresses allowed to only create new orders, but can't vote for approval.
- Only proposers and signers should be able to create new order.
- Order expiration time should exceed current time.
- Incoming value should be >= expected processing cost.
- Order can't be empty.
- Only successful
new_order
execution should produce deploy message fororder
contract. - Deploy message should result in successful
order
deployment with matching threshold, signers, number of signers, expiration date and order body. - Only successful
new_order
execution should result inorder_seqno
increase.
- Only
order
contract with accordingorder_seqno
andsigners
hash (specified in message) should be able to trigger that operation. signers
cell hash in incoming message should match current statesigners
hash. Should guarantee that change of signers results in orders invalidation.- Should trigger actions processing sequentially according to order list.
- Minimal processing cost calculated at
New order
stage should be >= actual costs of executing order including storage.
- Should only be able to trigger from self address.
- Main intention is to allow chained order execution.
- Should trigger actions processing according to passed order list.
Execute order message contains list with actions of two(currenty) types:
- Outgoing message.
- Update multisig parameters.
Specifies message mode and message cell.
Results in according message being sent.
Specifies multiowner state parameters such as:
- Order threshold
- Signers list
- Proposers list
- Modules prefix dictionary
- Guard contract cell
Should result in according contract state changes.
All features below should only be accessible when contract is deployed with EXPERIMENTAL_FEATURES
flag set.
- Module should be present in modules prefix dictionary by sender address used as a key.
- Should result in module order being processed
Guard is separate contract with it's own state (data/code) main purpose of which is to check execution context prior to action phase and react accordingly. For instance, prevent forbidden actions from execution.(?)
- Nobody except
proposers
andowners
can initiate creation of new order, nobody exceptowners
can approve new order. - Chenge of the
owners
set invalidates all orders with old set. Owner
compromise, in particularly compromise of less than Nowners
, does not hinder to execute orders or to propose new ones (including orders which will remove compromisedowners
from the owners list)Proposer
compromise does not hinder to execute orders or to propose new ones (including orders which will remove compromisedproposer
from the proposers list)- Logic of multiapproval wallet can not changed
- Order contract should only be able to initialize once.
- Order contract should only accept initialization messages from
multiowner
address. - Execution threshold should be set according to init message.
- Signers list should be set according to init message.
- Expiration date should exceed current timestamp(Should not be expired at the time of receiving a message).
- Expiration date should be set according to init message.
- Execution and approval state fields such as
approvals
(bit mask),approvals_num
,executed
should be zeroed out. - If signer initiated order contract deployment, it's approval should be accounted for. In case
threshold = 1
order should get executed.
Approval state is described with following fields:
approvals
is a bit mask where each bit describes signed position(bit position) and bit value describes presence of approval(true -> approved).approvals_num
is an approval counter that is compared againstthreshold
during order execution check.
In case approval is granted, bit is set in approvals
mask in accordance with signer position in signers
list.
For approval to be granted:
- Sender address should be present in
signers
list. - Signer index specified in message, should match sender address position at
signers
list. - Order should not be expired (
expiration_date < now()
). - Order can only be executed once
executed
field should befalse
. - Signer at specified index in
approvals
mask has not granted approval yet.(error::already_approved
)
In case order is expired:
- Message carrying remaining value and indicating expiry is sent back to approval sender address.
- Message carrying all of the order contract remaining balance is sent back to the
multiowner
contract.
In case order is already executed, message carrying remaining value is sent back to approval sender address.
On every initialization or order approval action, contract check if it's possible to execute order (order count has reached threshold). If so:
op::execute
message, carrying all remaining balance is sent tomultiowner
contract.executed
flag is set to true and repeated execution should not be possible afterwards.