Add work request/stake events and deployed to sepolia
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 42s
Details
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 42s
Details
This commit is contained in:
parent
e6599ec1f1
commit
40fbe2e18f
|
@ -10,12 +10,12 @@ import work1Artifact from './assets/Work1.json';
|
|||
|
||||
const contracts = {
|
||||
'0x539': { // Hardhat
|
||||
DAO: '0x8d914D38dD301FC4606f5aa9fEcF8A76389020d3',
|
||||
Work1: '0x050C420Cc4995B41217Eba1B54B82Fd5687e9139',
|
||||
DAO: '0x635F46Ea745a14431B27c5dd5838306Be289B747',
|
||||
Work1: '0xEAefe601Aad7422307B99be65bbE005aeA966012',
|
||||
},
|
||||
'0xaa36a7': { // Sepolia
|
||||
DAO: '0x8F00038542C87A5eAf18d5938B7723bF2A04A4e4',
|
||||
Work1: '0x42b79f8d8408c36aD4347ab72f826684440a7a8F',
|
||||
DAO: '0x38AE4ABD47B10f6660CD70Cc8FF3401341E13d9e',
|
||||
Work1: '0x358A07B26F4c556140872ecdB69c58e8807E7178',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -152,7 +152,6 @@ function App() {
|
|||
const promises = [];
|
||||
dispatchValidationPool({ type: 'refresh' });
|
||||
for (let i = 0; i < count; i += 1) {
|
||||
// promises.push(DAOContract.methods.validationPools(i).call());
|
||||
promises.push(fetchValidationPool(i));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
@ -163,8 +162,15 @@ function App() {
|
|||
Object.assign(s, {
|
||||
id: Number(stakeIndex),
|
||||
currentUserIsWorker: () => s.worker.toLowerCase() === account.toString().toLowerCase(),
|
||||
timeRemaining: new Date(Number(s.endTime) * 1000) - new Date(),
|
||||
});
|
||||
dispatchAvailabilityStake({ type: 'update', item: s });
|
||||
if (s.timeRemaining > 0) {
|
||||
setTimeout(() => {
|
||||
s.timeRemaining = 0;
|
||||
dispatchAvailabilityStake({ type: 'update', item: s });
|
||||
}, s.timeRemaining);
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
|
@ -231,6 +237,12 @@ function App() {
|
|||
fetchValidationPool(event.returnValues.poolIndex);
|
||||
});
|
||||
|
||||
work1Contract.events.AvailabilityStaked({ fromBlock: 'latest' }).on('data', (event) => {
|
||||
console.log('event: availability staked', event);
|
||||
fetchAvailabilityStake(event.returnValues.stakeIndex);
|
||||
fetchReputation();
|
||||
});
|
||||
|
||||
work1Contract.events.WorkAssigned({ fromBlock: 'latest' }).on('data', (event) => {
|
||||
console.log('event: work assigned', event);
|
||||
const r = fetchWorkRequest(event.returnValues.requestIndex);
|
||||
|
@ -241,6 +253,11 @@ function App() {
|
|||
console.log('event: work evidence submitted', event);
|
||||
fetchWorkRequest(event.returnValues.requestIndex);
|
||||
});
|
||||
|
||||
work1Contract.events.WorkApprovalSubmitted({ fromBlock: 'latest' }).on('data', (event) => {
|
||||
console.log('event: work approval submitted', event);
|
||||
fetchWorkRequest(event.returnValues.requestIndex);
|
||||
});
|
||||
}, [provider, account, chainId, balance, setReputation, dispatchAvailabilityStake,
|
||||
dispatchValidationPool, dispatchWorkRequest]);
|
||||
|
||||
|
@ -313,8 +330,7 @@ function App() {
|
|||
});
|
||||
}, [DAO, account]);
|
||||
|
||||
const stakeAvailability = useCallback(async () => {
|
||||
const duration = 300; // 5 minutes
|
||||
const stakeAvailability = useCallback(async (duration) => {
|
||||
const target = contracts[chainId].Work1;
|
||||
await DAO.methods.stakeAvailability(target, reputation, duration).send({
|
||||
from: account,
|
||||
|
@ -324,6 +340,20 @@ function App() {
|
|||
setReputation(0);
|
||||
}, [DAO, account, chainId, reputation, setReputation]);
|
||||
|
||||
const reclaimAvailabilityStake = useCallback(async (stakeIndex) => {
|
||||
await work1.methods.reclaimAvailability(stakeIndex).send({
|
||||
from: account,
|
||||
gas: 1000000,
|
||||
});
|
||||
}, [work1, account]);
|
||||
|
||||
const extendAvailabilityStake = useCallback(async (stakeIndex, duration) => {
|
||||
await work1.methods.extendAvailability(stakeIndex, duration).send({
|
||||
from: account,
|
||||
gas: 1000000,
|
||||
});
|
||||
}, [work1, account]);
|
||||
|
||||
const requestWork = useCallback(async () => {
|
||||
const web3 = new Web3(provider);
|
||||
const priceWei = BigInt(web3.utils.toWei(work1Price, 'ether'));
|
||||
|
@ -482,13 +512,19 @@ function App() {
|
|||
<div>
|
||||
<h2>Work Contract 1</h2>
|
||||
<div>
|
||||
Price:
|
||||
{work1Price}
|
||||
{' '}
|
||||
ETH
|
||||
{`Price: ${work1Price} ETH`}
|
||||
</div>
|
||||
<div>
|
||||
<Button onClick={() => stakeAvailability()}>Stake Availability</Button>
|
||||
Stake Availability:
|
||||
{' '}
|
||||
{!reputation && <>No reputation available to stake</>}
|
||||
{reputation > 0 && (
|
||||
<>
|
||||
<Button onClick={() => stakeAvailability(300)}>5 Min.</Button>
|
||||
{' '}
|
||||
<Button onClick={() => stakeAvailability(7200)}>2 Hr.</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
Availability Stake Count:
|
||||
|
@ -505,6 +541,7 @@ function App() {
|
|||
<th>End Time</th>
|
||||
<th>Assigned</th>
|
||||
<th>Reclaimed</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -516,6 +553,22 @@ function App() {
|
|||
<td>{new Date(Number(s.endTime) * 1000).toLocaleString()}</td>
|
||||
<td>{s.assigned.toString()}</td>
|
||||
<td>{s.reclaimed.toString()}</td>
|
||||
<td>
|
||||
{s.currentUserIsWorker() && (
|
||||
<Button onClick={() => extendAvailabilityStake(s.id, 3600)}>
|
||||
Extend 1 Hr.
|
||||
</Button>
|
||||
)}
|
||||
{s.currentUserIsWorker() && s.timeRemaining <= 0
|
||||
&& !s.assigned && !s.reclaimed && (
|
||||
<>
|
||||
{' '}
|
||||
<Button onClick={() => reclaimAvailabilityStake(s.id)}>
|
||||
Reclaim
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -39,8 +39,10 @@ contract Work1 is IAcceptAvailability {
|
|||
// TODO: Make parameters configurable
|
||||
uint constant POOL_DURATION = 1 days;
|
||||
|
||||
event AvailabilityStaked(uint stakeIndex);
|
||||
event WorkAssigned(address worker, uint requestIndex);
|
||||
event WorkEvidenceSubmitted(uint requestIndex);
|
||||
event WorkApprovalSubmitted(uint requestIndex, bool approval);
|
||||
|
||||
constructor(DAO dao_, uint price_) {
|
||||
dao = dao_;
|
||||
|
@ -53,10 +55,13 @@ contract Work1 is IAcceptAvailability {
|
|||
uint256 amount,
|
||||
uint duration
|
||||
) external {
|
||||
AvailabilityStake storage stake = stakes[stakeCount++];
|
||||
require(amount > 0, "No stake provided");
|
||||
uint stakeIndex = stakeCount++;
|
||||
AvailabilityStake storage stake = stakes[stakeIndex];
|
||||
stake.worker = sender;
|
||||
stake.amount = amount;
|
||||
stake.endTime = block.timestamp + duration;
|
||||
emit AvailabilityStaked(stakeIndex);
|
||||
}
|
||||
|
||||
function extendAvailability(uint stakeIndex, uint duration) external {
|
||||
|
@ -66,6 +71,7 @@ contract Work1 is IAcceptAvailability {
|
|||
"Worker can only extend their own availability stake"
|
||||
);
|
||||
stake.endTime = block.timestamp + duration;
|
||||
emit AvailabilityStaked(stakeIndex);
|
||||
}
|
||||
|
||||
function reclaimAvailability(uint stakeIndex) external {
|
||||
|
@ -79,8 +85,10 @@ contract Work1 is IAcceptAvailability {
|
|||
"Stake duration has not yet elapsed"
|
||||
);
|
||||
require(!stake.reclaimed, "Stake has already been reclaimed");
|
||||
require(!stake.assigned, "Stake has already been assigned work");
|
||||
stake.reclaimed = true;
|
||||
dao.transfer(msg.sender, stake.amount);
|
||||
emit AvailabilityStaked(stakeIndex);
|
||||
}
|
||||
|
||||
/// Select a worker randomly from among the available workers, weighted by amount staked
|
||||
|
@ -151,6 +159,7 @@ contract Work1 is IAcceptAvailability {
|
|||
request.approval = approval;
|
||||
// Make work evidence post
|
||||
uint postIndex = dao.addPost(stake.worker);
|
||||
emit WorkApprovalSubmitted(requestIndex, approval);
|
||||
// Initiate validation pool
|
||||
request.poolIndex = dao.initiateValidationPool{value: request.fee}(
|
||||
postIndex,
|
||||
|
|
|
@ -49,7 +49,7 @@ describe('Work1', () => {
|
|||
work1 = setup.work1;
|
||||
account1 = setup.account1;
|
||||
account2 = setup.account2;
|
||||
await dao.stakeAvailability(work1.target, 50, STAKE_DURATION);
|
||||
await expect(dao.stakeAvailability(work1.target, 50, STAKE_DURATION)).to.emit(work1, 'AvailabilityStaked').withArgs(0);
|
||||
});
|
||||
|
||||
it('Should be able to stake availability', async () => {
|
||||
|
@ -62,13 +62,24 @@ describe('Work1', () => {
|
|||
expect(stake.endTime).to.equal(await time.latest() + STAKE_DURATION);
|
||||
});
|
||||
|
||||
it('should not be able to stake availability without reputation value', async () => {
|
||||
await expect(dao.stakeAvailability(work1.target, 0, STAKE_DURATION)).to.be.revertedWith('No stake provided');
|
||||
});
|
||||
|
||||
it('should be able to reclaim staked availability after duration elapses', async () => {
|
||||
expect(await dao.balanceOf(account1)).to.equal(50);
|
||||
time.increase(STAKE_DURATION + 1);
|
||||
await work1.reclaimAvailability(0);
|
||||
await expect(work1.reclaimAvailability(0)).to.emit(work1, 'AvailabilityStaked').withArgs(0);
|
||||
expect(await dao.balanceOf(account1)).to.equal(100);
|
||||
});
|
||||
|
||||
it('should not be able to reclaim staked availability twice', async () => {
|
||||
expect(await dao.balanceOf(account1)).to.equal(50);
|
||||
time.increase(STAKE_DURATION + 1);
|
||||
await work1.reclaimAvailability(0);
|
||||
await expect(work1.reclaimAvailability(0)).to.be.revertedWith('Stake has already been reclaimed');
|
||||
});
|
||||
|
||||
it('should not be able to reclaim staked availability before duration elapses', async () => {
|
||||
await expect(work1.reclaimAvailability(0)).to.be.revertedWith('Stake duration has not yet elapsed');
|
||||
});
|
||||
|
@ -80,7 +91,7 @@ describe('Work1', () => {
|
|||
|
||||
it('should be able to extend the duration of an availability stake before it expires', async () => {
|
||||
await time.increase(STAKE_DURATION / 2);
|
||||
await work1.extendAvailability(0, STAKE_DURATION);
|
||||
await expect(work1.extendAvailability(0, STAKE_DURATION)).to.emit(work1, 'AvailabilityStaked').withArgs(0);
|
||||
});
|
||||
|
||||
it('should be able to extend the duration of an availability stake after it expires', async () => {
|
||||
|
@ -107,6 +118,16 @@ describe('Work1', () => {
|
|||
expect(request.customer).to.equal(account2);
|
||||
});
|
||||
|
||||
it('should not be able to reclaim stake after work is assigned', async () => {
|
||||
const {
|
||||
dao, work1, account1, account2,
|
||||
} = await loadFixture(deploy);
|
||||
await dao.stakeAvailability(work1.target, 50, STAKE_DURATION);
|
||||
const requestWork = () => work1.connect(account2).requestWork({ value: WORK1_PRICE });
|
||||
await expect(requestWork()).to.emit(work1, 'WorkAssigned').withArgs(account1, 0);
|
||||
await time.increase(STAKE_DURATION + 1);
|
||||
await expect(work1.reclaimAvailability(0)).to.be.revertedWith('Stake has already been assigned work');
|
||||
});
|
||||
it('should not be able to request work if there are no availability stakes', async () => {
|
||||
const {
|
||||
work1, account2,
|
||||
|
@ -129,7 +150,7 @@ describe('Work1', () => {
|
|||
} = await loadFixture(deploy);
|
||||
await dao.stakeAvailability(work1.target, 50, STAKE_DURATION);
|
||||
const requestWork = () => work1.connect(account2).requestWork({ value: WORK1_PRICE });
|
||||
await time.increase(61);
|
||||
await time.increase(STAKE_DURATION + 1);
|
||||
await expect(requestWork()).to.be.revertedWith('No available worker stakes');
|
||||
});
|
||||
|
||||
|
@ -178,7 +199,9 @@ describe('Work1', () => {
|
|||
it('should be able to submit work approval', async () => {
|
||||
await work1.connect(account2).requestWork({ value: WORK1_PRICE });
|
||||
await work1.submitWorkEvidence(0);
|
||||
await expect(work1.submitWorkApproval(0, true)).to.emit(dao, 'ValidationPoolInitiated').withArgs(1);
|
||||
await expect(work1.submitWorkApproval(0, true))
|
||||
.to.emit(dao, 'ValidationPoolInitiated').withArgs(1)
|
||||
.to.emit(work1, 'WorkApprovalSubmitted').withArgs(0, true);
|
||||
const post = await dao.posts(1);
|
||||
expect(post.author).to.equal(account1);
|
||||
expect(post.sender).to.equal(work1.target);
|
||||
|
@ -187,7 +210,9 @@ describe('Work1', () => {
|
|||
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);
|
||||
await expect(work1.submitWorkApproval(0, false))
|
||||
.to.emit(dao, 'ValidationPoolInitiated').withArgs(1)
|
||||
.to.emit(work1, 'WorkApprovalSubmitted').withArgs(0, false);
|
||||
});
|
||||
|
||||
it('should not be able to submit work approval/disapproval twice', async () => {
|
||||
|
|
Loading…
Reference in New Issue