In some case one may want to execute an action only if many users approve this action. This kind of pattern is called multi-signature.
Multi-signature
When invoking a smart contract, an entrypoint is called and usually an action is executed (triggering a storage modification and/or transactions emmission). The purpose of a multi-signature pattern is to execute an action when all preconditions has been verified. The action that need to be executed depends on the smart contract logic. The mutli-signature implementation can be done in a single contract with the smart contract logic or in a separated contract like a proxy contract which emits transactions to the contract containing the logic.
Rules
The multi-signature pattern can be described with this set of rules :
- a user can propose an action
- a user can approve an action (proposed by someone else)
- a user can cancel his approval on an action.
- an action is automatically executed when it has been approved by enough users (a threshold of number of approvals must be defined)
- the smart contract must also handle a list of user in order to specify who is allowed to approve an action
Optionally
- the smart contract can also handle the number of approval per user and set the maximum number of approvals.
- the smart contract can also handle an inner state. Everytime an action is executed the inner state of the multi-signature contract is updated for tracability purpose
More complex rules can be added to these basic ones.
Implementation of multi-signature patterns
Let’s consider this implementation of the multi-signature pattern. This implementation takes all previously mentionned rules into account.
This smart contract MultisigProxy intends to play the role of a proxy pattern for the Counter contract. The Counter contract (the example at https://ide.ligolang.org/p/-hNqhvMFDFdsTULXq4K-KQ) has been deployed at address : KT1CFBbdhRCNAzNkX56v361XZToHCAtjSsVS The Counter contract handle a simple integer counter which can be incremented or decremented.
Instead of invoking the Counter contract, users propose a modification of the counter (e.g. Increment(5)) to the MultisigProxy contract which will forward it to the Counter contract (if approved by other users).
A user can invoke the entry point Send of the smart contract MultisigProxy to propose or approve a modification of the counter. When the number of approvals is reached, the desired modification is sent to the contract Counter via a transaction. A user can invoke the entry point Withdraw of the smart contract MultisigProxy to reject a proposed modification.
Loading...
Notice that in the Send function the number of voters is compared to the threshold. If the threshold is reached then:
- the message packed_msg is removed from message_storage
- the action is executed and takes the string as parameter
- the inner state state_hash of the contract is updated by creating a hash key of old state + treated message
- the counter (of number of proposals) is updated. This is used to compute the limit of maximum of proposal.
Loading...
Notice that in the Withdraw function :
- if a message proposal has no voters then it is removed
- the counter (of number of proposals) is updated. This is used to compute the limit of maximum of proposal.
Your mission
We have a basic mutli-signature contract but voters don’t approve quickly enough. Maybe if we grant a reward to signers it may speed the voting process. Modify the existing Multisig contract in order to handle a reputation level for each voters. We plan to grant “reputation” points when the message is really executed (one “reputation” point for each voters).
1- Notice that the storage contains a property called reputation which associates a nat number to a voter.
2- Modify the increment function to modify the reputation of a given addr address by granting one point of reputation. (use count as temporary variable for the match operator). If the voter is not registered yet in the reputation registry then add him. Otherwise update its reputation by incrementing by one its actual level. It is recommanded to use Map.add and Map.update when modifying a map.
3- Modify the reputation_updated variable (representing the new state of reputations) by iterating on voters with a Set.fold operation and applying increment function on reputation.
Loading…