CertiK reviewed Beincom (Beincom - Audit 3) on 19 Mar 2025: 20 findings, 0 critical; 12 marked fixed, 6 acknowledged, 2 open.
Report hosted on skynet.certik.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 4 | 0 |
| Medium | 0 | 2 | 3 |
| Low | 2 | 0 | 9 |
The `BicTokenPaymaster` contract includes a blocking feature designed to prevent blocked addresses from sending tokens. This is implemented through the `isBlocked` mapping and enforced in the `_validateBeforeTransfer` function: ```solidity=538 function _validateBeforeTransfer(address from) internal view { if (paused() || isBlocked[from]) { revert BICValidateBeforeTransfer(from); } } ``` However, this blocking mechanism does not prevent the blocked address from receiving tokens. This could result in tokens accumulating at a blocked address, potentially becoming stuck.
The `BicTokenPaymaster` contract allows addresses to be both blocked (`isBlocked`) from transferring tokens and excluded from fees (`isExcluded`). However, the current implementation does not prevent an address from being both blocked and fee-excluded simultaneously. In such a scenario, a blocked address can still transfer tokens without paying any fees, which undermines the intended restriction of blocking addresses.
In the `BicVesting` contract, the calculation `maxRewardStacks = DENOMINATOR / redeemRateNumber` can result in `maxRewardStacks` being zero if `redeemRateNumber` exceeds `DENOMINATOR` (e.g., `redeemRateNumber > 10,000`). A zero value for `maxRewardStacks` leads to incorrect end time computations and can cause the vesting release functions to revert, preventing beneficiaries from claiming their tokens.
If an event is not indexed in a smart contract, it means that the event's parameters are not tagged with the `indexed` keyword. This has implications for how the event data can be searched and filtered when looking through blockchain logs. Without indexing, the event will still emit the data as part of the transaction log, but users won't be able to query for these events using the parameters. They'll have to retrieve the entire set of logs and manually sift through them to find events with the specific data. This can be less efficient and more time-consuming, especially on a blockchain with a high volume of transactions and events.
In `TokenSingletonPaymaster`, the event emitted by the function `setOracle()` use the new oracle address for the old oracle address and the new oracle address parameter: ```solidity function setOracle(address _oracle) external onlyOwner { oracle = _oracle; // oracle is now the same address as _oracle emit SetOracle(oracle, _oracle, msg.sender); // this is equivalent to SetOracle(_oracle, _oracle, ... } ```
There should always be events emitted in the sensitive functions that are controlled by centralization roles.
The `_setPrePublicRound()` function allows setting `PrePublic` rounds without performing necessary validations on the provided parameters. Specifically: 1. There is no check to ensure `startTime` is less than `endTime`. This could result in invalid configurations where the round's start time is after its end time. 2. No validation is performed on other variables, such as `coolDown` or `maxAmountPerBuy`, which may lead to inconsistent or unexpected behavior. This lack of validation could result in the creation of invalid pre-public rounds, potentially leading to failures when users attempt to participate in the pre-public sale.
In `setLiquidityFee()`: ```solidity=200 require(min >= 0 && min <= max && max <= 5000, "B: invalid values"); ``` `min` being a `uint256`, it cannot be lower than zero, therefore `min >= 0` is always true. In `setLFReduction()`: ```solidity=212 if (_LFReduction <= 0) { ``` `_LFReduction` is a `uint256`, it cannot be lower than zero, therefore `_LFReduction <= 0` is equivalent to `_LFReduction == 0`
The `BicTokenPaymaster` contract is utilizing Solidity version `^0.8.23` and OpenZeppelin Contracts version `v5`. Solidity `0.8.x` arithmetic operations include built-in overflow and underflow checks, eliminating the necessity for the `SafeMath` library. Additionally, OpenZeppelin Contracts version `v5` removed the `SafeMath` library. Despite these advancements, the protocol has manually integrated the `SafeMath` library, which is now redundant.
In `TokenSingletonPaymaster`'s constructor, `_singers` is supposed to be `_signers`.
The contract `BicTokenPaymaster` defines a time period as `LFPeriod = 60 * 60 * 24 * 30` to represent 30 days in seconds. While this approach works, Solidity provides built-in time units that allow developers to define durations more clearly and concisely. For instance, the same time period can be written as `30 days`, improving code readability and reducing potential errors from manual calculations.
The contract's vesting logic has several issues related to the calculation of the vesting end time and the handling of token amounts: 1. **End Time Adjustment**: The vesting period's `end` time is adjusted when `DENOMINATOR % redeemRate > 0` by adding one `durationSeconds`. However, this adjustment can lead to incorrect final vesting periods or unused tokens. Specifically: - If `redeemRate` is not a divisor of `DENOMINATOR`, the last vesting period may allocate more tokens than intended or revert if the contract does not hold sufficient tokens. - If additional tokens are sent to the contract after initialization, they can be incorrectly distributed during the final vesting period. 2. **Over-allocation of Tokens**: When `block.timestamp == end`, the `_amountPerDuration` logic may still allocate tokens for another full period rather than only the remaining tokens. This can result in either: - More tokens than planned are distributed if the contract holds extra tokens. - The transaction fails if the contract does not hold enough tokens to meet the overestimated allocation.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (5)
1,044 projects reviewed · 1,375 reports · latest May 2025
See CertiK’s auditsSomething 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