diff --git a/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol b/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol index 349415283..8248f81c9 100644 --- a/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol +++ b/packages/contracts/contracts/rewards/SubgraphAvailabilityManager.sol @@ -197,11 +197,15 @@ contract SubgraphAvailabilityManager is Governed { ) private { uint256 timestamp = block.timestamp; - // corresponding votes based on _deny for a subgraph deployment - uint256[NUM_ORACLES] storage lastVoteForSubgraph = _deny - ? lastDenyVote[currentNonce][_subgraphDeploymentID] - : lastAllowVote[currentNonce][_subgraphDeploymentID]; - lastVoteForSubgraph[_oracleIndex] = timestamp; + if (_deny) { + lastDenyVote[currentNonce][_subgraphDeploymentID][_oracleIndex] = timestamp; + // clear opposite vote for a subgraph deployment if it exists + lastAllowVote[currentNonce][_subgraphDeploymentID][_oracleIndex] = 0; + } else { + lastAllowVote[currentNonce][_subgraphDeploymentID][_oracleIndex] = timestamp; + // clear opposite vote for a subgraph deployment if it exists + lastDenyVote[currentNonce][_subgraphDeploymentID][_oracleIndex] = 0; + } emit OracleVote(_subgraphDeploymentID, _deny, _oracleIndex, timestamp); diff --git a/packages/contracts/test/rewards/subgraphAvailability.test.ts b/packages/contracts/test/rewards/subgraphAvailability.test.ts index 0dbbd1abb..1f04a3bbc 100644 --- a/packages/contracts/test/rewards/subgraphAvailability.test.ts +++ b/packages/contracts/test/rewards/subgraphAvailability.test.ts @@ -329,6 +329,31 @@ describe('SubgraphAvailabilityManager', () => { // previous votes are no longer valid expect(await rewardsManager.isDenied(subgraphDeploymentID1)).to.be.false }) + + it('clears opposite vote when voting', async () => { + const denied = true + await subgraphAvailabilityManager.connect(oracleOne).vote(subgraphDeploymentID1, denied, 0) + await subgraphAvailabilityManager.connect(oracleTwo).vote(subgraphDeploymentID1, denied, 1) + await subgraphAvailabilityManager.connect(oracleThree).vote(subgraphDeploymentID1, denied, 2) + + // 3/5 oracles vote denied = true so subgraph is denied + expect(await rewardsManager.isDenied(subgraphDeploymentID1)).to.be.true + + // oracleOne changes its vote to denied = false + await subgraphAvailabilityManager.connect(oracleOne).vote(subgraphDeploymentID1, false, 0) + + // last deny vote should be 0 for oracleOne + expect( + await subgraphAvailabilityManager.lastDenyVote(0, subgraphDeploymentID1, 0), + ).to.be.equal(0) + + // executionThreshold isn't met now since oracleOne changed its vote + expect(await subgraphAvailabilityManager.checkVotes(subgraphDeploymentID1, denied)).to.be + .false + + // subgraph is still denied in rewards manager because only one oracle changed its vote + expect(await rewardsManager.isDenied(subgraphDeploymentID1)).to.be.true + }) }) describe('vote many', async () => {