add automatic staking script
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
Details
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
Details
This commit is contained in:
parent
6df1ad4c70
commit
eaa81c17ec
|
@ -0,0 +1 @@
|
|||
SEPOLIA_PRIVATE_KEY=
|
|
@ -33,11 +33,6 @@ struct ValidationPool {
|
|||
bool outcome;
|
||||
}
|
||||
|
||||
struct StakeData {
|
||||
uint poolIndex;
|
||||
bool inFavor;
|
||||
}
|
||||
|
||||
/// This contract must manage validation pools and reputation,
|
||||
/// because otherwise there's no way to enforce appropriate permissions on
|
||||
/// transfer of value between reputation NFTs.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require('@nomicfoundation/hardhat-toolbox');
|
||||
require('@nomicfoundation/hardhat-verify');
|
||||
require('dotenv').config();
|
||||
|
||||
/** @type import('hardhat/config').HardhatUserConfig */
|
||||
|
@ -16,4 +17,12 @@ module.exports = {
|
|||
accounts: [process.env.SEPOLIA_PRIVATE_KEY],
|
||||
},
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: {
|
||||
sepolia: process.env.ETHERSCAN_API_KEY,
|
||||
},
|
||||
},
|
||||
sourcify: {
|
||||
enabled: false,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"devDependencies": {
|
||||
"@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
|
||||
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
|
||||
"@nomicfoundation/hardhat-verify": "^2.0.5",
|
||||
"chai": "^4.4.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
|
@ -1693,11 +1694,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@nomicfoundation/hardhat-verify": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.4.tgz",
|
||||
"integrity": "sha512-B8ZjhOrmbbRWqJi65jvQblzjsfYktjqj2vmOm+oc2Vu8drZbT2cjeSCRHZKbS7lOtfW78aJZSFvw+zRLCiABJA==",
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.5.tgz",
|
||||
"integrity": "sha512-Tg4zu8RkWpyADSFIgF4FlJIUEI4VkxcvELsmbJn2OokbvH2SnUrqKmw0BBfDrtvP0hhmx8wsnrRKP5DV/oTyTA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ethersproject/abi": "^5.1.2",
|
||||
"@ethersproject/address": "^5.0.2",
|
||||
|
@ -2389,7 +2389,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
|
@ -2740,7 +2739,6 @@
|
|||
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
|
||||
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
@ -3120,7 +3118,6 @@
|
|||
"resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz",
|
||||
"integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nofilter": "^3.1.0"
|
||||
},
|
||||
|
@ -6396,8 +6393,7 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-stable-stringify-without-jsonify": {
|
||||
"version": "1.0.1",
|
||||
|
@ -6556,8 +6552,7 @@
|
|||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
|
@ -6576,8 +6571,7 @@
|
|||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
|
||||
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/log-symbols": {
|
||||
"version": "4.1.0",
|
||||
|
@ -7118,7 +7112,6 @@
|
|||
"resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz",
|
||||
"integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12.19"
|
||||
}
|
||||
|
@ -8286,7 +8279,6 @@
|
|||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
|
||||
"integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"astral-regex": "^2.0.0",
|
||||
|
@ -8304,7 +8296,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
|
@ -8320,7 +8311,6 @@
|
|||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
|
@ -8332,8 +8322,7 @@
|
|||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/solc": {
|
||||
"version": "0.7.3",
|
||||
|
@ -8751,7 +8740,6 @@
|
|||
"resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
|
||||
"integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ajv": "^8.0.1",
|
||||
"lodash.truncate": "^4.4.2",
|
||||
|
|
|
@ -4,13 +4,16 @@
|
|||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"test": "hardhat test",
|
||||
"automatic-staking-local": "hardhat run --network localhost scripts/automatic-staking.js localhost",
|
||||
"automatic-staking-sepolia": "hardhat run --network sepolia scripts/automatic-staking.js sepolia"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
|
||||
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
|
||||
"@nomicfoundation/hardhat-verify": "^2.0.5",
|
||||
"chai": "^4.4.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
const { ethers } = require('hardhat');
|
||||
|
||||
const DAOAddress = {
|
||||
localhost: '0x76Dfe9F47f06112a1b78960bf37d87CfbB6D6133',
|
||||
sepolia: '0x39B7522Ee1A5B13aE5580C40114239D4cE0e7D29',
|
||||
};
|
||||
|
||||
let dao;
|
||||
let account;
|
||||
let validationPools;
|
||||
let reputation;
|
||||
|
||||
const fetchReputation = async () => {
|
||||
reputation = await dao.balanceOf(account);
|
||||
console.log(`reputation: ${reputation}`);
|
||||
};
|
||||
|
||||
const fetchValidationPool = async (poolIndex) => {
|
||||
const pool = await dao.validationPools(poolIndex);
|
||||
validationPools[poolIndex] = pool;
|
||||
return pool;
|
||||
};
|
||||
|
||||
const fetchValidationPools = async () => {
|
||||
const count = await dao.validationPoolCount();
|
||||
console.log(`validation pool count: ${count}`);
|
||||
const promises = [];
|
||||
validationPools = [];
|
||||
for (let i = 0; i < count; i += 1) {
|
||||
promises.push(fetchValidationPool(i));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
};
|
||||
|
||||
const initialize = async () => {
|
||||
const network = process.argv[2];
|
||||
if (!network) {
|
||||
throw new Error('please provide network name as first argument');
|
||||
}
|
||||
if (!DAOAddress[network]) {
|
||||
throw new Error(`network '${network}' is unknown`);
|
||||
}
|
||||
dao = await ethers.getContractAt('DAO', DAOAddress);
|
||||
[account] = await ethers.getSigners();
|
||||
const address = await account.getAddress();
|
||||
console.log(`account: ${address}`);
|
||||
await fetchReputation();
|
||||
await fetchValidationPools();
|
||||
};
|
||||
|
||||
const poolIsActive = (pool) => {
|
||||
if (new Date() >= new Date(Number(pool.endTime) * 1000)) return false;
|
||||
if (pool.resolved) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
const stake = async (pool, amount) => {
|
||||
console.log(`staking ${amount} in favor of pool ${pool.id.toString()}`);
|
||||
await dao.stake(pool.id, amount, true);
|
||||
await fetchReputation();
|
||||
};
|
||||
|
||||
const stakeEach = async (pools, amountPerPool) => {
|
||||
const promises = [];
|
||||
pools.forEach((pool) => {
|
||||
promises.push(stake(pool, amountPerPool));
|
||||
});
|
||||
await Promise.all(promises);
|
||||
};
|
||||
|
||||
async function main() {
|
||||
await initialize();
|
||||
|
||||
validationPools.forEach((pool) => {
|
||||
let status;
|
||||
if (poolIsActive(pool)) status = 'Active';
|
||||
else if (!pool.resolved) status = 'Ready to Evaluate';
|
||||
else if (pool.outcome) status = 'Accepted';
|
||||
else status = 'Rejected';
|
||||
console.log(`pool ${pool.id.toString()}, status: ${status}`);
|
||||
});
|
||||
|
||||
// Stake half of available reputation on any active validation pools
|
||||
const activePools = validationPools.filter(poolIsActive);
|
||||
if (activePools.length && reputation > 0) {
|
||||
const amountPerPool = reputation / BigInt(2) / BigInt(activePools.length);
|
||||
await stakeEach(activePools, amountPerPool);
|
||||
}
|
||||
|
||||
// Listen for new validation pools
|
||||
dao.on('ValidationPoolInitiated', async (poolIndex) => {
|
||||
console.log(`pool ${poolIndex} started`);
|
||||
await fetchValidationPool(poolIndex);
|
||||
await fetchReputation();
|
||||
|
||||
// Stake half of available reputation on this validation pool
|
||||
const amount = reputation / BigInt(2);
|
||||
await stake(poolIndex, amount, true);
|
||||
});
|
||||
|
||||
dao.on('ValidationPoolResolved', async (poolIndex, votePasses) => {
|
||||
console.log(`pool ${poolIndex} resolved, status: ${votePasses ? 'accepted' : 'rejected'}`);
|
||||
fetchValidationPool(poolIndex);
|
||||
fetchReputation();
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
|
@ -44,9 +44,7 @@ describe('DAO', () => {
|
|||
const POOL_FEE = 100;
|
||||
|
||||
beforeEach(async () => {
|
||||
const setup = await loadFixture(deploy);
|
||||
dao = setup.dao;
|
||||
account1 = setup.account1;
|
||||
({ dao, account1 } = await loadFixture(deploy));
|
||||
await dao.addPost(account1);
|
||||
const init = () => dao.initiateValidationPool(0, POOL_DURATION, { value: POOL_FEE });
|
||||
await expect(init()).to.emit(dao, 'ValidationPoolInitiated').withArgs(0);
|
||||
|
|
|
@ -44,11 +44,9 @@ describe('Work1', () => {
|
|||
let account2;
|
||||
|
||||
beforeEach(async () => {
|
||||
const setup = await loadFixture(deploy);
|
||||
dao = setup.dao;
|
||||
work1 = setup.work1;
|
||||
account1 = setup.account1;
|
||||
account2 = setup.account2;
|
||||
({
|
||||
dao, work1, account1, account2,
|
||||
} = await loadFixture(deploy));
|
||||
await expect(dao.stakeAvailability(work1.target, 50, STAKE_DURATION)).to.emit(work1, 'AvailabilityStaked').withArgs(0);
|
||||
});
|
||||
|
||||
|
@ -204,11 +202,9 @@ describe('Work1', () => {
|
|||
let account2;
|
||||
|
||||
beforeEach(async () => {
|
||||
const setup = await loadFixture(deploy);
|
||||
dao = setup.dao;
|
||||
work1 = setup.work1;
|
||||
account1 = setup.account1;
|
||||
account2 = setup.account2;
|
||||
({
|
||||
dao, work1, account1, account2,
|
||||
} = await loadFixture(deploy));
|
||||
await dao.stakeAvailability(work1.target, 50, STAKE_DURATION);
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue