Limit effects of negative citations
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 40s
Details
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 40s
Details
This commit is contained in:
parent
1a4c5c338d
commit
a7f3e5f2e4
|
@ -21,9 +21,12 @@ struct Post {
|
|||
contract Forum is Reputation {
|
||||
mapping(uint => Post) public posts;
|
||||
uint public postCount;
|
||||
mapping(uint => mapping(uint => int)) _edgeBalances;
|
||||
|
||||
event PostAdded(uint postIndex);
|
||||
|
||||
// TODO: Add forum parameters
|
||||
|
||||
function addPost(
|
||||
address author,
|
||||
string calldata contentId,
|
||||
|
@ -59,25 +62,89 @@ contract Forum is Reputation {
|
|||
}
|
||||
|
||||
function _onValidatePost(uint postIndex, uint amount) internal {
|
||||
_propagateValue(postIndex, int(amount));
|
||||
_propagateReputation(postIndex, int(amount), false, 0);
|
||||
}
|
||||
|
||||
function _propagateValue(uint postIndex, int amount) internal {
|
||||
Post storage post = posts[postIndex];
|
||||
function _handleCitation(
|
||||
uint postIndex,
|
||||
Citation memory citation,
|
||||
int amount,
|
||||
bool initialNegative,
|
||||
uint depth
|
||||
) internal returns (int outboundAmount) {
|
||||
outboundAmount = (amount * citation.weightPercent) / 100;
|
||||
int balanceToOutbound = _edgeBalances[postIndex][
|
||||
citation.targetPostIndex
|
||||
];
|
||||
if (initialNegative) {
|
||||
if (outboundAmount < 0) {
|
||||
outboundAmount = outboundAmount > -balanceToOutbound
|
||||
? outboundAmount
|
||||
: -balanceToOutbound;
|
||||
} else {
|
||||
outboundAmount = outboundAmount < -balanceToOutbound
|
||||
? outboundAmount
|
||||
: -balanceToOutbound;
|
||||
}
|
||||
}
|
||||
int refund = _propagateReputation(
|
||||
citation.targetPostIndex,
|
||||
outboundAmount,
|
||||
initialNegative || (depth == 0 && citation.weightPercent < 0),
|
||||
depth + 1
|
||||
);
|
||||
outboundAmount -= refund;
|
||||
_edgeBalances[postIndex][citation.targetPostIndex] += outboundAmount;
|
||||
}
|
||||
|
||||
function _propagateReputation(
|
||||
uint postIndex,
|
||||
int amount,
|
||||
bool initialNegative,
|
||||
uint depth
|
||||
) internal returns (int refundToInbound) {
|
||||
Post storage post = posts[postIndex];
|
||||
int totalOutboundAmount;
|
||||
// Propagate negative citations first
|
||||
for (uint i = 0; i < post.citations.length; i++) {
|
||||
int share = (amount * post.citations[i].weightPercent) / 100;
|
||||
totalOutboundAmount += share;
|
||||
_propagateValue(post.citations[i].targetPostIndex, share);
|
||||
if (post.citations[i].weightPercent < 0) {
|
||||
int outboundAmount = _handleCitation(
|
||||
postIndex,
|
||||
post.citations[i],
|
||||
amount,
|
||||
initialNegative,
|
||||
depth
|
||||
);
|
||||
totalOutboundAmount += outboundAmount;
|
||||
}
|
||||
}
|
||||
// Now propagate positive citations
|
||||
for (uint i = 0; i < post.citations.length; i++) {
|
||||
if (post.citations[i].weightPercent > 0) {
|
||||
int outboundAmount = _handleCitation(
|
||||
postIndex,
|
||||
post.citations[i],
|
||||
amount,
|
||||
initialNegative,
|
||||
depth
|
||||
);
|
||||
totalOutboundAmount += outboundAmount;
|
||||
}
|
||||
}
|
||||
int remaining = amount - totalOutboundAmount;
|
||||
if (remaining > 0) {
|
||||
_update(address(this), post.author, uint(remaining));
|
||||
post.reputation += uint(remaining);
|
||||
} else {
|
||||
_update(post.author, address(this), uint(-remaining));
|
||||
post.reputation -= uint(-remaining);
|
||||
// Prevent reputation from being reduced below zero
|
||||
if (int(post.reputation) + remaining >= 0) {
|
||||
_update(post.author, address(this), uint(-remaining));
|
||||
post.reputation -= uint(-remaining);
|
||||
} else {
|
||||
refundToInbound = int(post.reputation) + remaining;
|
||||
_update(post.author, address(this), post.reputation);
|
||||
post.reputation = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,8 +56,6 @@ contract ValidationPools is Reputation, Forum {
|
|||
bool quorumMet
|
||||
);
|
||||
|
||||
// TODO: Add forum parameters
|
||||
|
||||
/// Internal function to register a stake for/against a validation pool
|
||||
function _stakeOnValidationPool(
|
||||
ValidationPool storage pool,
|
||||
|
@ -98,7 +96,6 @@ contract ValidationPools is Reputation, Forum {
|
|||
}
|
||||
|
||||
/// Accept fee to initiate a validation pool
|
||||
/// TODO: Handle multiple authors
|
||||
function initiateValidationPool(
|
||||
uint postIndex,
|
||||
uint duration,
|
||||
|
@ -140,10 +137,6 @@ contract ValidationPools is Reputation, Forum {
|
|||
// TODO: Make minting ratio an adjustable parameter
|
||||
_mint(address(this), msg.value);
|
||||
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);
|
||||
emit ValidationPoolInitiated(poolIndex);
|
||||
}
|
||||
|
||||
|
@ -176,7 +169,7 @@ contract ValidationPools is Reputation, Forum {
|
|||
pool.params.quorum[1] * (stakedFor + stakedAgainst) <=
|
||||
totalSupply() * pool.params.quorum[0]
|
||||
) {
|
||||
// Refund fee
|
||||
// TODO: Refund fee
|
||||
// TODO: this could be made available for the sender to withdraw
|
||||
// payable(pool.sender).transfer(pool.fee);
|
||||
pool.resolved = true;
|
||||
|
@ -230,7 +223,9 @@ 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
|
||||
// If vote passes, reward the author as though they had staked the winning portion of the VP initial stake
|
||||
// Here we assume a stakeForAuthor ratio of 0.5
|
||||
// TODO: Make stakeForAuthor an adjustable parameter
|
||||
totalRewards += pool.minted / 2;
|
||||
uint reward = ((((totalRewards * pool.minted) / 2) /
|
||||
amountFromWinners) * pool.params.bindingPercent) / 100;
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Forum', () => {
|
|||
} = {}) => dao.initiateValidationPool(
|
||||
postIndex ?? 0,
|
||||
duration ?? POOL_DURATION,
|
||||
quorum ?? [1, 3],
|
||||
quorum ?? [1, 10],
|
||||
winRatio ?? [1, 2],
|
||||
bindingPercent ?? 100,
|
||||
redistributeLosingStakes ?? true,
|
||||
|
@ -114,5 +114,92 @@ describe('Forum', () => {
|
|||
expect(await dao.balanceOf(account1)).to.equal(0);
|
||||
expect(await dao.balanceOf(account2)).to.equal(100);
|
||||
});
|
||||
|
||||
it('should be able to reverse a negative citation with a negative citation', async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postIndex: 0 });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
await dao.addPost(account2, 'second-content-id', [{ weightPercent: -100, targetPostIndex: 0 }]);
|
||||
await initiateValidationPool({ postIndex: 1 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(1);
|
||||
expect(await dao.balanceOf(account1)).to.equal(0);
|
||||
expect(await dao.balanceOf(account2)).to.equal(200);
|
||||
await dao.addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostIndex: 1 }]);
|
||||
await initiateValidationPool({ postIndex: 2 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
expect(await dao.balanceOf(account2)).to.equal(0);
|
||||
expect(await dao.balanceOf(account3)).to.equal(200);
|
||||
});
|
||||
|
||||
it('forum reputation rewards are shared with validation pool policing rewards', async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postIndex: 0 });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
await dao.addPost(account2, 'second-content-id', []);
|
||||
await initiateValidationPool({ postIndex: 1 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(1);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
expect(await dao.balanceOf(account2)).to.equal(100);
|
||||
await dao.addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostIndex: 1 }]);
|
||||
await initiateValidationPool({ postIndex: 2 });
|
||||
await dao.stakeOnValidationPool(2, 100, true);
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
expect(await dao.balanceOf(account1)).to.equal(133);
|
||||
expect(await dao.balanceOf(account2)).to.equal(34);
|
||||
expect(await dao.balanceOf(account3)).to.equal(133);
|
||||
});
|
||||
|
||||
it('should limit effects of negative references on prior positive references', async () => {
|
||||
console.log('First post');
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postIndex: 0 });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
console.log('Second post');
|
||||
await dao.addPost(account2, 'second-content-id', [{ weightPercent: 50, targetPostIndex: 0 }]);
|
||||
await initiateValidationPool({ postIndex: 1 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(1);
|
||||
expect(await dao.balanceOf(account1)).to.equal(150);
|
||||
expect(await dao.balanceOf(account2)).to.equal(50);
|
||||
console.log('Third post');
|
||||
await dao.addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostIndex: 1 }]);
|
||||
await initiateValidationPool({ postIndex: 2, fee: 200 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
expect(await dao.balanceOf(account2)).to.equal(0);
|
||||
expect(await dao.balanceOf(account3)).to.equal(300);
|
||||
});
|
||||
|
||||
it('should limit effects of negative references', async () => {
|
||||
console.log('First post');
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postIndex: 0 });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
console.log('Second post');
|
||||
await dao.addPost(account2, 'second-content-id', [{ weightPercent: -100, targetPostIndex: 0 }]);
|
||||
await initiateValidationPool({ postIndex: 1 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(1);
|
||||
expect(await dao.balanceOf(account1)).to.equal(0);
|
||||
expect(await dao.balanceOf(account2)).to.equal(200);
|
||||
console.log('Third post');
|
||||
await dao.addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostIndex: 1 }]);
|
||||
await initiateValidationPool({ postIndex: 2, fee: 200 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
expect(await dao.balanceOf(account2)).to.equal(0);
|
||||
expect(await dao.balanceOf(account3)).to.equal(300);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue