Skip to content

Commit 6aca892

Browse files
authored
Merge pull request from GHSA-p4j4-4h8c-rrc6
fix: rounding error in L2 Curation
2 parents f85b674 + fb5798d commit 6aca892

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

packages/contracts/contracts/curation/Curation.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ contract Curation is CurationV2Storage, GraphUpgradeable {
340340
override
341341
returns (uint256, uint256)
342342
{
343+
// NOTE: We're aware that this function rounds down and tax can be 0 for small amounts
344+
// of tokens but since minimumCurationDeposit is 1 GRT tax will always be greater than 0.
343345
uint256 curationTax = _tokensIn.mul(uint256(curationTaxPercentage)).div(MAX_PPM);
344346
uint256 signalOut = _tokensToSignal(_subgraphDeploymentID, _tokensIn.sub(curationTax));
345347
return (signalOut, curationTax);

packages/contracts/contracts/l2/curation/L2Curation.sol

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,14 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation {
400400
override
401401
returns (uint256, uint256)
402402
{
403-
uint256 curationTax = _tokensIn.mul(uint256(curationTaxPercentage)).div(MAX_PPM);
404-
uint256 signalOut = _tokensToSignal(_subgraphDeploymentID, _tokensIn.sub(curationTax));
403+
// Calculate tokens after tax first, subtract that from the tokens in
404+
// to get the curation tax to avoid rounding down to zero.
405+
uint256 tokensAfterCurationTax = uint256(MAX_PPM)
406+
.sub(curationTaxPercentage)
407+
.mul(_tokensIn)
408+
.div(MAX_PPM);
409+
uint256 curationTax = _tokensIn.sub(tokensAfterCurationTax);
410+
uint256 signalOut = _tokensToSignal(_subgraphDeploymentID, tokensAfterCurationTax);
405411
return (signalOut, curationTax);
406412
}
407413

packages/contracts/test/unit/l2/l2Curation.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,47 @@ describe('L2Curation', () => {
469469
.mint(subgraphDeploymentID, tokensToDeposit, expectedSignal.add(1))
470470
await expect(tx).revertedWith('Slippage protection')
471471
})
472+
473+
it('should pay a minimum of 1 wei GRT in tax when depositing small amounts', async function () {
474+
// Set minimum curation deposit
475+
await contracts.Curation.connect(governor).setMinimumCurationDeposit('1')
476+
477+
// Set curation tax to 1%
478+
await contracts.Curation.connect(governor).setCurationTaxPercentage(10000)
479+
480+
// Deposit a small amount where tax would be less than 1 wei
481+
const tokensToDeposit = '99'
482+
483+
const expectedTokens = '98'
484+
const expectedSignal = '98'
485+
const expectedTax = 1
486+
487+
const tx = contracts.Curation.connect(curator).mint(
488+
subgraphDeploymentID,
489+
tokensToDeposit,
490+
expectedSignal,
491+
)
492+
493+
await expect(tx)
494+
.emit(contracts.Curation, 'Signalled')
495+
.withArgs(
496+
curator.address,
497+
subgraphDeploymentID,
498+
tokensToDeposit,
499+
expectedSignal,
500+
expectedTax,
501+
)
502+
503+
const burnTx = contracts.Curation.connect(curator).burn(
504+
subgraphDeploymentID,
505+
expectedSignal,
506+
expectedTokens,
507+
)
508+
509+
await expect(burnTx)
510+
.emit(contracts.Curation, 'Burned')
511+
.withArgs(curator.address, subgraphDeploymentID, expectedTokens, expectedSignal)
512+
})
472513
})
473514

474515
describe('curate tax free (from GNS)', async function () {

0 commit comments

Comments
 (0)