Hi community,
We know that ErgoMixer is already making some small profits in a decentralized manner. The aim of this topic is to introduce a raw idea about having a generalized form of running a business on top of ERGO.
As I said, this is certainly a raw idea and I’m unaware if there is already some well-defined approach for this.
Let’s suppose a business is going to have N
shares and hence M <= N
shareholders. The business is making some profits (just like ErgoMixer), the aim is to have an approach to distribute this profit among shareholders in a decentralized manner.
TLDR;
The business will issue a token with the quantity of N
representing shares.
Also, we need a data input in which it is specified that who are the current shareholders, the proportion of profit distribution, and possibly some other parameters specifying fee params! When having such data input, the business’s contract that is in charge of getting fees from its users can use that data input and enforce the proper profit distribution.
Data input contract
The contract is minimal to just show the idea. It certainly also needs some other logic.
{
val curLocked = SELF.R4[Coll[Coll[Byte]]].get // ids of boxes locking shares
val selfCp = OUTPUTS(0)
val nextLocked = selfCp.R5[Coll[Coll[Byte]]].get
val lockLogic = { // one wishes to lock his shares to receive his profit proportionately
val lockingBox = OUTPUTS(1)
val nextLockedLogic = nextLocked.size == curLocked.size + 1 && nextLocked.slice(0, nextLocked.size - 1) == curLocked &&
nextLocked(nextLocked.size - 1) == lockingBox.id // box id of the locking box must be added and others untouched
INPUTS.size == 2 && INPUTS(0).id == SELF.id && blake2b256(INPUTS(1).propositionBytes) != lockHash &&
lockingBox.tokens(0)._1 == businessTokenId && blake2b256(lockingBox.propositionBytes) == lockHash &&
lockingBox.R5[Coll[Byte]].get == blake2b256(SELF.propositionBytes) && nextLockedLogic
}
val unlockLogic = { // one wishes to unlock his shares for any reason, for example to sell them
val nextLockedLogic = nextLocked.size == curLocked.size - 1 &&
nextLocked == curLocked.filter({(id: Coll[Byte]) => id != INPUTS(1).id}) // box id must be removed
INPUTS.size == 2 && INPUTS(0).id == SELF.id && blake2b256(INPUTS(1).propositionBytes) == lockHash && nextLockedLogic
}
sigmaProp(lockLogic || unlockLogic) // needs other logic of course like selfCp must have the same value, tokens, etc.
}
The idea is for the shareholders to lock their tokens (shares) to receive profit. We will see the locking contract soon but when they do so, id of the box that locks their tokens is added to the data input. So now the contract in charge of getting fees from users can use this data input and enforce the usage of all locking boxes as its other data inputs and distribute the profit proportionately!
As it is obvious in the contract, there is also an unlocking logic that lets shareholders to unlock their tokens for any reason, probably to sell them!
Locking contract
{
val sharesOwner = SELF.R4[GroupElement].get
val dataInputHash = SELF.R5[Coll[Byte]].get
proveDlog(sharesOwner) && sigmaProp(blake2b256(INPUTS(0).propositionBytes) == dataInputHash)
}
The box that is locking shares will have PK of its owner in R4 to specify who can spend it and also where the profit must go to. Also in R5, the hash of the data input contract is placed so that the only way to spend the box is to include the data input as the first input, hence enforcing the removal of box id from the data input box. Also, of course, the amount of shares is identifiable with the token quantity in the assets of the box.
So in summary with these two contracts, there is an approach to identify the shareholders and distribute the profit to them. Also, they have the chance to unlock their shares and sell/auction them without causing any trouble for the business and other shareholders.
Some other things are needed, for example, the data input itself must contain an NFT to be distinguishable from fake ones!