Platform: Code4rena
Start Date: 20/09/2022
Pot Size: $30,000 USDC
Total HM: 12
Participants: 198
Period: 3 days
Judge: 0xean
Total Solo HM: 2
Id: 164
League: ETH
Rank: 157/198
Findings: 2
Award: $9.83
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Czar102
Also found by: 0xDecorativePineapple, 0xNazgul, 0xSky, 0xbepresent, 0xmatt, Atarpara, Bahurum, DimitarDimitrov, Franfran, GimelSec, JGcarv, JLevick, Junnon, OptimismSec, Rolezn, Ruhum, Soosh, Tomo, Trust, __141345__, adriro, ajtra, bin2chen, cRat1st0s, cccz, cryptonue, d3e4, innertia, jag, joestakey, neumo, obront, pashov, pauliax, pcarranzav, peanuts, rajatbeladiya, rbserver, reassor, seyni, wagmi, zzykxx, zzzitron
0.7375 USDC - $0.74
VariableSupplyERC20Token allows to set a "maxSupply_" during construction which should set the maximum amount that an admin can mint.
@param maxSupply_ - What's the maximum supply. The contract won't allow minting over this amount. Set to 0 for no limit.
This variable is later used in the mint()
function to check if there's enough amount left to mint more tokens. However, if the minted amount(s) (ie one or more calls to mint) reduce this amount to 0, then the behavior changes to the "no limit" mode which will allow any amount to be minted later on.
Giving this a medium risk since this function is admin restricted.
maxSupply > 0
.Here's a small test to reproduce the issue:
describe("VariableSupplyERC20Token", async function () { it("should not mint more than max supply", async () => { const [admin, bob, alice] = await ethers.getSigners(); const maxSupply = 100; const initialSupply = 0; const VariableSupplyERC20Token = await ethers.getContractFactory("VariableSupplyERC20Token", admin); const token = await VariableSupplyERC20Token.deploy("Broken", "BRO", initialSupply, maxSupply); await token.deployed(); expect(await token.isAdmin(admin.address)).to.be.true; // we mint so that mintableSupply is reduced to exactly 0, which resets the // "max supply" behaviour and allows to mint any amount await (await token.mint(bob.address, maxSupply / 2)).wait(); await (await token.mint(bob.address, maxSupply / 2)).wait(); await expect(token.mint(alice.address, 999)).to.be.revertedWith("INVALID_AMOUNT"); }); });
Keep track of the "no limit" mode in a separate variable instead of using the logic of mintableSupply == 0
.
#0 - 0xean
2022-09-23T23:51:34Z
dupe of #3
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x040, 0x1f8b, 0x4non, 0x85102, 0xA5DF, 0xDanielC, 0xNazgul, 0xSmartContract, 0xbepresent, 0xc0ffEE, 0xsam, 2997ms, AkshaySrivastav, Amithuddar, Atarpara, Aymen0909, B2, Bnke0x0, CertoraInc, Chom, ChristianKuri, CodingNameKiki, Deivitto, Diana, DimitarDimitrov, Diraco, Funen, JC, JLevick, JohnSmith, Junnon, KIntern_NA, Lambda, MasterCookie, Matin, Noah3o6, Ocean_Sky, OptimismSec, RaymondFam, Respx, ReyAdmirado, RockingMiles, Rohan16, Rolezn, Ruhum, Saintcode_, Satyam_Sharma, Sm4rty, SnowMan, SooYa, Sta1400, StevenL, Tadashi, Tagir2003, TomJ, Tomio, Tomo, V_B, Waze, WilliamAmbrozic, Yiko, __141345__, a12jmx, adriro, ajtra, ak1, async, aysha, beardofginger, bobirichman, brgltd, bulej93, c3phas, carrotsmuggler, caventa, ch0bu, cryptostellar5, cryptphi, csanuragjain, d3e4, delfin454000, dharma09, djxploit, durianSausage, eighty, emrekocak, erictee, exd0tpy, fatherOfBlocks, francoHacker, gianganhnguyen, gogo, got_targ, hxzy, ignacio, ikbkln, imare, indijanc, jag, jpserrat, karanctf, ladboy233, leosathya, lucacez, lukris02, m9800, malinariy, martin, medikko, mics, millersplanet, mrpathfindr, nalus, natzuu, neko_nyaa, oyc_109, pauliax, peanuts, pedroais, peiw, pfapostol, prasantgupta52, rbserver, ret2basic, rokinot, rotcivegaf, rvierdiiev, sach1r0, samruna, seyni, slowmoses, subtle77, supernova, tgolding55, tibthecat, tnevler, w0Lfrum, yaemsobak, zishansami
9.086 USDC - $9.09
finalVestedAmount
in revokeClaim
finalVestedAmount
can be simplified to the sum of linear + cliff amounts:
uint112 finalVestAmt = _claim.linearVestAmount + _claim.cliffAmount;
Since revokeClaim
operates on active claims, the final vested amount should be equivalent to adding both amounts.
Since this is only usage of finalVestedAmount
the function can be removed.
https://github.com/code-423n4/2022-09-vtvl/blob/main/contracts/VTVLVesting.sol#L422