add contract support for multi-authorship
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
db43bd95d8
commit
0eee2ef7ae
|
@ -27,7 +27,9 @@ contract Onboarding is WorkContract, IOnValidate {
|
|||
request.status = WorkStatus.ApprovalSubmitted;
|
||||
request.approval = approval;
|
||||
// Make work evidence post
|
||||
dao.addPost(stake.worker, request.evidenceContentId, request.citations);
|
||||
Author[] memory authors = new Author[](1);
|
||||
authors[0] = Author(100, stake.worker);
|
||||
dao.addPost(authors, request.evidenceContentId, request.citations);
|
||||
emit WorkApprovalSubmitted(requestIndex, approval);
|
||||
// Initiate validation pool
|
||||
uint poolIndex = dao.initiateValidationPool{
|
||||
|
@ -70,8 +72,11 @@ contract Onboarding is WorkContract, IOnValidate {
|
|||
payable(request.customer).transfer(request.fee / 10);
|
||||
return 1;
|
||||
}
|
||||
// Make onboarding post
|
||||
Citation[] memory emptyCitations;
|
||||
dao.addPost(request.customer, request.requestContentId, emptyCitations);
|
||||
Author[] memory authors = new Author[](1);
|
||||
authors[0] = Author(100, request.customer);
|
||||
dao.addPost(authors, request.requestContentId, emptyCitations);
|
||||
dao.initiateValidationPool{value: request.fee / 10}(
|
||||
request.requestContentId,
|
||||
POOL_DURATION,
|
||||
|
|
|
@ -73,7 +73,9 @@ contract Proposals is DAOContract, IOnValidate {
|
|||
// or support post lookup by contentId
|
||||
// TODO: Take citations as a parameter
|
||||
Citation[] memory emptyCitations;
|
||||
dao.addPost(author, contentId, emptyCitations);
|
||||
Author[] memory authors = new Author[](1);
|
||||
authors[0] = Author(100, author);
|
||||
dao.addPost(authors, contentId, emptyCitations);
|
||||
proposalIndex = proposalCount++;
|
||||
Proposal storage proposal = proposals[proposalIndex];
|
||||
proposal.sender = msg.sender;
|
||||
|
|
|
@ -179,7 +179,9 @@ abstract contract WorkContract is
|
|||
request.status = WorkStatus.ApprovalSubmitted;
|
||||
request.approval = approval;
|
||||
// Make work evidence post
|
||||
dao.addPost(stake.worker, request.evidenceContentId, request.citations);
|
||||
Author[] memory authors = new Author[](1);
|
||||
authors[0] = Author(100, stake.worker);
|
||||
dao.addPost(authors, request.evidenceContentId, request.citations);
|
||||
emit WorkApprovalSubmitted(requestIndex, approval);
|
||||
// Initiate validation pool
|
||||
uint poolIndex = dao.initiateValidationPool{value: request.fee}(
|
||||
|
|
|
@ -9,10 +9,15 @@ struct Citation {
|
|||
string targetPostId;
|
||||
}
|
||||
|
||||
struct Author {
|
||||
uint weightPercent;
|
||||
address authorAddress;
|
||||
}
|
||||
|
||||
struct Post {
|
||||
string id;
|
||||
address sender;
|
||||
address author;
|
||||
Author[] authors;
|
||||
Citation[] citations;
|
||||
uint reputation;
|
||||
// TODO: timestamp
|
||||
|
@ -31,20 +36,29 @@ contract Forum is Reputation {
|
|||
uint depthLimit = 3;
|
||||
|
||||
function addPost(
|
||||
address author,
|
||||
Author[] calldata authors,
|
||||
string calldata contentId,
|
||||
Citation[] calldata citations
|
||||
) external {
|
||||
require(authors.length > 0, "Post must include at least one author");
|
||||
postCount++;
|
||||
postIds.push(contentId);
|
||||
Post storage post = posts[contentId];
|
||||
require(
|
||||
post.author == address(0),
|
||||
post.authors.length == 0,
|
||||
"A post with this contentId already exists"
|
||||
);
|
||||
post.author = author;
|
||||
post.sender = msg.sender;
|
||||
post.id = contentId;
|
||||
uint authorTotalWeightPercent;
|
||||
for (uint i = 0; i < authors.length; i++) {
|
||||
authorTotalWeightPercent += authors[i].weightPercent;
|
||||
post.authors.push(authors[i]);
|
||||
}
|
||||
require(
|
||||
authorTotalWeightPercent == 100,
|
||||
"Author weights must sum to 100%"
|
||||
);
|
||||
for (uint i = 0; i < citations.length; i++) {
|
||||
post.citations.push(citations[i]);
|
||||
}
|
||||
|
@ -68,6 +82,13 @@ contract Forum is Reputation {
|
|||
emit PostAdded(contentId);
|
||||
}
|
||||
|
||||
function getPostAuthors(
|
||||
string calldata postId
|
||||
) external view returns (Author[] memory) {
|
||||
Post storage post = posts[postId];
|
||||
return post.authors;
|
||||
}
|
||||
|
||||
function _onValidatePost(string memory postId, uint amount) internal {
|
||||
_propagateReputation(postId, int(amount), false, 0);
|
||||
}
|
||||
|
@ -111,6 +132,39 @@ contract Forum is Reputation {
|
|||
_edgeBalances[postId][citation.targetPostId] += outboundAmount;
|
||||
}
|
||||
|
||||
function _distributeAmongAuthors(
|
||||
Post memory post,
|
||||
int amount
|
||||
) internal returns (int refund) {
|
||||
int allocated;
|
||||
for (uint i = 0; i < post.authors.length; i++) {
|
||||
Author memory author = post.authors[i];
|
||||
int share;
|
||||
if (i < post.authors.length - 1) {
|
||||
share = (amount * int(author.weightPercent)) / 100;
|
||||
allocated += share;
|
||||
} else {
|
||||
// For the last author, allocate the remainder.
|
||||
share = amount - allocated;
|
||||
}
|
||||
if (share > 0) {
|
||||
_update(address(this), author.authorAddress, uint(share));
|
||||
} else if (balanceOf(author.authorAddress) < uint(-share)) {
|
||||
// Author has already lost some REP gained from this post.
|
||||
// That means other DAO members have earned it for policing.
|
||||
// We need to refund the difference here to ensure accurate bookkeeping
|
||||
refund += share + int(balanceOf(author.authorAddress));
|
||||
_update(
|
||||
author.authorAddress,
|
||||
address(this),
|
||||
balanceOf(author.authorAddress)
|
||||
);
|
||||
} else {
|
||||
_update(author.authorAddress, address(this), uint(-share));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _propagateReputation(
|
||||
string memory postId,
|
||||
int amount,
|
||||
|
@ -146,37 +200,21 @@ contract Forum is Reputation {
|
|||
}
|
||||
}
|
||||
if (amount > 0) {
|
||||
_update(address(this), post.author, uint(amount));
|
||||
_distributeAmongAuthors(post, amount);
|
||||
post.reputation += uint(amount);
|
||||
} else {
|
||||
// Prevent reputation from being reduced below zero
|
||||
if (int(post.reputation) + amount >= 0) {
|
||||
if (balanceOf(post.author) >= uint(-amount)) {
|
||||
_update(post.author, address(this), uint(-amount));
|
||||
} else {
|
||||
// Author has already lost some REP gained from this post.
|
||||
// That means other DAO members have earned it for policing.
|
||||
// We need to refund the difference here to ensure accurate bookkeeping
|
||||
refundToInbound = amount + int(balanceOf(post.author));
|
||||
_update(post.author, address(this), balanceOf(post.author));
|
||||
}
|
||||
// Reduce the reputation of each author proportionately;
|
||||
// If any author has insufficient reputation, refund the difference.
|
||||
refundToInbound = _distributeAmongAuthors(post, amount);
|
||||
post.reputation -= uint(-amount);
|
||||
} else {
|
||||
// If we applied the full amount, the post's reputation would decrease below zero.
|
||||
refundToInbound = int(post.reputation) + amount;
|
||||
if (balanceOf(post.author) >= post.reputation) {
|
||||
_update(post.author, address(this), post.reputation);
|
||||
} else {
|
||||
// If author has already lost reputation that was gained from this post,
|
||||
// that means other DAO members gained it through policing.
|
||||
// We have to increase the magnitude of the amount we're "refunding", which is expressed as a negative number.
|
||||
// This has the effect of preserving the sum of all members' REP.
|
||||
// However, we still set the post reputation all the way to zero.
|
||||
// So we end up decreasing the sum of all posts' REP.
|
||||
refundToInbound -= int(
|
||||
post.reputation - balanceOf(post.author)
|
||||
);
|
||||
_update(post.author, address(this), balanceOf(post.author));
|
||||
}
|
||||
refundToInbound += _distributeAmongAuthors(
|
||||
post,
|
||||
-int(post.reputation)
|
||||
);
|
||||
post.reputation = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ contract ValidationPools is Reputation, Forum {
|
|||
require(winRatio[0] <= winRatio[1], "Win ratio is greater than one");
|
||||
require(bindingPercent <= 100, "Binding percent must be <= 100");
|
||||
Post storage post = posts[postId];
|
||||
require(post.author != address(0), "Target post not found");
|
||||
require(post.authors.length != 0, "Target post not found");
|
||||
poolIndex = validationPoolCount++;
|
||||
ValidationPool storage pool = validationPools[poolIndex];
|
||||
pool.sender = msg.sender;
|
||||
|
@ -197,9 +197,14 @@ contract ValidationPools is Reputation, Forum {
|
|||
votePasses =
|
||||
stakedFor * pool.params.winRatio[1] >=
|
||||
(stakedFor + stakedAgainst) * pool.params.winRatio[0];
|
||||
if (votePasses && !isMember[post.author]) {
|
||||
members[memberCount++] = post.author;
|
||||
isMember[post.author] = true;
|
||||
if (votePasses) {
|
||||
for (uint i = 0; i < post.authors.length; i++) {
|
||||
address authorAddress = post.authors[i].authorAddress;
|
||||
if (!isMember[authorAddress]) {
|
||||
members[memberCount++] = authorAddress;
|
||||
isMember[authorAddress] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
pool.resolved = true;
|
||||
pool.outcome = votePasses;
|
||||
|
|
|
@ -39,6 +39,11 @@ describe('Forum', () => {
|
|||
{ value: fee ?? POOL_FEE },
|
||||
);
|
||||
|
||||
const addPost = (author, contentId, citations) => dao.addPost([{
|
||||
weightPercent: 100,
|
||||
authorAddress: author,
|
||||
}], contentId, citations);
|
||||
|
||||
describe('Post', () => {
|
||||
beforeEach(async () => {
|
||||
({
|
||||
|
@ -48,25 +53,69 @@ describe('Forum', () => {
|
|||
|
||||
it('should be able to add a post', async () => {
|
||||
const contentId = 'some-id';
|
||||
await expect(dao.addPost(account1, contentId, [])).to.emit(dao, 'PostAdded').withArgs('some-id');
|
||||
await expect(addPost(account1, contentId, [])).to.emit(dao, 'PostAdded').withArgs('some-id');
|
||||
const post = await dao.posts(contentId);
|
||||
expect(post.author).to.equal(account1);
|
||||
expect(post.sender).to.equal(account1);
|
||||
expect(post.id).to.equal(contentId);
|
||||
const postAuthors = await dao.getPostAuthors(contentId);
|
||||
expect(postAuthors).to.have.length(1);
|
||||
expect(postAuthors[0].weightPercent).to.equal(100);
|
||||
expect(postAuthors[0].authorAddress).to.equal(account1);
|
||||
});
|
||||
|
||||
it('should be able to add a post on behalf of another account', async () => {
|
||||
const contentId = 'some-id';
|
||||
await dao.addPost(account2, contentId, []);
|
||||
await addPost(account2, contentId, []);
|
||||
const post = await dao.posts(contentId);
|
||||
expect(post.author).to.equal(account2);
|
||||
expect(post.sender).to.equal(account1);
|
||||
expect(post.id).to.equal(contentId);
|
||||
const postAuthors = await dao.getPostAuthors(contentId);
|
||||
expect(postAuthors).to.have.length(1);
|
||||
expect(postAuthors[0].weightPercent).to.equal(100);
|
||||
expect(postAuthors[0].authorAddress).to.equal(account2);
|
||||
});
|
||||
|
||||
it('should be able to add a post with multiple authors', async () => {
|
||||
const contentId = 'some-id';
|
||||
await expect(dao.addPost([
|
||||
{ weightPercent: 50, authorAddress: account1 },
|
||||
{ weightPercent: 50, authorAddress: account2 },
|
||||
], contentId, [])).to.emit(dao, 'PostAdded').withArgs('some-id');
|
||||
const post = await dao.posts(contentId);
|
||||
expect(post.sender).to.equal(account1);
|
||||
expect(post.id).to.equal(contentId);
|
||||
const postAuthors = await dao.getPostAuthors(contentId);
|
||||
expect(postAuthors).to.have.length(2);
|
||||
expect(postAuthors[0].weightPercent).to.equal(50);
|
||||
expect(postAuthors[0].authorAddress).to.equal(account1);
|
||||
expect(postAuthors[1].weightPercent).to.equal(50);
|
||||
expect(postAuthors[1].authorAddress).to.equal(account2);
|
||||
await initiateValidationPool({ postId: 'some-id' });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(50);
|
||||
expect(await dao.balanceOf(account2)).to.equal(50);
|
||||
});
|
||||
|
||||
it('should not be able to add a post with total author weight < 100%', async () => {
|
||||
const contentId = 'some-id';
|
||||
await expect(dao.addPost([
|
||||
{ weightPercent: 50, authorAddress: account1 },
|
||||
{ weightPercent: 40, authorAddress: account2 },
|
||||
], contentId, [])).to.be.rejectedWith('Author weights must sum to 100%');
|
||||
});
|
||||
|
||||
it('should not be able to add a post with total author weight > 100%', async () => {
|
||||
const contentId = 'some-id';
|
||||
await expect(dao.addPost([
|
||||
{ weightPercent: 50, authorAddress: account1 },
|
||||
{ weightPercent: 60, authorAddress: account2 },
|
||||
], contentId, [])).to.be.rejectedWith('Author weights must sum to 100%');
|
||||
});
|
||||
|
||||
it('should be able to donate reputation via citations', async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await dao.addPost(account2, 'second-content-id', [{ weightPercent: 50, targetPostId: 'content-id' }]);
|
||||
await addPost(account1, 'content-id', []);
|
||||
await addPost(account2, 'second-content-id', [{ weightPercent: 50, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'second-content-id' });
|
||||
const pool = await dao.validationPools(0);
|
||||
expect(pool.postId).to.equal('second-content-id');
|
||||
|
@ -76,13 +125,13 @@ describe('Forum', () => {
|
|||
});
|
||||
|
||||
it('should be able to leach reputation via citations', async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await addPost(account1, 'content-id', []);
|
||||
expect((await dao.posts('content-id')).reputation).to.equal(0);
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
expect((await dao.posts('content-id')).reputation).to.equal(100);
|
||||
await dao.addPost(account2, 'second-content-id', [{ weightPercent: -50, targetPostId: 'content-id' }]);
|
||||
await addPost(account2, 'second-content-id', [{ weightPercent: -50, targetPostId: 'content-id' }]);
|
||||
expect((await dao.posts('second-content-id')).reputation).to.equal(0);
|
||||
await initiateValidationPool({ postId: 'second-content-id' });
|
||||
const pool = await dao.validationPools(1);
|
||||
|
@ -96,13 +145,13 @@ describe('Forum', () => {
|
|||
});
|
||||
|
||||
it('should be able to redistribute power via citations', async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
await dao.addPost(account2, 'second-content-id', []);
|
||||
await addPost(account2, 'second-content-id', []);
|
||||
expect(await dao.balanceOf(account2)).to.equal(0);
|
||||
await dao.addPost(account3, 'third-content-id', [
|
||||
await addPost(account3, 'third-content-id', [
|
||||
{ weightPercent: -100, targetPostId: 'content-id' },
|
||||
{ weightPercent: 100, targetPostId: 'second-content-id' },
|
||||
]);
|
||||
|
@ -117,17 +166,17 @@ describe('Forum', () => {
|
|||
});
|
||||
|
||||
it('should be able to reverse a negative citation with a negative citation', async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
await dao.addPost(account2, 'second-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await addPost(account2, 'second-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'second-content-id' });
|
||||
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, targetPostId: 'second-content-id' }]);
|
||||
await addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'second-content-id' }]);
|
||||
await initiateValidationPool({ postId: 'third-content-id' });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
|
@ -137,17 +186,17 @@ describe('Forum', () => {
|
|||
});
|
||||
|
||||
it('forum reputation rewards are shared with validation pool policing rewards', async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
await dao.addPost(account2, 'second-content-id', []);
|
||||
await addPost(account2, 'second-content-id', []);
|
||||
await initiateValidationPool({ postId: 'second-content-id' });
|
||||
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, targetPostId: 'second-content-id' }]);
|
||||
await addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'second-content-id' }]);
|
||||
await initiateValidationPool({ postId: 'third-content-id' });
|
||||
await dao.stakeOnValidationPool(2, 100, true);
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
|
@ -159,17 +208,17 @@ describe('Forum', () => {
|
|||
|
||||
it('should limit effects of negative references on prior positive references', async () => {
|
||||
console.log('First post');
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
await dao.addPost(account2, 'second-content-id', [{ weightPercent: 50, targetPostId: 'content-id' }]);
|
||||
await addPost(account2, 'second-content-id', [{ weightPercent: 50, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'second-content-id' });
|
||||
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);
|
||||
await dao.addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'second-content-id' }]);
|
||||
await addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'second-content-id' }]);
|
||||
await initiateValidationPool({ postId: 'third-content-id', fee: 200 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
|
@ -179,17 +228,17 @@ describe('Forum', () => {
|
|||
});
|
||||
|
||||
it('should limit effects of negative references on prior negative references', async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
await dao.addPost(account2, 'second-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await addPost(account2, 'second-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'second-content-id' });
|
||||
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, targetPostId: 'second-content-id' }]);
|
||||
await addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'second-content-id' }]);
|
||||
await initiateValidationPool({ postId: 'third-content-id', fee: 200 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
|
@ -199,10 +248,10 @@ describe('Forum', () => {
|
|||
});
|
||||
|
||||
it('should enforce depth limit', async () => {
|
||||
await dao.addPost(account1, 'content-id-1', []);
|
||||
await dao.addPost(account1, 'content-id-2', [{ weightPercent: 100, targetPostId: 'content-id-1' }]);
|
||||
await dao.addPost(account1, 'content-id-3', [{ weightPercent: 100, targetPostId: 'content-id-2' }]);
|
||||
await dao.addPost(account1, 'content-id-4', [{ weightPercent: 100, targetPostId: 'content-id-3' }]);
|
||||
await addPost(account1, 'content-id-1', []);
|
||||
await addPost(account1, 'content-id-2', [{ weightPercent: 100, targetPostId: 'content-id-1' }]);
|
||||
await addPost(account1, 'content-id-3', [{ weightPercent: 100, targetPostId: 'content-id-2' }]);
|
||||
await addPost(account1, 'content-id-4', [{ weightPercent: 100, targetPostId: 'content-id-3' }]);
|
||||
await initiateValidationPool({ postId: 'content-id-4' });
|
||||
await dao.evaluateOutcome(0);
|
||||
const posts = await Promise.all([
|
||||
|
@ -218,7 +267,7 @@ describe('Forum', () => {
|
|||
});
|
||||
|
||||
it('should be able to incinerate reputation', async () => {
|
||||
await dao.addPost(account1, 'content-id-1', [
|
||||
await addPost(account1, 'content-id-1', [
|
||||
{
|
||||
weightPercent: 50,
|
||||
targetPostId: '',
|
||||
|
@ -233,14 +282,14 @@ describe('Forum', () => {
|
|||
|
||||
describe('negative citation of a post, the author having already staked and lost reputation', async () => {
|
||||
beforeEach(async () => {
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await addPost(account1, 'content-id', []);
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
expect(await dao.totalSupply()).to.equal(100);
|
||||
expect((await dao.posts('content-id')).reputation).to.equal(100);
|
||||
|
||||
await dao.addPost(account2, 'second-content-id', []);
|
||||
await addPost(account2, 'second-content-id', []);
|
||||
await initiateValidationPool({ postId: 'second-content-id' });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(1);
|
||||
|
@ -265,7 +314,7 @@ describe('Forum', () => {
|
|||
|
||||
it('author and post rep can be completely destroyed', async () => {
|
||||
// account1's post is later strongly negatively referenced
|
||||
await dao.addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'third-content-id', fee: 200 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(3);
|
||||
|
@ -280,7 +329,7 @@ describe('Forum', () => {
|
|||
|
||||
it('author rep can be destroyed while some post rep remains', async () => {
|
||||
// account1's post is later strongly negatively referenced
|
||||
await dao.addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'third-content-id', fee: 70 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(3);
|
||||
|
@ -295,7 +344,7 @@ describe('Forum', () => {
|
|||
|
||||
it('author rep can be destroyed while some post rep remains (odd amount)', async () => {
|
||||
// account1's post is later strongly negatively referenced
|
||||
await dao.addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await addPost(account3, 'third-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'third-content-id', fee: 75 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(3);
|
||||
|
@ -308,5 +357,59 @@ describe('Forum', () => {
|
|||
expect((await dao.posts('third-content-id')).reputation).to.equal(125);
|
||||
});
|
||||
});
|
||||
|
||||
describe('negative citation of a post with multiple authors', async () => {
|
||||
beforeEach(async () => {
|
||||
await dao.addPost([
|
||||
{ weightPercent: 50, authorAddress: account1 },
|
||||
{ weightPercent: 50, authorAddress: account2 },
|
||||
], 'content-id', []);
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.evaluateOutcome(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(50);
|
||||
expect(await dao.balanceOf(account2)).to.equal(50);
|
||||
expect(await dao.totalSupply()).to.equal(100);
|
||||
expect((await dao.posts('content-id')).reputation).to.equal(100);
|
||||
|
||||
// account1 stakes and loses
|
||||
await initiateValidationPool({ postId: 'content-id' });
|
||||
await dao.stakeOnValidationPool(1, 25, true);
|
||||
await dao.connect(account2).stakeOnValidationPool(1, 60, false);
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(1);
|
||||
expect(await dao.balanceOf(account1)).to.equal(25);
|
||||
expect(await dao.balanceOf(account2)).to.equal(175);
|
||||
expect(await dao.totalSupply()).to.equal(200);
|
||||
expect((await dao.posts('content-id')).reputation).to.equal(100);
|
||||
});
|
||||
|
||||
it('author and post rep can be completely destroyed', async () => {
|
||||
// account1's post is later strongly negatively referenced
|
||||
await addPost(account3, 'second-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'second-content-id', fee: 400 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
expect(await dao.balanceOf(account1)).to.equal(0);
|
||||
expect(await dao.balanceOf(account2)).to.equal(125);
|
||||
expect(await dao.balanceOf(account3)).to.equal(475);
|
||||
expect(await dao.totalSupply()).to.equal(600);
|
||||
expect((await dao.posts('content-id')).reputation).to.equal(0);
|
||||
expect((await dao.posts('second-content-id')).reputation).to.equal(475);
|
||||
});
|
||||
|
||||
it('author rep can be destroyed while some post rep remains', async () => {
|
||||
// account1's post is later strongly negatively referenced
|
||||
await addPost(account3, 'second-content-id', [{ weightPercent: -100, targetPostId: 'content-id' }]);
|
||||
await initiateValidationPool({ postId: 'second-content-id', fee: 70 });
|
||||
await time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(2);
|
||||
expect(await dao.totalSupply()).to.equal(270);
|
||||
expect(await dao.balanceOf(account1)).to.equal(0);
|
||||
expect(await dao.balanceOf(account2)).to.equal(140);
|
||||
expect(await dao.balanceOf(account3)).to.equal(130);
|
||||
expect((await dao.posts('content-id')).reputation).to.equal(30);
|
||||
expect((await dao.posts('second-content-id')).reputation).to.equal(130);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@ describe('Onboarding', () => {
|
|||
const Onboarding = await ethers.getContractFactory('Onboarding');
|
||||
const onboarding = await Onboarding.deploy(dao.target, proposals.target, PRICE);
|
||||
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await dao.addPost([{ weightPercent: 100, authorAddress: account1 }], 'content-id', []);
|
||||
const callbackData = ethers.AbiCoder.defaultAbiCoder().encode([], []);
|
||||
await dao.initiateValidationPool(
|
||||
'content-id',
|
||||
|
@ -71,9 +71,12 @@ describe('Onboarding', () => {
|
|||
.to.emit(dao, 'ValidationPoolInitiated').withArgs(1)
|
||||
.to.emit(onboarding, 'WorkApprovalSubmitted').withArgs(0, true);
|
||||
const post = await dao.posts('evidence-content-id');
|
||||
expect(post.author).to.equal(account1);
|
||||
expect(post.sender).to.equal(onboarding.target);
|
||||
expect(post.id).to.equal('evidence-content-id');
|
||||
const postAuthors = await dao.getPostAuthors('evidence-content-id');
|
||||
expect(postAuthors).to.have.length(1);
|
||||
expect(postAuthors[0].weightPercent).to.equal(100);
|
||||
expect(postAuthors[0].authorAddress).to.equal(account1);
|
||||
const pool = await dao.validationPools(1);
|
||||
expect(pool.postId).to.equal('evidence-content-id');
|
||||
expect(pool.fee).to.equal(PRICE * 0.9);
|
||||
|
|
|
@ -16,8 +16,8 @@ describe('Proposal', () => {
|
|||
const Proposals = await ethers.getContractFactory('Proposals');
|
||||
const proposals = await Proposals.deploy(dao.target);
|
||||
|
||||
await dao.addPost(account1, 'some-content-id', []);
|
||||
await dao.addPost(account2, 'some-other-content-id', []);
|
||||
await dao.addPost([{ weightPercent: 100, authorAddress: account1 }], 'some-content-id', []);
|
||||
await dao.addPost([{ weightPercent: 100, authorAddress: account2 }], 'some-other-content-id', []);
|
||||
const callbackData = ethers.AbiCoder.defaultAbiCoder().encode([], []);
|
||||
await dao.initiateValidationPool(
|
||||
'some-content-id',
|
||||
|
@ -87,7 +87,10 @@ describe('Proposal', () => {
|
|||
});
|
||||
|
||||
it('Can submit a proposal', async () => {
|
||||
// Nothing to do here -- this just tests our beforeEach
|
||||
const postAuthors = await dao.getPostAuthors('proposal-content-id');
|
||||
expect(postAuthors).to.have.length(1);
|
||||
expect(postAuthors[0].weightPercent).to.equal(100);
|
||||
expect(postAuthors[0].authorAddress).to.equal(account1);
|
||||
});
|
||||
|
||||
it('Can attest for a proposal', async () => {
|
||||
|
|
|
@ -38,7 +38,7 @@ describe('Validation Pools', () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
({ dao, account1, account2 } = await loadFixture(deploy));
|
||||
await dao.addPost(account1, 'content-id', []);
|
||||
await dao.addPost([{ weightPercent: 100, authorAddress: account1 }], 'content-id', []);
|
||||
const init = () => initiateValidationPool({ fee: POOL_FEE });
|
||||
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(0);
|
||||
expect(await dao.validationPoolCount()).to.equal(1);
|
||||
|
@ -192,7 +192,7 @@ describe('Validation Pools', () => {
|
|||
beforeEach(async () => {
|
||||
time.increase(POOL_DURATION + 1);
|
||||
await dao.evaluateOutcome(0);
|
||||
await dao.addPost(account2, 'content-id-2', []);
|
||||
await dao.addPost([{ weightPercent: 100, authorAddress: account2 }], 'content-id-2', []);
|
||||
const init = () => initiateValidationPool({ postId: 'content-id-2' });
|
||||
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
|
||||
time.increase(POOL_DURATION + 1);
|
||||
|
|
|
@ -19,7 +19,7 @@ describe('Work1', () => {
|
|||
const Work1 = await ethers.getContractFactory('Work1');
|
||||
const work1 = await Work1.deploy(dao.target, proposals.target, WORK1_PRICE);
|
||||
|
||||
await dao.addPost(account1, 'some-content-id', []);
|
||||
await dao.addPost([{ weightPercent: 100, authorAddress: account1 }], 'some-content-id', []);
|
||||
const callbackData = ethers.AbiCoder.defaultAbiCoder().encode([], []);
|
||||
await dao.initiateValidationPool(
|
||||
'some-content-id',
|
||||
|
@ -212,9 +212,12 @@ describe('Work1', () => {
|
|||
expect(await dao.balanceOf(work1.target)).to.equal(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
const post = await dao.posts('evidence-content-id');
|
||||
expect(post.author).to.equal(account1);
|
||||
expect(post.sender).to.equal(work1.target);
|
||||
expect(post.id).to.equal('evidence-content-id');
|
||||
const postAuthors = await dao.getPostAuthors('evidence-content-id');
|
||||
expect(postAuthors).to.have.length(1);
|
||||
expect(postAuthors[0].weightPercent).to.equal(100);
|
||||
expect(postAuthors[0].authorAddress).to.equal(account1);
|
||||
const pool = await dao.validationPools(1);
|
||||
expect(pool.fee).to.equal(WORK1_PRICE);
|
||||
expect(pool.sender).to.equal(work1.target);
|
||||
|
|
|
@ -83,7 +83,10 @@ class Post {
|
|||
|
||||
// Upload hash to blockchain
|
||||
async publish(DAO, account) {
|
||||
await DAO.methods.addPost(account, this.hash, []).send({
|
||||
await DAO.methods.addPost([{
|
||||
weightPercent: 100,
|
||||
authorAddress: account,
|
||||
}], this.hash, []).send({
|
||||
from: account,
|
||||
gas: 1000000,
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue