clarify logic in evaluateOutcome
This commit is contained in:
parent
77cd551602
commit
989bc9846e
|
@ -9,9 +9,8 @@ import "hardhat/console.sol";
|
|||
struct ValidationPoolStake {
|
||||
uint id;
|
||||
bool inFavor;
|
||||
uint256 amount;
|
||||
uint amount;
|
||||
address sender;
|
||||
bool fromMint;
|
||||
}
|
||||
|
||||
struct ValidationPoolParams {
|
||||
|
@ -30,7 +29,7 @@ struct ValidationPool {
|
|||
mapping(uint => ValidationPoolStake) stakes;
|
||||
uint stakeCount;
|
||||
ValidationPoolParams params;
|
||||
uint256 fee;
|
||||
uint fee;
|
||||
uint endTime;
|
||||
bool resolved;
|
||||
bool outcome;
|
||||
|
@ -64,18 +63,16 @@ contract ValidationPools is Reputation, Forum {
|
|||
ValidationPool storage pool,
|
||||
address sender,
|
||||
uint256 amount,
|
||||
bool inFavor,
|
||||
bool fromMint
|
||||
bool inFavor
|
||||
) internal {
|
||||
require(block.timestamp <= pool.endTime, "Pool end time has passed");
|
||||
//_update(sender, address(this), amount);
|
||||
// We don't call _update here; We defer that until evaluateOutcome.
|
||||
uint stakeIndex = pool.stakeCount++;
|
||||
ValidationPoolStake storage s = pool.stakes[stakeIndex];
|
||||
s.sender = sender;
|
||||
s.inFavor = inFavor;
|
||||
s.amount = amount;
|
||||
s.id = stakeIndex;
|
||||
s.fromMint = fromMint;
|
||||
}
|
||||
|
||||
/// Accept reputation stakes toward a validation pool
|
||||
|
@ -85,7 +82,7 @@ contract ValidationPools is Reputation, Forum {
|
|||
bool inFavor
|
||||
) public {
|
||||
ValidationPool storage pool = validationPools[poolIndex];
|
||||
_stakeOnValidationPool(pool, msg.sender, amount, inFavor, false);
|
||||
_stakeOnValidationPool(pool, msg.sender, amount, inFavor);
|
||||
}
|
||||
|
||||
/// Accept reputation stakes toward a validation pool
|
||||
|
@ -97,7 +94,7 @@ contract ValidationPools is Reputation, Forum {
|
|||
) public {
|
||||
ValidationPool storage pool = validationPools[poolIndex];
|
||||
_spendAllowance(owner, msg.sender, amount);
|
||||
_stakeOnValidationPool(pool, owner, amount, inFavor, false);
|
||||
_stakeOnValidationPool(pool, owner, amount, inFavor);
|
||||
}
|
||||
|
||||
/// Accept fee to initiate a validation pool
|
||||
|
@ -145,8 +142,8 @@ contract ValidationPools is Reputation, Forum {
|
|||
pool.minted = msg.value;
|
||||
// Here we assume a stakeForAuthor ratio of 0.5
|
||||
// TODO: Make stakeForAuthor an adjustable parameter
|
||||
_stakeOnValidationPool(pool, post.author, msg.value / 2, true, true);
|
||||
_stakeOnValidationPool(pool, post.author, msg.value / 2, false, true);
|
||||
// _stakeOnValidationPool(pool, post.author, msg.value / 2, true, true);
|
||||
// _stakeOnValidationPool(pool, post.author, msg.value / 2, false, true);
|
||||
emit ValidationPoolInitiated(poolIndex);
|
||||
}
|
||||
|
||||
|
@ -155,8 +152,8 @@ contract ValidationPools is Reputation, Forum {
|
|||
ValidationPool storage pool = validationPools[poolIndex];
|
||||
Post storage post = posts[pool.postIndex];
|
||||
require(pool.resolved == false, "Pool is already resolved");
|
||||
uint256 stakedFor;
|
||||
uint256 stakedAgainst;
|
||||
uint stakedFor;
|
||||
uint stakedAgainst;
|
||||
ValidationPoolStake storage s;
|
||||
for (uint i = 0; i < pool.stakeCount; i++) {
|
||||
s = pool.stakes[i];
|
||||
|
@ -166,6 +163,8 @@ contract ValidationPools is Reputation, Forum {
|
|||
stakedAgainst += s.amount;
|
||||
}
|
||||
}
|
||||
stakedFor += pool.minted / 2;
|
||||
stakedAgainst += pool.minted / 2;
|
||||
// Special case for early evaluation if dao.totalSupply has been staked
|
||||
require(
|
||||
block.timestamp > pool.endTime ||
|
||||
|
@ -195,13 +194,6 @@ contract ValidationPools is Reputation, Forum {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
// We are holding the REP minted on behalf of the author.
|
||||
// We already registered their stakes. Now transfer the REP to the author,
|
||||
// so that the stakes can be fulfilled.
|
||||
_update(address(this), post.author, pool.minted);
|
||||
// TODO: Transfer REP to the forum instead of to the author directly
|
||||
|
||||
// A tie is resolved in favor of the validation pool.
|
||||
// This is especially important so that the DAO's first pool can pass,
|
||||
// when no reputation has yet been minted.
|
||||
|
@ -216,24 +208,20 @@ contract ValidationPools is Reputation, Forum {
|
|||
pool.resolved = true;
|
||||
pool.outcome = votePasses;
|
||||
emit ValidationPoolResolved(poolIndex, votePasses, true);
|
||||
|
||||
// Value of losing stakes should be distributed among winners, in proportion to their stakes
|
||||
uint256 amountFromWinners = votePasses ? stakedFor : stakedAgainst;
|
||||
uint256 amountFromLosers = votePasses ? stakedAgainst : stakedFor;
|
||||
// Only bindingPercent % should be redistributed
|
||||
// Stake senders should get (100-bindingPercent) % back
|
||||
// We have allowances for each stake. Time to collect from the losing stakes.
|
||||
uint amountFromWinners = votePasses ? stakedFor : stakedAgainst;
|
||||
uint totalRewards;
|
||||
uint totalAllocated;
|
||||
for (uint i = 0; i < pool.stakeCount; i++) {
|
||||
s = pool.stakes[i];
|
||||
uint bindingPercent = s.fromMint ? 100 : pool.params.bindingPercent;
|
||||
bool redistributeLosingStakes = s.fromMint ||
|
||||
pool.params.redistributeLosingStakes;
|
||||
if (votePasses != s.inFavor) {
|
||||
// Losing stake
|
||||
// If this stake is from the minted fee, don't burn it
|
||||
uint amount = (s.amount * bindingPercent) / 100;
|
||||
if (redistributeLosingStakes) {
|
||||
uint amount = (s.amount * pool.params.bindingPercent) / 100;
|
||||
if (pool.params.redistributeLosingStakes) {
|
||||
_update(s.sender, address(this), amount);
|
||||
totalRewards += amount;
|
||||
} else {
|
||||
|
@ -241,21 +229,35 @@ contract ValidationPools is Reputation, Forum {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (votePasses) {
|
||||
// If vote passes, reward the author as though they had staked the winnin portion of the VP initial stake
|
||||
totalRewards += pool.minted / 2;
|
||||
uint reward = ((((totalRewards * pool.minted) / 2) /
|
||||
amountFromWinners) * pool.params.bindingPercent) / 100;
|
||||
totalAllocated += reward;
|
||||
_update(address(this), post.author, pool.minted / 2 + reward);
|
||||
// TODO: Transfer REP to the forum instead of to the author directly
|
||||
} else {
|
||||
// If vote does not pass, divide the losing stake among the winners
|
||||
totalRewards += pool.minted;
|
||||
}
|
||||
// Include the losign portion of the VP initial stake
|
||||
// Issue rewards to the winners
|
||||
for (uint i = 0; i < pool.stakeCount; i++) {
|
||||
s = pool.stakes[i];
|
||||
uint bindingPercent = s.fromMint ? 100 : pool.params.bindingPercent;
|
||||
bool redistributeLosingStakes = s.fromMint ||
|
||||
pool.params.redistributeLosingStakes;
|
||||
if (redistributeLosingStakes && votePasses == s.inFavor) {
|
||||
if (
|
||||
pool.params.redistributeLosingStakes && votePasses == s.inFavor
|
||||
) {
|
||||
// Winning stake
|
||||
// If this stake is from the minted fee, always redistribute it to the winners
|
||||
uint reward = (((amountFromLosers * s.amount) /
|
||||
amountFromWinners) * bindingPercent) / 100;
|
||||
uint reward = (((totalRewards * s.amount) / amountFromWinners) *
|
||||
pool.params.bindingPercent) / 100;
|
||||
totalAllocated += reward;
|
||||
_update(address(this), s.sender, reward);
|
||||
}
|
||||
}
|
||||
|
||||
// Due to rounding, some reward may be left over. Let's give it to the author.
|
||||
uint remainder = totalRewards - totalAllocated;
|
||||
if (remainder > 0) {
|
||||
|
@ -265,7 +267,7 @@ contract ValidationPools is Reputation, Forum {
|
|||
// Distribute fee proportionately among all reputation holders
|
||||
for (uint i = 0; i < memberCount; i++) {
|
||||
address member = members[i];
|
||||
uint256 share = (pool.fee * balanceOf(member)) / totalSupply();
|
||||
uint share = (pool.fee * balanceOf(member)) / totalSupply();
|
||||
// TODO: For efficiency this could be modified to hold the funds for recipients to withdraw
|
||||
payable(member).transfer(share);
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ describe('Work1', () => {
|
|||
expect(pool.fee).to.equal(WORK1_PRICE);
|
||||
expect(pool.sender).to.equal(work1.target);
|
||||
expect(pool.postIndex).to.equal(1);
|
||||
expect(pool.stakeCount).to.equal(3);
|
||||
expect(pool.stakeCount).to.equal(1);
|
||||
await time.increase(86401);
|
||||
await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(1, true, true);
|
||||
expect(await dao.balanceOf(account1)).to.equal(200);
|
||||
|
|
Loading…
Reference in New Issue