started on tests for lightweight bench

This commit is contained in:
Ladd Hoffman 2024-06-29 12:57:07 -05:00
parent da20410f87
commit 3c4a5cbb7a
11 changed files with 491 additions and 38 deletions

View File

@ -28,7 +28,7 @@ if (ENABLE_STAKING === 'false') {
const start = async () => {
dao.on('ValidationPoolInitiated', async (poolIndex) => {
console.log('Validation Pool Initiated, index', poolIndex);
const pool = await dao.validationPools(poolIndex);
const pool = await dao.getValidationPool(poolIndex);
// Read post from database
let post;
try {

View File

@ -4,16 +4,16 @@ pragma solidity ^0.8.24;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "./Reputation.sol";
import "./Bench.sol";
import "./LightweightBench.sol";
import "../GlobalForum.sol";
import "../interfaces/IAcceptAvailability.sol";
import "../interfaces/IOnValidate.sol";
import "hardhat/console.sol";
contract DAO {
Reputation rep;
GlobalForum forum;
Bench bench;
LightweightBench lightweightBench;
mapping(uint => address) public members;
uint public memberCount;
mapping(address => bool) public isMember;
@ -31,16 +31,28 @@ contract DAO {
bool votePasses,
bool quorumMet
);
event LWResultProposed(
uint poolIndex,
uint proposedResultIndex,
string proposedResultHash
);
constructor(Reputation reputation_, Bench bench_, GlobalForum forum_) {
constructor(
Reputation reputation_,
Bench bench_,
LightweightBench lightweightBench_,
GlobalForum forum_
) {
rep = reputation_;
bench = bench_;
lightweightBench = lightweightBench_;
forum = forum_;
rep.registerDAO(this);
bench.registerDAO(this, forum);
lightweightBench.registerDAO(this);
}
function emitPostAdded(string memory id) public {
function emitPostAdded(string calldata id) public {
emit PostAdded(id);
}
@ -60,9 +72,22 @@ contract DAO {
emit LWValidationPoolInitiated(poolIndex);
}
function emitLWResultProposed(
uint poolIndex,
uint proposedResultIndex,
string calldata proposedResultHash
) public {
emit LWResultProposed(
poolIndex,
proposedResultIndex,
proposedResultHash
);
}
function update(address from, address to, uint256 value) public {
require(
msg.sender == address(bench),
msg.sender == address(lightweightBench) ||
msg.sender == address(bench),
"Only DAO core contracts may call update"
);
rep.update(from, to, value);
@ -70,7 +95,8 @@ contract DAO {
function mint(address account, uint256 value) public {
require(
msg.sender == address(bench),
msg.sender == address(lightweightBench) ||
msg.sender == address(bench),
"Only DAO core contracts may call mint"
);
rep.mint(account, value);
@ -78,7 +104,8 @@ contract DAO {
function burn(address account, uint256 value) public {
require(
msg.sender == address(bench),
msg.sender == address(lightweightBench) ||
msg.sender == address(bench),
"Only DAO core contracts may call burn"
);
rep.burn(account, value);
@ -86,7 +113,8 @@ contract DAO {
function registerMember(address account) public {
require(
msg.sender == address(bench),
msg.sender == address(lightweightBench) ||
msg.sender == address(bench),
"Only DAO core contracts may call registerMember"
);
if (!isMember[account]) {
@ -155,7 +183,7 @@ contract DAO {
}
}
function validationPools(
function getValidationPool(
uint poolIndex
)
public
@ -173,7 +201,7 @@ contract DAO {
return bench.validationPools(poolIndex);
}
function validationPoolCount() public view returns (uint) {
function getValidationPoolCount() public view returns (uint) {
return bench.validationPoolCount();
}
@ -210,7 +238,6 @@ contract DAO {
balanceOf(msg.sender) >= amount,
"Insufficient REP balance to cover stake"
);
// TODO: Encumber tokens
bench.stakeOnValidationPool(poolIndex, msg.sender, amount, inFavor);
}
@ -232,6 +259,104 @@ contract DAO {
return bench.evaluateOutcome(poolIndex);
}
function getLWValidationPool(
uint poolIndex
)
public
view
returns (
uint id,
address sender,
uint stakeCount,
LWVPoolParams memory params,
LWVPoolProps memory props,
bool callbackOnValidate,
bytes memory callbackData
)
{
return lightweightBench.validationPools(poolIndex);
}
function getLWValidationPoolCount() public view returns (uint) {
return lightweightBench.validationPoolCount();
}
function initiateLWValidationPool(
string calldata postId,
uint duration,
uint[2] calldata quorum, // [Numerator, Denominator]
uint[2] calldata winRatio, // [Numerator, Denominator]
uint bindingPercent,
bool redistributeLosingStakes,
bool callbackOnValidate,
bytes calldata callbackData
) external payable returns (uint) {
return
lightweightBench.initiateValidationPool{value: msg.value}(
msg.sender,
postId,
duration,
quorum,
winRatio,
bindingPercent,
redistributeLosingStakes,
callbackOnValidate,
callbackData
);
}
function proposeLWResult(
uint poolIndex,
string calldata resultHash,
Transfer[] calldata transfers
) external {
lightweightBench.proposeResult(poolIndex, resultHash, transfers);
}
function stakeOnLWValidationPool(
uint poolIndex,
string calldata resultHash,
uint256 amount,
bool inFavor
) public {
require(
balanceOf(msg.sender) >= amount,
"Insufficient REP balance to cover stake"
);
lightweightBench.stakeOnValidationPool(
poolIndex,
resultHash,
msg.sender,
amount,
inFavor
);
}
/// Accept reputation stakes toward a validation pool
function delegatedStakeOnLWValidationPool(
uint poolIndex,
string calldata resultHash,
address owner,
uint256 amount,
bool inFavor
) public {
if (allowance(owner, msg.sender) < amount) {
amount = allowance(owner, msg.sender);
}
rep.spendAllowance(owner, msg.sender, amount);
lightweightBench.stakeOnValidationPool(
poolIndex,
resultHash,
owner,
amount,
inFavor
);
}
function evaluateLWOutcome(uint poolIndex) public returns (bool) {
return lightweightBench.evaluateOutcome(poolIndex);
}
function onValidate(
address target,
bool votePasses,
@ -241,7 +366,8 @@ contract DAO {
bytes calldata callbackData
) public {
require(
msg.sender == address(bench),
msg.sender == address(lightweightBench) ||
msg.sender == address(bench),
"Only DAO core contracts may call onValidate"
);
IOnValidate(target).onValidate(

View File

@ -20,13 +20,13 @@ struct LWVPoolProps {
bool outcome;
}
contract LightweightBench {
struct Transfer {
address from;
address to;
uint amount;
}
struct Transfer {
address from;
address to;
uint amount;
}
contract LightweightBench {
struct ProposedResult {
Transfer[] transfers;
uint stakedFor;
@ -121,6 +121,10 @@ contract LightweightBench {
string calldata resultHash,
Transfer[] calldata transfers
) external {
require(
transfers.length > 0,
"The proposed result contains no transfers"
);
Pool storage pool = validationPools[poolIndex];
require(
block.timestamp <= pool.props.endTime,
@ -129,14 +133,16 @@ contract LightweightBench {
ProposedResult storage proposedResult = pool.proposedResults[
resultHash
];
pool.proposedResultHashes.push(resultHash);
require(
proposedResult.transfers.length == 0,
"This result hash has already been proposed"
);
uint resultIndex = pool.proposedResultHashes.length;
pool.proposedResultHashes.push(resultHash);
for (uint i = 0; i < transfers.length; i++) {
proposedResult.transfers.push(transfers[i]);
}
dao.emitLWResultProposed(poolIndex, resultIndex, resultHash);
}
/// Register a stake for/against a validation pool

View File

@ -39,7 +39,7 @@ const fetchPost = async (postIndex) => {
const fetchValidationPool = async (poolIndex) => {
const {
id, postIndex, sender, stakeCount, fee, duration, endTime, resolved, outcome,
} = await dao.validationPools(poolIndex);
} = await dao.getValidationPool(poolIndex);
const pool = {
id, postIndex, sender, stakeCount, fee, duration, endTime, resolved, outcome,
};
@ -49,7 +49,7 @@ const fetchValidationPool = async (poolIndex) => {
};
const fetchValidationPools = async () => {
const count = await dao.validationPoolCount();
const count = await dao.getValidationPoolCount();
console.log(`validation pool count: ${count}`);
const promises = [];
validationPools = [];

View File

@ -113,7 +113,7 @@ describe('Forum', () => {
await addPost(account1, 'content-id', []);
await addPost(account2, 'second-content-id', [{ weightPPM: 500000, targetPostId: 'content-id' }]);
await initiateValidationPool({ postId: 'second-content-id' });
const pool = await dao.validationPools(0);
const pool = await dao.getValidationPool(0);
expect(pool.props.postId).to.equal('second-content-id');
await dao.evaluateOutcome(0);
expect(await dao.balanceOf(account1)).to.equal(50);
@ -127,7 +127,7 @@ describe('Forum', () => {
expect(await dao.balanceOf(account1)).to.equal(100);
await addPost(account2, 'second-content-id', [{ weightPPM: -500000, targetPostId: 'content-id' }]);
await initiateValidationPool({ postId: 'second-content-id' });
const pool = await dao.validationPools(1);
const pool = await dao.getValidationPool(1);
expect(pool.props.postId).to.equal('second-content-id');
await time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(1);
@ -147,7 +147,7 @@ describe('Forum', () => {
{ weightPPM: 1000000, targetPostId: 'second-content-id' },
]);
await initiateValidationPool({ postId: 'third-content-id' });
const pool = await dao.validationPools(1);
const pool = await dao.getValidationPool(1);
expect(pool.props.postId).to.equal('third-content-id');
await time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(1);
@ -183,7 +183,7 @@ describe('Forum', () => {
{ weightPPM: 100000, targetPostId: 'nonexistent-content-id' },
]);
await initiateValidationPool({ postId: 'second-content-id' });
const pool = await dao.validationPools(0);
const pool = await dao.getValidationPool(0);
expect(pool.props.postId).to.equal('second-content-id');
await dao.evaluateOutcome(0);
expect(await dao.balanceOf(account1)).to.equal(10);

View File

@ -0,0 +1,318 @@
const {
time,
loadFixture,
} = require('@nomicfoundation/hardhat-toolbox/network-helpers');
const { expect } = require('chai');
const { ethers } = require('hardhat');
const deployDAO = require('./util/deploy-dao');
describe('Lightweight Validation Pools', () => {
async function deploy() {
const [account1, account2] = await ethers.getSigners();
const { dao, forum } = await deployDAO();
return {
dao, forum, account1, account2,
};
}
let dao;
let forum;
let account1;
let account2;
const POOL_DURATION = 3600; // 1 hour
const POOL_FEE = 100;
const emptyCallbackData = ethers.AbiCoder.defaultAbiCoder().encode([], []);
const initiateValidationPool = ({
postId, duration,
quorum, winRatio, bindingPercent,
redistributeLosingStakes, callbackOnValidate,
callbackData, fee,
} = {}) => dao.initiateLWValidationPool(
postId ?? 'content-id',
duration ?? POOL_DURATION,
quorum ?? [1, 3],
winRatio ?? [1, 2],
bindingPercent ?? 100,
redistributeLosingStakes ?? true,
callbackOnValidate ?? false,
callbackData ?? emptyCallbackData,
{ value: fee ?? POOL_FEE },
);
beforeEach(async () => {
({
dao, forum, account1, account2,
} = await loadFixture(deploy));
await forum.addPost([{ weightPPM: 1000000, authorAddress: account1 }], 'content-id', []);
const init = () => initiateValidationPool({ fee: POOL_FEE });
await expect(init()).to.emit(dao, 'LWValidationPoolInitiated').withArgs(0);
expect(await dao.getLWValidationPoolCount()).to.equal(1);
expect(await dao.memberCount()).to.equal(0);
expect(await dao.balanceOf(account1)).to.equal(0);
expect(await dao.totalSupply()).to.equal(POOL_FEE);
});
describe('Initiate', () => {
it('should be able to initiate a validation pool without a fee', async () => {
const init = () => initiateValidationPool({ fee: 0 });
await expect(init()).to.emit(dao, 'LWValidationPoolInitiated');
});
it('should not be able to initiate a validation pool with a quorum below the minimum', async () => {
const init = () => initiateValidationPool({ quorum: [1, 11] });
await expect(init()).to.be.revertedWith('Quorum is below minimum');
});
it('should not be able to initiate a validation pool with a quorum greater than 1', async () => {
const init = () => initiateValidationPool({ quorum: [11, 10] });
await expect(init()).to.be.revertedWith('Quorum is greater than one');
});
it('should not be able to initiate a validation pool with duration below minimum', async () => {
const init = () => initiateValidationPool({ duration: 0 });
await expect(init()).to.be.revertedWith('Duration is too short');
});
it('should not be able to initiate a validation pool with duration above maximum', async () => {
const init = () => initiateValidationPool({ duration: 40000000000000 });
await expect(init()).to.be.revertedWith('Duration is too long');
});
it('should not be able to initiate a validation pool with bindingPercent above 100', async () => {
const init = () => initiateValidationPool({ bindingPercent: 101 });
await expect(init()).to.be.revertedWith('Binding percent must be <= 100');
});
it('should be able to initiate a second validation pool', async () => {
const init = () => initiateValidationPool();
await expect(init()).to.emit(dao, 'LWValidationPoolInitiated').withArgs(1);
expect(await dao.getLWValidationPoolCount()).to.equal(2);
});
it('Should be able to fetch pool instance', async () => {
const pool = await dao.getLWValidationPool(0);
expect(pool).to.exist;
expect(pool.params.duration).to.equal(POOL_DURATION);
expect(pool.props.postId).to.equal('content-id');
expect(pool.props.resolved).to.be.false;
expect(pool.sender).to.equal(account1);
});
});
describe('Propose Result', () => {
it('should not be able to propose an empty result', async () => {
await expect(dao.proposeLWResult(0, 'some-hash', [])).to.be.revertedWith('The proposed result contains no transfers');
});
it('should be able to propose a result', async () => {
await expect(dao.proposeLWResult(0, 'some-hash', [{ from: account1, to: account2, amount: 0 }])).to.emit(dao, 'LWResultProposed').withArgs(0, 0, 'some-hash');
await expect(dao.proposeLWResult(0, 'some-other-hash', [{ from: account1, to: account2, amount: 0 }])).to.emit(dao, 'LWResultProposed').withArgs(0, 1, 'some-other-hash');
});
it('should not be able to propose the same result twice', async () => {
await expect(dao.proposeLWResult(0, 'some-hash', [{ from: account1, to: account2, amount: 0 }])).to.emit(dao, 'LWResultProposed').withArgs(0, 0, 'some-hash');
await expect(dao.proposeLWResult(0, 'some-hash', [{ from: account1, to: account2, amount: 0 }])).to.be.revertedWith('This result hash has already been proposed');
});
});
describe('Stake', async () => {
beforeEach(async () => {
time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(0);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(0);
await initiateValidationPool();
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(100);
});
it('should be able to stake before validation pool has elapsed', async () => {
await dao.stakeOnLWValidationPool(1, 10, true);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(100);
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(1, true, true);
expect(await dao.balanceOf(account1)).to.equal(200);
expect(await dao.balanceOf(dao.target)).to.equal(0);
});
it('should not be able to stake after validation pool has elapsed', async () => {
time.increase(POOL_DURATION + 1);
await expect(dao.stakeOnValidationPool(1, 10, true)).to.be.revertedWith('Pool end time has passed');
});
it('should be able to stake against a validation pool', async () => {
await dao.stakeOnValidationPool(1, 10, false);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(100);
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(1, false, true);
expect(await dao.balanceOf(account1)).to.equal(200);
expect(await dao.balanceOf(dao.target)).to.equal(0);
const pool = await dao.getValidationPool(1);
expect(pool.props.outcome).to.be.false;
});
it('should not be able to stake more REP than the sender owns', async () => {
await expect(dao.stakeOnValidationPool(1, 200, true)).to.be.revertedWith('Insufficient REP balance to cover stake');
});
});
describe('Delegated stake', () => {
it('should stake the lesser of the allowed amount or the owner\'s remaining balance', async () => {
// TODO: owner delegates stake and then loses rep
});
});
describe('Evaluate outcome', () => {
it('should not be able to evaluate outcome before duration has elapsed if not all rep has been staked', async () => {
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(0));
await initiateValidationPool({ fee: 100 });
await expect(dao.evaluateOutcome(1)).to.be.revertedWith('Pool end time has not yet arrived');
});
it('should not be able to evaluate outcome before duration has elapsed unless all rep has been staked', async () => {
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(0));
await initiateValidationPool({ fee: 100 });
await dao.stakeOnValidationPool(1, 100, true);
await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(1, true, true);
});
it('should be able to evaluate outcome after duration has elapsed', async () => {
expect(await dao.balanceOf(dao.target)).to.equal(100);
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(0, true, true);
expect(await dao.memberCount()).to.equal(1);
expect(await dao.balanceOf(account1)).to.equal(100);
const pool = await dao.getValidationPool(0);
expect(pool.props.resolved).to.be.true;
expect(pool.props.outcome).to.be.true;
});
it('should not be able to evaluate outcome more than once', async () => {
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(0, true, true);
await expect(dao.evaluateOutcome(0)).to.be.revertedWith('Pool is already resolved');
});
it('should be able to evaluate outcome of second validation pool', async () => {
const init = () => initiateValidationPool();
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
expect(await dao.getValidationPoolCount()).to.equal(2);
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(0, true, true);
expect(await dao.balanceOf(account1)).to.equal(100);
await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(1, true, true);
expect(await dao.balanceOf(account1)).to.equal(200);
});
it('should not be able to evaluate outcome if quorum is not met', async () => {
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(0, true, true);
const init = () => initiateValidationPool({ quorum: [1, 1] });
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
expect(await dao.getValidationPoolCount()).to.equal(2);
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(1, false, false);
});
describe('Validation pool options', () => {
beforeEach(async () => {
time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(0);
await forum.addPost([{ weightPPM: 1000000, 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);
await dao.evaluateOutcome(1);
});
it('Binding validation pool should redistribute stakes', async () => {
const init = () => initiateValidationPool();
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(2);
await dao.connect(account1).stakeOnValidationPool(2, 10, true);
await dao.connect(account2).stakeOnValidationPool(2, 10, false);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(account2)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(100);
time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(2);
expect(await dao.balanceOf(account1)).to.equal(210);
expect(await dao.balanceOf(account2)).to.equal(90);
expect(await dao.balanceOf(dao.target)).to.equal(0);
});
it('Non binding validation pool should not redistribute stakes', async () => {
const init = () => initiateValidationPool({ bindingPercent: 0 });
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(2);
await dao.connect(account1).stakeOnValidationPool(2, 10, true);
await dao.connect(account2).stakeOnValidationPool(2, 10, false);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(account2)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(100);
time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(2);
expect(await dao.balanceOf(account1)).to.equal(200);
expect(await dao.balanceOf(account2)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(0);
});
it('Partially binding validation pool should redistribute some stakes', async () => {
const init = () => initiateValidationPool({ bindingPercent: 50 });
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(2);
await dao.connect(account1).stakeOnValidationPool(2, 10, true);
await dao.connect(account2).stakeOnValidationPool(2, 10, false);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(account2)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(100);
time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(2);
expect(await dao.balanceOf(account1)).to.equal(205);
expect(await dao.balanceOf(account2)).to.equal(95);
expect(await dao.balanceOf(dao.target)).to.equal(0);
expect(await dao.totalSupply()).to.equal(300);
});
it('If redistributeLosingStakes is false, validation pool should burn binding portion of losing stakes', async () => {
const init = () => initiateValidationPool({
bindingPercent: 50,
redistributeLosingStakes: false,
});
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(2);
await dao.connect(account1).stakeOnValidationPool(2, 10, true);
await dao.connect(account2).stakeOnValidationPool(2, 10, false);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(account2)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(100);
time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(2);
expect(await dao.balanceOf(account1)).to.equal(200);
expect(await dao.balanceOf(account2)).to.equal(95);
expect(await dao.balanceOf(dao.target)).to.equal(0);
expect(await dao.totalSupply()).to.equal(295);
});
it('If redistributeLosingStakes is false and bindingPercent is 0, accounts should recover initial balances', async () => {
const init = () => initiateValidationPool({
bindingPercent: 0,
redistributeLosingStakes: false,
});
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(2);
await dao.connect(account1).stakeOnValidationPool(2, 10, true);
await dao.connect(account2).stakeOnValidationPool(2, 10, false);
expect(await dao.balanceOf(account1)).to.equal(100);
expect(await dao.balanceOf(account2)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(100);
time.increase(POOL_DURATION + 1);
await dao.evaluateOutcome(2);
expect(await dao.balanceOf(account1)).to.equal(200);
expect(await dao.balanceOf(account2)).to.equal(100);
expect(await dao.balanceOf(dao.target)).to.equal(0);
expect(await dao.totalSupply()).to.equal(300);
});
});
});
});

View File

@ -76,7 +76,7 @@ describe('Onboarding', () => {
expect(post.authors).to.have.length(1);
expect(post.authors[0].weightPPM).to.equal(1000000);
expect(post.authors[0].authorAddress).to.equal(account1);
const pool = await dao.validationPools(1);
const pool = await dao.getValidationPool(1);
expect(pool.props.postId).to.equal('evidence-content-id');
expect(pool.props.fee).to.equal(PRICE * 0.9);
expect(pool.sender).to.equal(onboarding.target);
@ -127,7 +127,7 @@ describe('Onboarding', () => {
expect(post.authors).to.have.length(1);
expect(post.authors[0].weightPPM).to.equal(1000000);
expect(post.authors[0].authorAddress).to.equal(account2);
const pool = await dao.validationPools(2);
const pool = await dao.getValidationPool(2);
expect(pool.props.postId).to.equal('req-content-id');
expect(pool.props.fee).to.equal(PRICE * 0.1);
expect(pool.sender).to.equal(onboarding.target);

View File

@ -224,7 +224,7 @@ describe('Proposal', () => {
});
afterEach(async () => {
const pool = await dao.validationPools(3);
const pool = await dao.getValidationPool(3);
expect(pool.props.resolved).to.be.true;
});
@ -310,7 +310,7 @@ describe('Proposal', () => {
});
afterEach(async () => {
const pool = await dao.validationPools(4);
const pool = await dao.getValidationPool(4);
expect(pool.props.resolved).to.be.true;
});

View File

@ -46,7 +46,7 @@ describe('Validation Pools', () => {
await forum.addPost([{ weightPPM: 1000000, 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);
expect(await dao.getValidationPoolCount()).to.equal(1);
expect(await dao.memberCount()).to.equal(0);
expect(await dao.balanceOf(account1)).to.equal(0);
expect(await dao.totalSupply()).to.equal(POOL_FEE);
@ -86,11 +86,11 @@ describe('Validation Pools', () => {
it('should be able to initiate a second validation pool', async () => {
const init = () => initiateValidationPool();
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
expect(await dao.validationPoolCount()).to.equal(2);
expect(await dao.getValidationPoolCount()).to.equal(2);
});
it('Should be able to fetch pool instance', async () => {
const pool = await dao.validationPools(0);
const pool = await dao.getValidationPool(0);
expect(pool).to.exist;
expect(pool.params.duration).to.equal(POOL_DURATION);
expect(pool.props.postId).to.equal('content-id');
@ -133,7 +133,7 @@ describe('Validation Pools', () => {
await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(1, false, true);
expect(await dao.balanceOf(account1)).to.equal(200);
expect(await dao.balanceOf(dao.target)).to.equal(0);
const pool = await dao.validationPools(1);
const pool = await dao.getValidationPool(1);
expect(pool.props.outcome).to.be.false;
});
@ -170,7 +170,7 @@ describe('Validation Pools', () => {
await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(0, true, true);
expect(await dao.memberCount()).to.equal(1);
expect(await dao.balanceOf(account1)).to.equal(100);
const pool = await dao.validationPools(0);
const pool = await dao.getValidationPool(0);
expect(pool.props.resolved).to.be.true;
expect(pool.props.outcome).to.be.true;
});
@ -184,7 +184,7 @@ describe('Validation Pools', () => {
it('should be able to evaluate outcome of second validation pool', async () => {
const init = () => initiateValidationPool();
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
expect(await dao.validationPoolCount()).to.equal(2);
expect(await dao.getValidationPoolCount()).to.equal(2);
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(0)).to.emit(dao, 'ValidationPoolResolved').withArgs(0, true, true);
expect(await dao.balanceOf(account1)).to.equal(100);
@ -198,7 +198,7 @@ describe('Validation Pools', () => {
const init = () => initiateValidationPool({ quorum: [1, 1] });
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
expect(await dao.validationPoolCount()).to.equal(2);
expect(await dao.getValidationPoolCount()).to.equal(2);
time.increase(POOL_DURATION + 1);
await expect(dao.evaluateOutcome(1)).to.emit(dao, 'ValidationPoolResolved').withArgs(1, false, false);
});

View File

@ -229,7 +229,7 @@ describe('Work1', () => {
expect(post.authors).to.have.length(1);
expect(post.authors[0].weightPPM).to.equal(1000000);
expect(post.authors[0].authorAddress).to.equal(account1);
const pool = await dao.validationPools(1);
const pool = await dao.getValidationPool(1);
expect(pool.props.fee).to.equal(WORK1_PRICE);
expect(pool.sender).to.equal(work1.target);
expect(pool.props.postId).to.equal('evidence-content-id');

View File

@ -3,14 +3,17 @@ const { ethers } = require('hardhat');
const deployDAO = async () => {
const Reputation = await ethers.getContractFactory('Reputation');
const Bench = await ethers.getContractFactory('Bench');
const LightweightBench = await ethers.getContractFactory('LightweightBench');
const DAO = await ethers.getContractFactory('DAO');
const GlobalForum = await ethers.getContractFactory('GlobalForum');
const forum = await GlobalForum.deploy();
const reputation = await Reputation.deploy();
const bench = await Bench.deploy();
const lightweightBench = await LightweightBench.deploy();
const dao = await DAO.deploy(
reputation.target,
bench.target,
lightweightBench.target,
forum.target,
);
return {