UniGoldCoin is indivisible token representing the right to reclaim physical gold coin. The digital token gets created after physical gold coin batch got manufactured. The creaton of the digital tokens governed by flexible governance scheme.
Deployed on Ethereum mainnet:
Burner contract receives and burns UniGoldCoin token and triggers coin delivery to the sender.
The Congress contract allows to execute certain actions (token minting in this case) via majority of votes.
In contrast to traditional Ownable pattern, Congress protects the managed contract (token) against
unfair behaviour of minority (for example, a single founder having one of the project keys has no
power to mint the token until other(s) vote for the operation).
Majority formula is voters/2+1
. The voters list is formed dynamically through the voting. Voters
can be added if current majority trusts new party. The party can be removed from the voters if it
has been compromised (majority executes untrust operation on it to do this).
The Congress intentionally has primitive interface to hide proposal management complexity. The interaction with it looks like:
Voter1 Voter2 Voter3 Voter4 Voter5 Congress Token
| | | | | | |
| | 1. deploy Congress | | |
+-+-----------------------+-----------------------------------------> |
||| | | | | | |
||| | | 2. deploy Token(Congress) | |
||+-----------------------+----------------------------------------------------------------->
||| | 3. setToken(Token) | |
||+-----------------------+-----------+-----------+-----------------> |
||| | | | | | |
Congress has a sender address (who deployed the contract) as a single voter, the majority is 1/1, and the single mint() call will go through all the proposal steps - it gets created, votes set to 1, majority gets achieved and the .mint() method on the token gets immediately executed.
Voter1 Voter2 Voter3 Voter4 Voter5 Congress Token
||| | | | | | |
||| | | | | | |
||| | | 4. mint(args...) | |
||+-----------------------------------+-----------+-----------------> 1/1, mint |
||| | | | | +---------------------->|
The scheme with the single voter doesn't give any protection against unfair behaviour, and 1/1 state is transient to add other trusted parties. The new voter candidate should generate Ethereum private key on its own and provide address to the Voter1. Then Voter1 executes .trust(Voter2) transaction (5) and since it's a single voter, the single call is enough to allow this request.
Now Congress has 2 voters configuration and majority formulae is 2/2. If the team decides to mint some amount of tokens they should both agree on minting parameters (_to, _amount, _batchCode), these parameters get hashed and reference to a common proposal hash.
Voter1 Voter2 Voter3 Voter4 Voter5 Congress Token
||| | | | | | |
||| | | 5. trust(Voter2). | |
||+-----------------------------------+-----------+-----------------> 1/1, trust, =2 voters |
||| ||| | | | | |
||| ||| | 6. mint(args...) | | |
||| ||+----------------------------------------------------> 1/2, wait |
||+-----------------------------------------------------------------> 2/2, mint |
||| ||| | | | +----------------------->
||| ||| | | | | |
The 2-voters sheme has no protection against loss of a single key. If one of the secrets lost, the further operations will be impossible, so it's recommended to have redundant options like 2/3, 3/4, 3/5, 4/6, 4/7, 5/8 and so on.
Now both (2/2) voters can add third one via .trust(Voter3) command (7,8).
Voter1 Voter2 Voter3 Voter4 Voter5 Congress
||| ||| | | | |
||| ||| | 7. trust(Voter3), 1/2| |
||| ||+----------------------+----------------------------->1/2, wait
||| ||| | | | |
||| ||| | 8. trust(Voter3), 2/2 = 3Voters |
||+-----------------------------------+-----------+----------------->2/2, trust, =3 voters
||| ||| ||| | | |
with 3 voters request gets executed after 2 votes. On the diagram below Voter2 and Voter3 do the mint request with given arguments. The first request initiates proposal and sets votes to 1, the second increments counter to 2. 2 votes is enough for 3 parties, so it gets executed.
Voter1 Voter2 Voter3 Voter4 Voter5 Congress Token
||| ||| ||| | | | |
||| ||| ||| 9. mint(args) | | |
||| ||| ||+---------------------------------------> 1/3, wait |
||| ||+----------------------------------------------------> 2/3, mint |
||| ||| ||| | | +----------------------->
||| ||| ||| | | | |
To add 4th voter the Congress needs 2 trust votes of 3 participants.
Voter1 Voter2 Voter3 Voter4 Voter5 Congress
||| ||| ||| | | |
||| ||| ||| 10.trust(Voter4) | |
||| ||| ||+---------------------------------------> 1/3, wait
||| ||+----------------------------------------------------> 2/3, trust, =4 voters
||| ||| ||| ||| | |
With 4 voters proposal needs to get 3 votes to execute.
Voter1 Voter2 Voter3 Voter4 Voter5 Congress Token
||| ||| ||| ||| | | |
||| ||| 11. mint(args...) | | |
||| ||+----------------------------------------------------> 1/4, wait |
||| ||| ||+---------------------------------------> 2/4, wait |
||| ||| ||| ||+---------------------------> 3/4, mint |
||| ||| ||| ||| | +----------------------->
||| ||| ||| ||| | | |
The configuration can be changed to any number of voters (trust actions extend voters list, untrust - collapse it).
Running tests
npm install
npm run test
or see latest test results on travis