diff --git a/backend/src/event-handlers/rollup.js b/backend/src/event-handlers/rollup.js index 9197803..395e6a8 100644 --- a/backend/src/event-handlers/rollup.js +++ b/backend/src/event-handlers/rollup.js @@ -28,11 +28,6 @@ const stakeRollupAvailability = async () => { await dao.stakeAvailability(rollup.target, currentRep, availabilityStakeDuration); }; -const extendRollupAvailability = async () => { - const currentRep = await dao.balanceOf(await wallet.getAddress()); - await dao.stakeAvailability(rollup.target, currentRep, availabilityStakeDuration); -}; - const getBatchPostAuthorWeights = async (batchItems_) => { const weights = {}; await Promise.each(batchItems_, async (postId) => { @@ -184,12 +179,9 @@ const start = async () => { batchWorker = await rollup.batchWorker(); console.log('At startup', { batchWorker }); - // Stake availability and + // Stake availability and set an interval to maintain it await stakeRollupAvailability(); - // Set an interval to maintain it - setInterval(() => { - - }); + setInterval(stakeRollupAvailability, availabilityStakeDuration * 1000); rollup.on('BatchWorkerAssigned', async (batchWorker_) => { console.log('Batch worker assigned:', batchWorker); diff --git a/ethereum/contracts/Availability.sol b/ethereum/contracts/Availability.sol index fb04ded..e810e56 100644 --- a/ethereum/contracts/Availability.sol +++ b/ethereum/contracts/Availability.sol @@ -25,7 +25,7 @@ contract Availability is IAcceptAvailability, DAOContract { address worker, uint256 amount, uint duration - ) external { + ) external returns (uint refund) { require( msg.sender == address(dao), "acceptAvailability must only be called by DAO contract" @@ -41,6 +41,10 @@ contract Availability is IAcceptAvailability, DAOContract { // Stake has already been assigned; We need to create a new one stakeIndex = stakeCount++; activeWorkerStakes[worker] = stakeIndex; + } else { + // We are replacing an existing stake. + // That means we can refund some of the granted allowance + refund = stakes[stakeIndex].amount; } AvailabilityStake storage stake = stakes[stakeIndex]; stake.worker = worker; diff --git a/ethereum/contracts/core/DAO.sol b/ethereum/contracts/core/DAO.sol index bca74ec..3500fc4 100644 --- a/ethereum/contracts/core/DAO.sol +++ b/ethereum/contracts/core/DAO.sol @@ -101,14 +101,6 @@ contract DAO { return rep.allowance(owner, spender); } - function spendAllowance( - address owner, - address spender, - uint256 value - ) public { - return rep.spendAllowance(owner, spender, value); - } - function forwardAllowance( address owner, address to, @@ -124,8 +116,16 @@ contract DAO { uint256 value, uint duration ) external returns (bool) { - rep.approve(msg.sender, to, value); - IAcceptAvailability(to).acceptAvailability(msg.sender, value, duration); + uint refund = IAcceptAvailability(to).acceptAvailability( + msg.sender, + value, + duration + ); + rep.approve( + msg.sender, + to, + rep.allowance(msg.sender, to) + value - refund + ); return true; } @@ -219,7 +219,7 @@ contract DAO { if (allowance(owner, msg.sender) < amount) { amount = allowance(owner, msg.sender); } - spendAllowance(owner, msg.sender, amount); + rep.spendAllowance(owner, msg.sender, amount); bench.stakeOnValidationPool(poolIndex, owner, amount, inFavor); } diff --git a/ethereum/contracts/interfaces/IAcceptAvailability.sol b/ethereum/contracts/interfaces/IAcceptAvailability.sol index 9643466..68f54bb 100644 --- a/ethereum/contracts/interfaces/IAcceptAvailability.sol +++ b/ethereum/contracts/interfaces/IAcceptAvailability.sol @@ -6,5 +6,5 @@ interface IAcceptAvailability { address from, uint256 value, uint duration - ) external; + ) external returns (uint refund); } diff --git a/ethereum/test/Work1.js b/ethereum/test/Work1.js index 38cc2dc..a31ed15 100644 --- a/ethereum/test/Work1.js +++ b/ethereum/test/Work1.js @@ -69,6 +69,7 @@ describe('Work1', () => { expect(stake.worker).to.equal(account1); expect(stake.amount).to.equal(50); expect(stake.endTime).to.equal(await time.latest() + STAKE_DURATION); + expect(await dao.allowance(account1, work1.target)).to.equal(50); }); it('should not be able to stake availability without reputation value', async () => { @@ -84,6 +85,7 @@ describe('Work1', () => { expect(await work1.stakeCount()).to.equal(1); await expect(dao.stakeAvailability(work1.target, 50, STAKE_DURATION)).to.emit(work1, 'AvailabilityStaked').withArgs(0); expect(await work1.stakeCount()).to.equal(1); + expect(await dao.allowance(account1, work1.target)).to.equal(50); }); it('should be able to extend the duration of an availability stake after it expires', async () => { @@ -91,6 +93,7 @@ describe('Work1', () => { expect(await work1.stakeCount()).to.equal(1); await dao.stakeAvailability(work1.target, 50, STAKE_DURATION); expect(await work1.stakeCount()).to.equal(1); + expect(await dao.allowance(account1, work1.target)).to.equal(50); }); it('extending a stake before expiration should reset the end time to the new duration from the present', async () => { @@ -101,6 +104,7 @@ describe('Work1', () => { const expectedEndTime = await time.latest() + 2 * STAKE_DURATION; const stake = await work1.stakes(0); expect(stake.endTime).to.be.within(expectedEndTime - 1, expectedEndTime); + expect(await dao.allowance(account1, work1.target)).to.equal(50); }); it('extending a stake after expiration should restart the stake for the given duration', async () => { @@ -111,6 +115,7 @@ describe('Work1', () => { const expectedEndTime = await time.latest() + STAKE_DURATION * 2; const stake = await work1.stakes(0); expect(stake.endTime).to.be.within(expectedEndTime - 1, expectedEndTime); + expect(await dao.allowance(account1, work1.target)).to.equal(50); }); }); @@ -166,7 +171,7 @@ describe('Work1', () => { it('after a stake has been assigned work, staking again should create a new stake', async () => { const { - dao, work1, account2, + dao, work1, account1, account2, } = await loadFixture(deploy); await dao.stakeAvailability(work1.target, 50, STAKE_DURATION); await work1.connect(account2).requestWork('req-content-id', { value: WORK1_PRICE }); @@ -174,6 +179,7 @@ describe('Work1', () => { expect(await work1.stakeCount()).to.equal(1); await dao.stakeAvailability(work1.target, 50, STAKE_DURATION); expect(await work1.stakeCount()).to.equal(2); + expect(await dao.allowance(account1, work1.target)).to.equal(100); }); });