As of 3 Nov 2026, Vanilla has 1 audit report on Trustblock, by CertiK, dated 2 Aug 2023. That report lists no open critical findings.
Record last updated . It holds audits, findings and contracts up to Nov 2026, and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Vanilla Contract | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 1 | 0 |
| Medium | 0 | 0 | 0 |
| Low | 4 | 0 | 17 |
`rewardAmount()` is supposed to calculate the reward claimable by `account`. However, `msg.sender` is used as argument for `getBoostedAmount()`.
Open the report```sol=144 require(beforeUnlockBlock < afterUnlockBlock, "Vanilla: period"); ``` `increaseLockPeriod()` checks if block number is increasing, however, it's more reasonable to check if stage is.
Open the report`Reinforcer` always uses only one random word in `fulfillRandomWords()`. The `numWords` state field is redundant.
Open the reportThe argument `rewardPool` of `Distributor.NewRewardPool` event is in fact `depositToken`. The function `Distributor.rewardPerPeriod()` in fact returns `rewardSince`.
Open the report`Vanilla721.mint()` directly checks if `!ticket.pendingTokenIds(tokenId)` and then does `ticket.setPendingTokenIds(tokenId)`. However, it is reasonable to perform this check directly in `Ticket.setPendingTokenIds()` to hide the implementation details.
Open the reportPerforming integer division before multiplication truncates the low bits, losing the precision of calculation. ```solidity=220 uint rewardPerPool = rewardPerPeriod(poolState.lastUpdatedBlock) * poolState.rewardWeight / totalRewardWeight; ``` ```solidity=224 poolState.rewardRate += safe144(rewardPerPool * 1e18 / poolState.totalDeposit); ``` --- ```solidity=53 newMaxRewardWeights[i] = safe112( maxNumber / subtractedPoint * reinforceVanillaFee ); ```
Open the reportOne or more parameters with `memory` data location are never modified in their functions and those functions are never called internally within the contract. Thus, their data location can be changed to `calldata` to avoid the gas consumption copying from calldata to memory. ```solidity=53 function submitTransaction( ``` `submitTransaction` has memory location parameters: `signature`, `data`.
Open the report`Distributor.constructor()` and `setTokenPerBlock()` don't check if `newStartBlock` and `newTokenPerBlock` are valid. `Locker.setBoostDivider()` doesn't check if `boostDivider` is non-zero.
Open the reportThere is no upper limit restricting parameter of `setFeePercentage()`, potentially enabling up to 100% of fees on transactions.
Open the report`Locker.increaseLockPeriod()` is not protected from reentrancy, however, does external calls and updates `accountState.rewardDebt` after that.
Open the report`Vanilla.setAdmin()` sets the new admin without guaranteeing they are able to actuate transactions on-chain.
Open the reportType casting refers to changing the variable of one data type into another. The code contains an unsafe cast between integer types, which may result in unexpected truncation or sign flipping of the value. ```solidity=100 uint32(startBlock > block.number ? startBlock : block.number), ``` `startBlock` is declared as `uint`. If it was initialized bigger than `type(uint32).max`, the result of `addRewardPool()` is unexpected. --- ```solidity=260 return blockNumber < startBlock ? uint16(passedStage) : uint16((blockNumber - startBlock) / blockPeriod + passedStage); ``` `blockNumber` is provided by the user as `uint`. The result of type truncation is unexpected. --- ```solidity=23 int i = int(to); ``` `BIT` uses unsafe type casting.
Open the report`BIT.safe16()`, `Distributor.safe112()`, `Distributor.blocksPerYear` are never used.
Open the reportThe event `Reinforcer.NewReinforceLinkFee` is never used.
Open the reportIt is not recommended to use Solidity's `transfer()` and `send()` functions for transferring native tokens. Those functions forward only a fixed amount of gas (2300 specifically) and the receiving contracts may run out of gas before finishing the transfer. Also, EVM instructions' gas costs may increase in the future. Thus, some contracts that can receive now may stop working in the future due to the gas limitation. ```solidity=198 payable(msg.sender).transfer(amount); ``` - `Distributor.withdraw` uses `transfer()`.
Open the reportDifferent magic numbers are used as-is in code.
Open the reportThe linked variables assigned in the constructor can be declared as `immutable`. Immutable state variables can be assigned during contract creation but will remain constant throughout the lifetime of a deployed contract. A big advantage of immutable variables is that reading them is significantly cheaper than reading from regular state variables since they will not be stored in storage.
Open the reportThe reports name a repository or files. Open a report to see its scope.
Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.
Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="bum-1"></div></body>
Paste the code where the label should appear. It uses no API credit and updates by itself.
Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us