add post
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 29s Details

This commit is contained in:
Ladd Hoffman 2024-03-12 14:10:06 -05:00
parent d8e4d4fd6a
commit 83f8474905
4 changed files with 59 additions and 24 deletions

View File

@ -6,6 +6,11 @@ import "./IAcceptAvailability.sol";
import "hardhat/console.sol";
struct Post {
address sender;
address author;
}
struct Stake {
bool inFavor;
uint256 amount;
@ -13,9 +18,9 @@ struct Stake {
}
struct ValidationPool {
Post post;
mapping(uint => Stake) stakes;
uint stakeCount;
address author;
uint256 fee;
uint256 initialStakedFor;
uint256 initialStakedAgainst;
@ -39,6 +44,8 @@ contract DAO is ERC20("Reputation", "REP") {
mapping(address => bool) public isMember;
mapping(uint => ValidationPool) public validationPools;
uint public validationPoolCount;
mapping(uint => Post) public posts;
uint public postCount;
// ufixed8x1 constant mintingRatio = 1;
// ufixed8x1 constant quorum = 0;
@ -50,18 +57,24 @@ contract DAO is ERC20("Reputation", "REP") {
event ValidationPoolInitiated(uint poolIndex);
event ValidationPoolResolved(uint poolIndex, bool votePasses);
function addPost(address author) public returns (uint postIndex) {
postIndex = postCount++;
Post storage post = posts[postIndex];
post.author = author;
post.sender = msg.sender;
}
/// Accept fee to initiate a validation pool
/// TODO: Rather than accept author as a parameter, accept a reference to a forum post
/// TODO: Handle multiple authors
/// TODO: Constrain duration to allowable range
function initiateValidationPool(
address author,
uint postIndex,
uint duration
) public payable returns (uint poolIndex) {
require(msg.value > 0, "Fee is required to initiate validation pool");
poolIndex = validationPoolCount++;
ValidationPool storage pool = validationPools[poolIndex];
pool.author = author;
pool.post = posts[postIndex];
pool.fee = msg.value;
pool.duration = duration;
pool.endTime = block.timestamp + duration;
@ -71,10 +84,10 @@ contract DAO is ERC20("Reputation", "REP") {
// Implementing this with adjustable parameters will require more advanced fixed point math.
// TODO: Make minting ratio an adjustable parameter
// TODO: Make stakeForAuthor an adjustable parameter
_mint(author, msg.value);
_mint(pool.post.author, msg.value);
// TODO: We need a way to exclude this pending reputation from the total supply when computing fee distribution
_stake(pool, author, msg.value / 2, true);
_stake(pool, author, msg.value / 2, false);
_stake(pool, pool.post.author, msg.value / 2, true);
_stake(pool, pool.post.author, msg.value / 2, false);
emit ValidationPoolInitiated(poolIndex);
}
@ -124,9 +137,9 @@ contract DAO is ERC20("Reputation", "REP") {
// This is especially important so that the DAO's first pool can pass,
// when no reputation has yet been minted.
votePasses = stakedFor >= stakedAgainst;
if (votePasses && !isMember[pool.author]) {
members[memberCount++] = pool.author;
isMember[pool.author] = true;
if (votePasses && !isMember[pool.post.author]) {
members[memberCount++] = pool.post.author;
isMember[pool.post.author] = true;
}
pool.resolved = true;
emit ValidationPoolResolved(poolIndex, votePasses);
@ -146,7 +159,7 @@ contract DAO is ERC20("Reputation", "REP") {
// Due to rounding, there may be some reward left over. Include this as a reward to the author.
uint256 remainder = amountFromLosers - totalRewards;
if (remainder > 0) {
_transfer(address(this), pool.author, remainder);
_transfer(address(this), pool.post.author, remainder);
}
// Distribute fee proportionatly among all reputation holders
for (uint i = 0; i < memberCount; i++) {

View File

@ -149,9 +149,11 @@ contract Work1 is IAcceptAvailability {
AvailabilityStake storage stake = stakes[request.stakeIndex];
request.status = WorkStatus.ApprovalSubmitted;
request.approval = approval;
// Make work evidence post
uint postIndex = dao.addPost(stake.worker);
// Initiate validation pool
request.poolIndex = dao.initiateValidationPool{value: request.fee}(
stake.worker,
postIndex,
POOL_DURATION
);
}

View File

@ -6,16 +6,10 @@ const { expect } = require('chai');
const { ethers } = require('hardhat');
describe('DAO', () => {
// We define a fixture to reuse the same setup in every test.
// We use loadFixture to run this setup once, snapshot that state,
// and reset Hardhat Network to that snapshot in every test.
async function deploy() {
// Contracts are deployed using the first signer/account by default
const [account1, account2] = await ethers.getSigners();
const DAO = await ethers.getContractFactory('DAO');
const dao = await DAO.deploy();
return { dao, account1, account2 };
}
@ -25,6 +19,24 @@ describe('DAO', () => {
expect(await dao.totalSupply()).to.equal(0);
});
describe('Post', () => {
it('should be able to add a post', async () => {
const { dao, account1 } = await loadFixture(deploy);
await dao.addPost(account1);
const post = await dao.posts(0);
expect(post.author).to.equal(account1);
expect(post.sender).to.equal(account1);
});
it('should be able to add a post on behalf of another account', async () => {
const { dao, account1, account2 } = await loadFixture(deploy);
await dao.addPost(account2);
const post = await dao.posts(0);
expect(post.author).to.equal(account2);
expect(post.sender).to.equal(account1);
});
});
describe('Validation Pool', () => {
let dao;
let account1;
@ -35,7 +47,8 @@ describe('DAO', () => {
const setup = await loadFixture(deploy);
dao = setup.dao;
account1 = setup.account1;
const init = () => dao.initiateValidationPool(account1, POOL_DURATION, { value: POOL_FEE });
await dao.addPost(account1);
const init = () => dao.initiateValidationPool(0, POOL_DURATION, { value: POOL_FEE });
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(0);
expect(await dao.validationPoolCount()).to.equal(1);
expect(await dao.memberCount()).to.equal(0);
@ -46,12 +59,12 @@ describe('DAO', () => {
describe('Initiate', () => {
it('should not be able to initiate a validation pool without a fee', async () => {
const setup = await loadFixture(deploy);
const init = () => setup.dao.initiateValidationPool(setup.account1, POOL_DURATION);
const init = () => setup.dao.initiateValidationPool(0, POOL_DURATION);
await expect(init()).to.be.revertedWith('Fee is required to initiate validation pool');
});
it('should be able to initiate a second validation pool', async () => {
const init = () => dao.initiateValidationPool(account1, POOL_DURATION, { value: POOL_FEE });
const init = () => dao.initiateValidationPool(0, POOL_DURATION, { value: POOL_FEE });
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
expect(await dao.validationPoolCount()).to.equal(2);
});
@ -82,7 +95,7 @@ describe('DAO', () => {
});
it('should be able to evaluate outcome of second validation pool', async () => {
const init = () => dao.initiateValidationPool(account1, POOL_DURATION, { value: POOL_FEE });
const init = () => dao.initiateValidationPool(0, POOL_DURATION, { value: POOL_FEE });
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
expect(await dao.validationPoolCount()).to.equal(2);
time.increase(POOL_DURATION + 1);
@ -99,7 +112,7 @@ describe('DAO', () => {
await dao.evaluateOutcome(0);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(0);
await dao.initiateValidationPool(account1, POOL_DURATION, { value: POOL_FEE });
await dao.initiateValidationPool(0, POOL_DURATION, { value: POOL_FEE });
expect(await dao.balanceOf(dao.target)).to.equal(100);
});

View File

@ -17,7 +17,8 @@ describe('Work1', () => {
const Work1 = await ethers.getContractFactory('Work1');
const work1 = await Work1.deploy(dao.target, WORK1_PRICE);
await dao.initiateValidationPool(account1, 0, { value: 100 });
await dao.addPost(account1);
await dao.initiateValidationPool(0, 0, { value: 100 });
await dao.evaluateOutcome(0);
return {
@ -177,6 +178,12 @@ describe('Work1', () => {
await expect(work1.submitWorkApproval(0, true)).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
});
it('should be able to submit work disapproval', async () => {
await work1.connect(account2).requestWork({ value: WORK1_PRICE });
await work1.submitWorkEvidence(0);
await expect(work1.submitWorkApproval(0, false)).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
});
it('should not be able to submit work approval/disapproval twice', async () => {
await work1.connect(account2).requestWork({ value: WORK1_PRICE });
await work1.submitWorkEvidence(0);