From bf9299ab5c71e9125cac2122162ff17bf9e4ae57 Mon Sep 17 00:00:00 2001 From: r4bbit <445106+0x-r4bbit@users.noreply.github.com> Date: Thu, 1 May 2025 17:10:23 +0200 Subject: [PATCH] fix(Karma): prevent overflow errors when issuing rewards As described in #206 it's theoretically possible to cause overflows when either Karma is issued via `mint()` or `setReward()` because both functions don't take the supply of the other "domain" into account. This commit fixes this by performing an arithmetic operation on `super.totalSupply()`, `totalDistributorAllocation` and the newly issued `amount`. If there's an overflow, the code will cause an overflow and reverts. This ensure overflows can't happen *after* rewards have been issued. Closes #206 --- .gas-report | 76 ++++++++++++++++++++++++------------------------ .gas-snapshot | 54 ++++++++++++++++++++-------------- src/Karma.sol | 9 ++++++ test/Karma.t.sol | 25 ++++++++++++++++ 4 files changed, 104 insertions(+), 60 deletions(-) diff --git a/.gas-report b/.gas-report index 15b69d0..663ea8a 100644 --- a/.gas-report +++ b/.gas-report @@ -10,7 +10,7 @@ |-------------------------------------------------------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-------------------------------------------------------------------------------------------+-----------------+--------+--------+--------+---------| -| fallback | 746 | 142734 | 190919 | 190943 | 447 | +| fallback | 746 | 135524 | 193312 | 193348 | 498 | ╰-------------------------------------------------------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭-----------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -18,13 +18,13 @@ +===============================================================================================================+ | Deployment Cost | Deployment Size | | | | | |-----------------------------------------------------+-----------------+---------+---------+---------+---------| -| 4734998 | 22941 | | | | | +| 4746226 | 22993 | | | | | |-----------------------------------------------------+-----------------+---------+---------+---------+---------| | | | | | | | |-----------------------------------------------------+-----------------+---------+---------+---------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-----------------------------------------------------+-----------------+---------+---------+---------+---------| -| run | 3956429 | 3956429 | 3956429 | 3956429 | 106 | +| run | 3966846 | 3966846 | 3966846 | 3966846 | 116 | ╰-----------------------------------------------------+-----------------+---------+---------+---------+---------╯ ╭-----------------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -66,7 +66,7 @@ |---------------------------------------------------------+-----------------+-----+--------+-----+---------| | Function Name | Min | Avg | Median | Max | # Calls | |---------------------------------------------------------+-----------------+-----+--------+-----+---------| -| activeNetworkConfig | 455 | 455 | 455 | 455 | 320 | +| activeNetworkConfig | 455 | 455 | 455 | 455 | 340 | ╰---------------------------------------------------------+-----------------+-----+--------+-----+---------╯ ╭---------------------------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -88,7 +88,7 @@ +=====================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------+-----------------+--------+--------+--------+---------| -| 0 | 9823 | | | | | +| 0 | 9875 | | | | | |------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------+-----------------+--------+--------+--------+---------| @@ -96,31 +96,31 @@ |------------------------------+-----------------+--------+--------+--------+---------| | acceptOwnership | 12020 | 12020 | 12020 | 12020 | 1 | |------------------------------+-----------------+--------+--------+--------+---------| -| addRewardDistributor | 2589 | 66851 | 70586 | 70586 | 128 | +| addRewardDistributor | 2589 | 65692 | 70586 | 70586 | 150 | |------------------------------+-----------------+--------+--------+--------+---------| -| allowance | 482 | 482 | 482 | 482 | 2 | +| allowance | 482 | 482 | 482 | 482 | 3 | |------------------------------+-----------------+--------+--------+--------+---------| -| approve | 419 | 419 | 419 | 419 | 2 | +| approve | 419 | 419 | 419 | 419 | 3 | |------------------------------+-----------------+--------+--------+--------+---------| -| balanceOf | 10019 | 13685 | 10019 | 21019 | 6 | +| balanceOf | 10019 | 13685 | 10019 | 21019 | 9 | |------------------------------+-----------------+--------+--------+--------+---------| -| getRewardDistributors | 1140 | 3384 | 3384 | 5628 | 4 | +| getRewardDistributors | 1140 | 3384 | 3384 | 5628 | 6 | |------------------------------+-----------------+--------+--------+--------+---------| -| initialize | 95872 | 95872 | 95872 | 95872 | 106 | +| initialize | 95872 | 95872 | 95872 | 95872 | 116 | |------------------------------+-----------------+--------+--------+--------+---------| -| mint | 2632 | 37252 | 48792 | 48792 | 8 | +| mint | 2632 | 37628 | 51197 | 51197 | 14 | |------------------------------+-----------------+--------+--------+--------+---------| | owner | 363 | 1029 | 363 | 2363 | 3 | |------------------------------+-----------------+--------+--------+--------+---------| -| removeRewardDistributor | 2632 | 12148 | 4824 | 28990 | 6 | +| removeRewardDistributor | 2632 | 12148 | 4824 | 28990 | 9 | |------------------------------+-----------------+--------+--------+--------+---------| -| setReward | 22021 | 157523 | 164219 | 164219 | 276 | +| setReward | 9233 | 156626 | 166624 | 166624 | 284 | |------------------------------+-----------------+--------+--------+--------+---------| -| totalSupply | 3545 | 8211 | 9545 | 11545 | 6 | +| totalSupply | 3545 | 7545 | 9545 | 9545 | 9 | |------------------------------+-----------------+--------+--------+--------+---------| -| transfer | 417 | 417 | 417 | 417 | 2 | +| transfer | 417 | 417 | 417 | 417 | 3 | |------------------------------+-----------------+--------+--------+--------+---------| -| transferFrom | 511 | 511 | 511 | 511 | 2 | +| transferFrom | 511 | 511 | 511 | 511 | 3 | |------------------------------+-----------------+--------+--------+--------+---------| | transferOwnership | 26328 | 26328 | 26328 | 26328 | 1 | ╰------------------------------+-----------------+--------+--------+--------+---------╯ @@ -184,7 +184,7 @@ |--------------------------------------------+-----------------+--------+--------+--------+---------| | getAccountVaults | 5230 | 5230 | 5230 | 5230 | 4 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| getVault | 1823 | 6596 | 1823 | 15823 | 4182 | +| getVault | 1823 | 6622 | 1823 | 15823 | 4183 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | initialize | 92752 | 92752 | 92752 | 92752 | 93 | |--------------------------------------------+-----------------+--------+--------+--------+---------| @@ -192,7 +192,7 @@ |--------------------------------------------+-----------------+--------+--------+--------+---------| | leave | 88837 | 88837 | 88837 | 88837 | 1 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| lock | 7040 | 42498 | 45950 | 84893 | 1034 | +| lock | 7040 | 42317 | 45950 | 84893 | 1034 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | migrateToVault | 9294 | 51723 | 16883 | 163832 | 4 | |--------------------------------------------+-----------------+--------+--------+--------+---------| @@ -210,7 +210,7 @@ |--------------------------------------------+-----------------+--------+--------+--------+---------| | rewardStartTime | 364 | 1364 | 1364 | 2364 | 2 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| rewardsBalanceOf | 2295 | 3505 | 3908 | 6295 | 268 | +| rewardsBalanceOf | 2295 | 3499 | 3908 | 6295 | 268 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | rewardsBalanceOfAccount | 10220 | 10220 | 10220 | 10220 | 1 | |--------------------------------------------+-----------------+--------+--------+--------+---------| @@ -220,33 +220,33 @@ |--------------------------------------------+-----------------+--------+--------+--------+---------| | setTrustedCodehash | 24238 | 24238 | 24238 | 24238 | 93 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| stake | 2639 | 129085 | 59967 | 225838 | 2668 | +| stake | 2639 | 128634 | 59967 | 225838 | 2668 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | stakedBalanceOf | 2622 | 2622 | 2622 | 2622 | 1 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | totalMP | 805 | 1257 | 1257 | 1710 | 6 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| totalMPAccrued | 385 | 1070 | 385 | 2385 | 4162 | +| totalMPAccrued | 385 | 1073 | 385 | 2385 | 4163 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| totalMPStaked | 429 | 1113 | 429 | 2429 | 4165 | +| totalMPStaked | 429 | 1117 | 429 | 2429 | 4166 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| totalMaxMP | 407 | 1092 | 407 | 2407 | 4162 | +| totalMaxMP | 407 | 1095 | 407 | 2407 | 4163 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | totalRewardsAccrued | 407 | 407 | 407 | 407 | 3 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| totalRewardsSupply | 998 | 1627 | 1792 | 6737 | 290 | +| totalRewardsSupply | 998 | 1624 | 1792 | 6737 | 290 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | totalShares | 597 | 597 | 597 | 597 | 6 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| totalStaked | 408 | 1092 | 408 | 2408 | 4169 | +| totalStaked | 408 | 1095 | 408 | 2408 | 4170 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| unstake | 38969 | 41472 | 38995 | 75006 | 269 | +| unstake | 38969 | 41385 | 38995 | 75006 | 269 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | updateAccount | 347677 | 347677 | 347677 | 347677 | 1 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | updateGlobalState | 15820 | 25876 | 29230 | 29230 | 8 | |--------------------------------------------+-----------------+--------+--------+--------+---------| -| updateVault | 31948 | 34054 | 31948 | 110579 | 1024 | +| updateVault | 31948 | 33943 | 31948 | 110579 | 1025 | |--------------------------------------------+-----------------+--------+--------+--------+---------| | upgradeTo | 10279 | 10895 | 10279 | 12745 | 4 | |--------------------------------------------+-----------------+--------+--------+--------+---------| @@ -274,7 +274,7 @@ |----------------------------------------+-----------------+--------+--------+--------+---------| | leave | 12161 | 124868 | 66517 | 354279 | 4 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| lock | 12091 | 57919 | 61416 | 100356 | 1035 | +| lock | 12091 | 57739 | 61416 | 100356 | 1035 | |----------------------------------------+-----------------+--------+--------+--------+---------| | migrateToVault | 24782 | 75606 | 32371 | 212902 | 4 | |----------------------------------------+-----------------+--------+--------+--------+---------| @@ -282,13 +282,13 @@ |----------------------------------------+-----------------+--------+--------+--------+---------| | register | 12718 | 78090 | 78644 | 78644 | 366 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| stake | 12071 | 163003 | 75460 | 281406 | 2669 | +| stake | 12071 | 162433 | 75460 | 281406 | 2669 | |----------------------------------------+-----------------+--------+--------+--------+---------| | stakeManager | 369 | 369 | 369 | 369 | 365 | |----------------------------------------+-----------------+--------+--------+--------+---------| | trustStakeManager | 7580 | 7580 | 7580 | 7580 | 1 | |----------------------------------------+-----------------+--------+--------+--------+---------| -| unstake | 12048 | 57787 | 54438 | 106028 | 270 | +| unstake | 12048 | 57701 | 54438 | 106028 | 270 | |----------------------------------------+-----------------+--------+--------+--------+---------| | withdraw | 20733 | 20733 | 20733 | 20733 | 1 | ╰----------------------------------------+-----------------+--------+--------+--------+---------╯ @@ -304,7 +304,7 @@ |----------------------------------------------------+-----------------+------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------------------+-----------------+------+--------+--------+---------| -| fallback | 708 | 6326 | 2301 | 374054 | 23163 | +| fallback | 708 | 6331 | 2301 | 374054 | 23169 | |----------------------------------------------------+-----------------+------+--------+--------+---------| | implementation | 346 | 2345 | 2346 | 2346 | 4349 | ╰----------------------------------------------------+-----------------+------+--------+--------+---------╯ @@ -376,13 +376,13 @@ |-------------------------------------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-------------------------------------------------------------------+-----------------+-------+--------+-------+---------| -| rewardsBalanceOfAccount | 549 | 1882 | 2549 | 2549 | 12 | +| rewardsBalanceOfAccount | 549 | 1882 | 2549 | 2549 | 18 | |-------------------------------------------------------------------+-----------------+-------+--------+-------+---------| -| setTotalKarmaShares | 43589 | 43589 | 43589 | 43589 | 12 | +| setTotalKarmaShares | 43589 | 43589 | 43589 | 43589 | 18 | |-------------------------------------------------------------------+-----------------+-------+--------+-------+---------| -| setUserKarmaShare | 44194 | 44194 | 44194 | 44194 | 4 | +| setUserKarmaShare | 44194 | 44194 | 44194 | 44194 | 6 | |-------------------------------------------------------------------+-----------------+-------+--------+-------+---------| -| totalRewardsSupply | 324 | 324 | 324 | 324 | 12 | +| totalRewardsSupply | 324 | 324 | 324 | 324 | 18 | ╰-------------------------------------------------------------------+-----------------+-------+--------+-------+---------╯ ╭---------------------------------------------------------------------+-----------------+-------+--------+-------+---------╮ @@ -410,9 +410,9 @@ |---------------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |---------------------------------------------+-----------------+-------+--------+-------+---------| -| approve | 29075 | 31502 | 29183 | 46259 | 2668 | +| approve | 29075 | 31501 | 29183 | 46259 | 2668 | |---------------------------------------------+-----------------+-------+--------+-------+---------| -| balanceOf | 561 | 1351 | 561 | 2561 | 4956 | +| balanceOf | 561 | 1354 | 561 | 2561 | 4957 | |---------------------------------------------+-----------------+-------+--------+-------+---------| | mint | 33964 | 37136 | 34072 | 68248 | 2677 | ╰---------------------------------------------+-----------------+-------+--------+-------+---------╯ diff --git a/.gas-snapshot b/.gas-snapshot index bdfca93..9dbfcd3 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -6,15 +6,15 @@ EmergencyExitTest:test_EmergencyExitToAlternateAddress() (gas: 432421) EmergencyExitTest:test_EmergencyExitWithLock() (gas: 430501) EmergencyExitTest:test_EmergencyExitWithRewards() (gas: 418391) EmergencyExitTest:test_OnlyOwnerCanEnableEmergencyMode() (gas: 39176) -FuzzTests:testFuzz_AccrueMP(uint128,uint64,uint64) (runs: 1000, μ: 373456, ~: 342655) -FuzzTests:testFuzz_AccrueMP_Relock(uint128,uint64,uint64,uint64) (runs: 1000, μ: 472165, ~: 444746) -FuzzTests:testFuzz_EmergencyExit(uint256,uint256) (runs: 1000, μ: 495256, ~: 486543) -FuzzTests:testFuzz_Lock(uint256,uint64) (runs: 1000, μ: 726736, ~: 725709) -FuzzTests:testFuzz_Relock(uint256,uint64,uint64) (runs: 1000, μ: 384630, ~: 362893) -FuzzTests:testFuzz_Rewards(uint256,uint256,uint256,uint16,uint16) (runs: 1000, μ: 594630, ~: 595934) -FuzzTests:testFuzz_Stake(uint256,uint64) (runs: 1000, μ: 288633, ~: 260818) -FuzzTests:testFuzz_Unstake(uint128,uint64,uint16,uint128) (runs: 1000, μ: 476844, ~: 448237) -FuzzTests:testFuzz_UpdateVault(uint128,uint64,uint64) (runs: 1000, μ: 373479, ~: 342678) +FuzzTests:testFuzz_AccrueMP(uint128,uint64,uint64) (runs: 1000, μ: 372282, ~: 342651) +FuzzTests:testFuzz_AccrueMP_Relock(uint128,uint64,uint64,uint64) (runs: 1000, μ: 472264, ~: 444743) +FuzzTests:testFuzz_EmergencyExit(uint256,uint256) (runs: 1000, μ: 495376, ~: 486543) +FuzzTests:testFuzz_Lock(uint256,uint64) (runs: 1000, μ: 726274, ~: 725709) +FuzzTests:testFuzz_Relock(uint256,uint64,uint64) (runs: 1000, μ: 381860, ~: 362893) +FuzzTests:testFuzz_Rewards(uint256,uint256,uint256,uint16,uint16) (runs: 1000, μ: 597041, ~: 598339) +FuzzTests:testFuzz_Stake(uint256,uint64) (runs: 1000, μ: 288027, ~: 260835) +FuzzTests:testFuzz_Unstake(uint128,uint64,uint16,uint128) (runs: 1000, μ: 475649, ~: 448228) +FuzzTests:testFuzz_UpdateVault(uint128,uint64,uint64) (runs: 1000, μ: 372305, ~: 342674) IntegrationTest:testStakeFoo() (gas: 1362727) KarmaNFTTest:testApproveNotAllowed() (gas: 10507) KarmaNFTTest:testGetApproved() (gas: 10531) @@ -27,27 +27,27 @@ KarmaNFTTest:testSetMetadataGeneratorRevert() (gas: 1006937) KarmaNFTTest:testTokenURI() (gas: 1105935) KarmaNFTTest:testTransferNotAllowed() (gas: 10701) KarmaOwnershipTest:testAddKarmaDistributorOnlyOwner() (gas: 364768) -KarmaOwnershipTest:testBalanceOf() (gas: 423830) +KarmaOwnershipTest:testBalanceOf() (gas: 431045) KarmaOwnershipTest:testBalanceOfWithNoSystemTotalKarma() (gas: 49479) KarmaOwnershipTest:testInitialOwner() (gas: 17601) -KarmaOwnershipTest:testMintOnlyOwner() (gas: 371195) +KarmaOwnershipTest:testMintOnlyOwner() (gas: 376410) KarmaOwnershipTest:testOwnershipTransfer() (gas: 98047) KarmaOwnershipTest:testRemoveKarmaDistributorOnlyOwner() (gas: 88820) KarmaOwnershipTest:testRemoveUnknownKarmaDistributor() (gas: 41398) -KarmaOwnershipTest:testTotalSupply() (gas: 331725) +KarmaOwnershipTest:testTotalSupply() (gas: 338940) KarmaOwnershipTest:testTransfersNotAllowed() (gas: 40196) KarmaTest:testAddKarmaDistributorOnlyOwner() (gas: 364768) -KarmaTest:testBalanceOf() (gas: 423830) +KarmaTest:testBalanceOf() (gas: 431045) KarmaTest:testBalanceOfWithNoSystemTotalKarma() (gas: 49545) -KarmaTest:testMintOnlyOwner() (gas: 371195) +KarmaTest:testMintOnlyOwner() (gas: 376410) KarmaTest:testRemoveKarmaDistributorOnlyOwner() (gas: 88798) KarmaTest:testRemoveUnknownKarmaDistributor() (gas: 41398) -KarmaTest:testTotalSupply() (gas: 331725) +KarmaTest:testTotalSupply() (gas: 338940) KarmaTest:testTransfersNotAllowed() (gas: 40241) LeaveTest:test_LeaveShouldProperlyUpdateAccounting() (gas: 9617526) LeaveTest:test_RevertWhenStakeManagerIsTrusted() (gas: 332331) LeaveTest:test_TrustNewStakeManager() (gas: 9673268) -LockTest:test_LockFailsWithInvalidPeriod(uint256) (runs: 1000, μ: 382886, ~: 382908) +LockTest:test_LockFailsWithInvalidPeriod(uint256) (runs: 1000, μ: 382883, ~: 382908) LockTest:test_LockFailsWithNoStake() (gas: 88865) LockTest:test_LockFailsWithZero() (gas: 342393) LockTest:test_LockMultipleTimesExceedMaxLock() (gas: 624582) @@ -68,12 +68,22 @@ NFTMetadataGeneratorSVGTest:testSetImageStringsRevert() (gas: 35891) NFTMetadataGeneratorURLTest:testGenerateMetadata() (gas: 108341) NFTMetadataGeneratorURLTest:testSetBaseURL() (gas: 50631) NFTMetadataGeneratorURLTest:testSetBaseURLRevert() (gas: 36066) -StakeManager_RewardsTest:testRewardsBalanceOf() (gas: 1274873) -StakeManager_RewardsTest:testSetRewards() (gas: 224614) -StakeManager_RewardsTest:testSetRewards_RevertsBadAmount() (gas: 61280) -StakeManager_RewardsTest:testSetRewards_RevertsBadDuration() (gas: 101038) +OverflowTest:testAddKarmaDistributorOnlyOwner() (gas: 364746) +OverflowTest:testBalanceOf() (gas: 431045) +OverflowTest:testBalanceOfWithNoSystemTotalKarma() (gas: 49545) +OverflowTest:testMintOnlyOwner() (gas: 376410) +OverflowTest:testRemoveKarmaDistributorOnlyOwner() (gas: 88798) +OverflowTest:testRemoveUnknownKarmaDistributor() (gas: 41410) +OverflowTest:testTotalSupply() (gas: 338940) +OverflowTest:testTransfersNotAllowed() (gas: 40241) +OverflowTest:test_RevertWhen_MintingCausesOverflow() (gas: 129363) +OverflowTest:test_RevertWhen_SettingRewardCausesOverflow() (gas: 127641) +StakeManager_RewardsTest:testRewardsBalanceOf() (gas: 1279683) +StakeManager_RewardsTest:testSetRewards() (gas: 227019) +StakeManager_RewardsTest:testSetRewards_RevertsBadAmount() (gas: 63685) +StakeManager_RewardsTest:testSetRewards_RevertsBadDuration() (gas: 103443) StakeManager_RewardsTest:testSetRewards_RevertsNotAuthorized() (gas: 39367) -StakeManager_RewardsTest:testTotalRewardsSupply() (gas: 740407) +StakeManager_RewardsTest:testTotalRewardsSupply() (gas: 745217) StakeTest:test_StakeMultipleAccounts() (gas: 555080) StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 563572) StakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 942163) @@ -119,7 +129,7 @@ UnstakeTest:test_UnstakeOneAccount() (gas: 543645) UnstakeTest:test_UnstakeOneAccountAndAccruedMP() (gas: 543156) UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 467580) UnstakeTest:test_UnstakeOneAccountWithLockUpAndAccruedMP() (gas: 560332) -UpdateVaultTest:test_UpdateAccount() (gas: 2391077) +UpdateVaultTest:test_UpdateAccount() (gas: 2393482) UpgradeTest:test_RevertWhenNotOwner() (gas: 3562509) UpgradeTest:test_UpgradeStakeManager() (gas: 9509435) VaultRegistrationTest:test_VaultRegistration() (gas: 63138) diff --git a/src/Karma.sol b/src/Karma.sol index 0967718..8e1a568 100644 --- a/src/Karma.sol +++ b/src/Karma.sol @@ -101,8 +101,11 @@ contract Karma is Initializable, ERC20Upgradeable, Ownable2StepUpgradeable, UUPS revert Karma__UnknownDistributor(); } + _overflowCheck(amount); + rewardDistributorAllocations[rewardsDistributor] += amount; totalDistributorAllocation += amount; + IRewardDistributor(rewardsDistributor).setReward(amount, duration); } @@ -114,6 +117,7 @@ contract Karma is Initializable, ERC20Upgradeable, Ownable2StepUpgradeable, UUPS * @param amount The amount of tokens to mint. */ function mint(address account, uint256 amount) external onlyOwner { + _overflowCheck(amount); _mint(account, amount); } @@ -166,6 +170,11 @@ contract Karma is Initializable, ERC20Upgradeable, Ownable2StepUpgradeable, UUPS _checkOwner(); } + function _overflowCheck(uint256 amount) internal view { + // This will revert if `amount` overflows the total supply + super.totalSupply() + totalDistributorAllocation + amount; + } + /*////////////////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ diff --git a/test/Karma.t.sol b/test/Karma.t.sol index 6832b15..29883b0 100644 --- a/test/Karma.t.sol +++ b/test/Karma.t.sol @@ -167,3 +167,28 @@ contract KarmaOwnershipTest is KarmaTest { assertEq(karma.owner(), alice); } } + +contract OverflowTest is KarmaTest { + function setUp() public override { + super.setUp(); + } + + function test_RevertWhen_MintingCausesOverflow() public { + vm.startBroadcast(owner); + karma.setReward(address(distributor1), type(uint256).max, 1000); + vm.stopBroadcast(); + + vm.prank(owner); + vm.expectRevert(); + karma.mint(owner, 1e18); + } + + function test_RevertWhen_SettingRewardCausesOverflow() public { + vm.prank(owner); + karma.mint(owner, type(uint256).max); + + vm.prank(owner); + vm.expectRevert(); + karma.setReward(address(distributor1), 1e18, 1000); + } +}