add contract support for multi-authorship
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 40s Details

This commit is contained in:
Ladd Hoffman 2024-04-19 14:28:26 -05:00
parent db43bd95d8
commit 0eee2ef7ae
11 changed files with 247 additions and 80 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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}(

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
});
});
});
});

View File

@ -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);

View File

@ -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 () => {

View File

@ -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);

View File

@ -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);

View File

@ -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,
});