Here is an implementation suggestion for group currencies.
Textual description:
A group currency would define a number of individual Circles tokens directly or transitively (all accounts trusted by account X) as members. All of those members Circles could be used to mint the group currency.
Because of the minting rule that always requires to use personal Circles all group currency will be “backed” (potentially transitively in layered groups) by personal Circles.
Optionally a group currency can offer to redeem group currency for underlying tokens. This can be restricted by additional rules or made available to anyone.
Optionally a fee can be charged for minting group currency and/or redeeming group currency.
is ERC20
owner // has admin rights - specifically adding and removing accounts to the group
redeemer // has the right to redeem group currency for underlying tokens (optional, can be public)
/* dictionary of (Circles) ERC20 addresses that are members - side note: we do not need to check that those tokens are personal Circles ERC20 - they could also be other group currencies to create layered groups*/
direct_members{} // address (ERC20 token) -> boolean
/* dictionary of Circles accounts (personal or shared accounts)
those act as trust delegates, if an account is trusted by an account in this dictionary it will be transitively a member*/
delegated_trustees{} // address (account) -> boolean
mint_fee
add_member(address):
require(msg.sender = owner)
direct_members[address] = true
remove_member(address):
require(msg.sender = owner)
direct_members[address] = false
/* potentially the same functions with batch functionality; equivalent for groups */
// Group currently is created from collateral tokens. Collateral is either directly part of the direct_members dictionary or trusted by someone in the delegated_trustees dictionary.
mint(trusted_by, collateral, amount):
if trusted_by != 0:
require(trusted_by in delegated_trustees)
require(trusted_by.trust(collateral)
else:
require(direct_members[collateral])
collateral.transer_from(from:msg.sender, to:this, amount=amount)
mint amount * (1-mint-fee)
// send minted amount to msg.sender
redeem(ERC20, amount)
if redeemer != 0: require(msq.sender = redeemer)
//burn group currency
this.transfer_from(msg.sender, 0x0000, amount)
//send ERC20 to redeemer
account.transfer(msg.sender, amount)
Optional the group currency can register in the Circles WOT and trust all Circles that it would allow to use for minting (all members). This would allow others to make transitive transfers trough this account. The potential downside would be that the group currency would likely become only backed by the “weakest Circles” of the group instead of trough an average pool as anyone could extract more valuable Circles for the least valuable Circles that are part of the group.
P.S: One alternative way to add various redeem logic is to simply specify a contract (“treasury”) where Circles are sent to when used for minting. Any redeem logic in this case could be outsourced to the treasury contract. The simplest form would be to use a Safe (“Shared Wallet”) that would allow access to those Circles. More complex forms could be contracts that only allow access to those tokens by burning group tokens.