Added first tests
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 36s Details

This commit is contained in:
Ladd Hoffman 2024-03-05 21:21:27 -06:00
parent 720acd58a3
commit 20a4aab2a6
9 changed files with 2647 additions and 92 deletions

25
ethereum/.eslintrc.cjs Normal file
View File

@ -0,0 +1,25 @@
module.exports = {
root: true,
env: { browser: true, es2020: true, mocha: true },
extends: [
'eslint:recommended',
'airbnb',
'plugin:chai-friendly/recommended',
],
ignorePatterns: ['hardhat.config.js'],
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
settings: { react: { version: '18.2' } },
plugins: [
'chai-friendly',
],
rules: {
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: ['test/**'],
optionalDependencies: false,
peerDependencies: false,
},
],
},
};

View File

@ -35,9 +35,9 @@ struct StakeData {
contract DAO is ERC721("Reputation", "REP"), ReputationHolder {
mapping(uint256 tokenId => uint256) tokenValues;
uint256 nextTokenId;
uint256 totalValue;
mapping(uint => ValidationPool) validationPools;
uint validationPoolCount;
uint256 public totalValue;
mapping(uint => ValidationPool) public validationPools;
uint public validationPoolCount;
// ufixed8x1 constant mintingRatio = 1;
// ufixed8x1 constant quorum = 0;
@ -93,8 +93,8 @@ contract DAO is ERC721("Reputation", "REP"), ReputationHolder {
function initiateValidationPool(
address author,
uint duration
) public payable {
uint poolIndex = validationPoolCount++;
) public payable returns (uint poolIndex) {
poolIndex = validationPoolCount++;
ValidationPool storage pool = validationPools[poolIndex];
pool.author = author;
pool.fee = msg.value;
@ -234,8 +234,9 @@ contract DAO is ERC721("Reputation", "REP"), ReputationHolder {
}
// Distribute fee proportionatly among all reputation holders
for (uint tokenId = 0; tokenId < nextTokenId; tokenId++) {
uint256 share = (pool.fee * tokenValues[tokenId]) / totalValue;
uint256 share = (pool.fee * valueOf(tokenId)) / totalValue;
address recipient = ownerOf(tokenId);
// TODO: For efficiency this could be modified to hold the funds for recipients to withdraw
payable(recipient).transfer(share);
}
}

View File

@ -24,15 +24,19 @@ struct WorkRequest {
WorkStatus status;
uint stakeIndex;
bool approval;
uint poolIndex;
}
contract Work1 is ReputationHolder {
DAO dao;
DAO immutable dao;
uint public immutable price;
mapping(uint => AvailabilityStake) stakes;
uint stakeCount;
mapping(uint => WorkRequest) requests;
uint requestCount;
mapping(uint => WorkRequest) public requests;
uint public requestCount;
// TODO: Make parameters configurable
uint constant POOL_DURATION = 1 days;
event WorkAssigned(address worker, uint requestIndex);
@ -104,8 +108,13 @@ contract Work1 is ReputationHolder {
function submitWorkApproval(uint requestIndex, bool approval) external {
WorkRequest storage request = requests[requestIndex];
require(request.status == WorkStatus.EvidenceSubmitted);
AvailabilityStake storage stake = stakes[request.stakeIndex];
request.status = WorkStatus.ApprovalSubmitted;
request.approval = approval;
// TODO: Initiate validation pool
// Initiate validation pool
request.poolIndex = dao.initiateValidationPool(
stake.worker,
POOL_DURATION
);
}
}

View File

@ -1,6 +1,6 @@
require("@nomicfoundation/hardhat-toolbox");
require('@nomicfoundation/hardhat-toolbox');
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.24",
solidity: '0.8.24',
};

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,15 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-chai-friendly": "^0.7.4",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-react": "^7.34.0",
"eslint-plugin-react-hooks": "^4.6.0",
"hardhat": "^2.20.1",
"prettier": "^3.2.5",
"prettier-plugin-solidity": "^1.3.1"

40
ethereum/test/DAO.js Normal file
View File

@ -0,0 +1,40 @@
const {
loadFixture,
} = require('@nomicfoundation/hardhat-toolbox/network-helpers');
const { expect } = require('chai');
const { ethers } = require('hardhat');
describe.only('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 deployDAO() {
// 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 };
}
describe('Validation Pool', () => {
it('Should deploy', async () => {
const { dao } = await loadFixture(deployDAO);
expect(dao).to.exist;
expect(await dao.totalValue()).to.equal(0);
});
describe('Initiate validation pool', () => {
it('Should initiate', async () => {
const POOL_DURATION = 3600; // 1 hour
const { dao, account1 } = await loadFixture(deployDAO);
const init = () => dao.initiateValidationPool(account1, POOL_DURATION);
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(0);
const pool = await dao.validationPools(0);
expect(pool).to.exist;
expect(pool.duration).to.equal(POOL_DURATION);
});
});
});
});

View File

@ -1,11 +1,12 @@
const {
time,
loadFixture,
} = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs");
const { expect } = require("chai");
} = require('@nomicfoundation/hardhat-toolbox/network-helpers');
const { anyValue } = require('@nomicfoundation/hardhat-chai-matchers/withArgs');
const { expect } = require('chai');
const { ethers } = require('hardhat');
describe("Lock", function () {
describe('Lock', () => {
// 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.
@ -19,58 +20,60 @@ describe("Lock", function () {
// Contracts are deployed using the first signer/account by default
const [owner, otherAccount] = await ethers.getSigners();
const Lock = await ethers.getContractFactory("Lock");
const Lock = await ethers.getContractFactory('Lock');
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
return { lock, unlockTime, lockedAmount, owner, otherAccount };
return {
lock, unlockTime, lockedAmount, owner, otherAccount,
};
}
describe("Deployment", function () {
it("Should set the right unlockTime", async function () {
describe('Deployment', () => {
it('Should set the right unlockTime', async () => {
const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture);
expect(await lock.unlockTime()).to.equal(unlockTime);
});
it("Should set the right owner", async function () {
it('Should set the right owner', async () => {
const { lock, owner } = await loadFixture(deployOneYearLockFixture);
expect(await lock.owner()).to.equal(owner.address);
});
it("Should receive and store the funds to lock", async function () {
it('Should receive and store the funds to lock', async () => {
const { lock, lockedAmount } = await loadFixture(
deployOneYearLockFixture
deployOneYearLockFixture,
);
expect(await ethers.provider.getBalance(lock.target)).to.equal(
lockedAmount
lockedAmount,
);
});
it("Should fail if the unlockTime is not in the future", async function () {
it('Should fail if the unlockTime is not in the future', async () => {
// We don't use the fixture here because we want a different deployment
const latestTime = await time.latest();
const Lock = await ethers.getContractFactory("Lock");
const Lock = await ethers.getContractFactory('Lock');
await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
"Unlock time should be in the future"
'Unlock time should be in the future',
);
});
});
describe("Withdrawals", function () {
describe("Validations", function () {
it("Should revert with the right error if called too soon", async function () {
describe('Withdrawals', () => {
describe('Validations', () => {
it('Should revert with the right error if called too soon', async () => {
const { lock } = await loadFixture(deployOneYearLockFixture);
await expect(lock.withdraw()).to.be.revertedWith(
"You can't withdraw yet"
"You can't withdraw yet",
);
});
it("Should revert with the right error if called from another account", async function () {
it('Should revert with the right error if called from another account', async () => {
const { lock, unlockTime, otherAccount } = await loadFixture(
deployOneYearLockFixture
deployOneYearLockFixture,
);
// We can increase the time in Hardhat Network
@ -78,13 +81,13 @@ describe("Lock", function () {
// We use lock.connect() to send a transaction from another account
await expect(lock.connect(otherAccount).withdraw()).to.be.revertedWith(
"You aren't the owner"
"You aren't the owner",
);
});
it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () {
it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async () => {
const { lock, unlockTime } = await loadFixture(
deployOneYearLockFixture
deployOneYearLockFixture,
);
// Transactions are sent using the first signer by default
@ -94,31 +97,33 @@ describe("Lock", function () {
});
});
describe("Events", function () {
it("Should emit an event on withdrawals", async function () {
describe('Events', () => {
it('Should emit an event on withdrawals', async () => {
const { lock, unlockTime, lockedAmount } = await loadFixture(
deployOneYearLockFixture
deployOneYearLockFixture,
);
await time.increaseTo(unlockTime);
await expect(lock.withdraw())
.to.emit(lock, "Withdrawal")
.to.emit(lock, 'Withdrawal')
.withArgs(lockedAmount, anyValue); // We accept any value as `when` arg
});
});
describe("Transfers", function () {
it("Should transfer the funds to the owner", async function () {
const { lock, unlockTime, lockedAmount, owner } = await loadFixture(
deployOneYearLockFixture
describe('Transfers', () => {
it('Should transfer the funds to the owner', async () => {
const {
lock, unlockTime, lockedAmount, owner,
} = await loadFixture(
deployOneYearLockFixture,
);
await time.increaseTo(unlockTime);
await expect(lock.withdraw()).to.changeEtherBalances(
[owner, lock],
[lockedAmount, -lockedAmount]
[lockedAmount, -lockedAmount],
);
});
});

59
ethereum/test/Work1.js Normal file
View File

@ -0,0 +1,59 @@
const {
time,
loadFixture,
} = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { expect } = require("chai");
describe("Lock", function () {
// 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 deployOneYearLockFixture() {
const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60;
const ONE_GWEI = 1_000_000_000;
const lockedAmount = ONE_GWEI;
const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS;
// Contracts are deployed using the first signer/account by default
const [owner, otherAccount] = await ethers.getSigners();
const Lock = await ethers.getContractFactory("Lock");
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
return { lock, unlockTime, lockedAmount, owner, otherAccount };
}
describe("Deployment", function () {
it("Should set the right unlockTime", async function () {
const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture);
expect(await lock.unlockTime()).to.equal(unlockTime);
});
it("Should set the right owner", async function () {
const { lock, owner } = await loadFixture(deployOneYearLockFixture);
expect(await lock.owner()).to.equal(owner.address);
});
it("Should receive and store the funds to lock", async function () {
const { lock, lockedAmount } = await loadFixture(
deployOneYearLockFixture
);
expect(await ethers.provider.getBalance(lock.target)).to.equal(
lockedAmount
);
});
it("Should fail if the unlockTime is not in the future", async function () {
// We don't use the fixture here because we want a different deployment
const latestTime = await time.latest();
const Lock = await ethers.getContractFactory("Lock");
await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
"Unlock time should be in the future"
);
});
});
});