implement negative citations
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 33s Details

This commit is contained in:
Ladd Hoffman 2024-04-10 17:31:55 -05:00
parent 5cffb8f556
commit 842c1d2e81
2 changed files with 63 additions and 11 deletions

View File

@ -2,6 +2,7 @@
pragma solidity ^0.8.24;
import "./Reputation.sol";
import "hardhat/console.sol";
struct Citation {
int weightPercent;
@ -36,16 +37,22 @@ contract Forum is Reputation {
for (uint i = 0; i < citations.length; i++) {
post.citations.push(citations[i]);
}
int totalCitationWeightAbs;
int totalCitationWeightPos;
int totalCitationWeightNeg;
for (uint i = 0; i < post.citations.length; i++) {
int weight = post.citations[i].weightPercent;
require(weight >= -100, "Each citation weight must be >= -100");
require(weight <= 100, "Each citation weight must be <= 100");
totalCitationWeightAbs += weight > 0 ? weight : -weight;
if (weight > 0) totalCitationWeightPos += weight;
else totalCitationWeightNeg += weight;
}
require(
totalCitationWeightAbs <= 100,
"Sum of absolute value of citations must be <= 100"
totalCitationWeightPos <= 100,
"Sum of positive citations must be <= 100"
);
require(
totalCitationWeightNeg >= -100,
"Sum of positive citations must be >= -100"
);
emit PostAdded(postIndex);
}
@ -56,13 +63,18 @@ contract Forum is Reputation {
function _propagateValue(uint postIndex, int amount) internal {
Post storage post = posts[postIndex];
int totalOutboundAmount;
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);
}
uint remaining = uint(amount - totalOutboundAmount);
_update(address(this), post.author, remaining);
int remaining = amount - totalOutboundAmount;
if (remaining > 0) {
_update(address(this), post.author, uint(remaining));
} else {
_update(post.author, address(this), uint(-remaining));
}
}
}

View File

@ -7,14 +7,17 @@ const { ethers } = require('hardhat');
describe('Forum', () => {
async function deploy() {
const [account1, account2] = await ethers.getSigners();
const [account1, account2, account3] = await ethers.getSigners();
const DAO = await ethers.getContractFactory('DAO');
const dao = await DAO.deploy();
return { dao, account1, account2 };
return {
dao, account1, account2, account3,
};
}
let dao;
let account1;
let account2;
let account3;
const POOL_DURATION = 3600; // 1 hour
const POOL_FEE = 100;
const emptyCallbackData = ethers.AbiCoder.defaultAbiCoder().encode([], []);
@ -38,7 +41,9 @@ describe('Forum', () => {
describe('Post', () => {
beforeEach(async () => {
({ dao, account1, account2 } = await loadFixture(deploy));
({
dao, account1, account2, account3,
} = await loadFixture(deploy));
});
it('should be able to add a post', async () => {
@ -59,15 +64,50 @@ describe('Forum', () => {
expect(post.contentId).to.equal(contentId);
});
it('should propagate reputation to citations', async () => {
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, targetPostIndex: 0 }]);
await initiateValidationPool({ postIndex: 1 });
const pool = await dao.validationPools(0);
expect(pool.postIndex).to.equal(1);
await dao.evaluateOutcome(0);
expect(await dao.balanceOf(account2)).to.equal(50);
expect(await dao.balanceOf(account1)).to.equal(50);
expect(await dao.balanceOf(account2)).to.equal(50);
});
it('should be able to leach reputation via citations', 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: -50, targetPostIndex: 0 }]);
await initiateValidationPool({ postIndex: 1 });
const pool = await dao.validationPools(1);
expect(pool.postIndex).to.equal(1);
await time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(1);
expect(await dao.balanceOf(account1)).to.equal(50);
expect(await dao.balanceOf(account2)).to.equal(150);
});
it('should be able to redistribute power via citations', 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', []);
expect(await dao.balanceOf(account2)).to.equal(0);
await dao.addPost(account3, 'third-content-id', [
{ weightPercent: -100, targetPostIndex: 0 },
{ weightPercent: 100, targetPostIndex: 1 },
]);
await initiateValidationPool({ postIndex: 2 });
const pool = await dao.validationPools(1);
expect(pool.postIndex).to.equal(2);
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(100);
});
});
});