TokenOps

QuantstampFiles named in the report

Quantstamp reviewed TokenOps on 20 Sep 2023: 5 findings, 0 critical; 3 marked fixed, 2 acknowledged.

No open critical findings
Open the reportOpen TokenOps’s security record

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings5

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High001
Medium010
Low012
HighVested, Unclaimed Tokens Become Frozen Once Admin Revokes the GrantFixed

An admin can revoke a grant through function `revokeGrant()`, resulting in the vesting being stopped and all yet unvested tokens being freed to be used for other grants. Importantly, the unvested, yet unwithdrawn tokens by end-users should still be able to be withdrawn by them, as the user has rightfully vested all tokens until then. However, this becomes impossible, as the user becomes unable to call the `withdraw()` function, as the modifier in the `hasActiveGrant()` function requires the `isActive` field to be `true` for a given user. This is however set to false during the revocation process. These vested, but unwithdrawn funds, therefore, become stuck in the contract, as these funds are contained in the sum of reserved tokens `numTokensReservedForVesting` for granted users, but are non-withdrawable by the user with the revoked grant, as they are not able to perform any withdrawals anymore. Notice that the `isActive` flag can also never be toggled again to true, making the vested, unwithdrawn funds permanently stuck.

LowAdmin Role Can Be LostFixed

An implementation of `AccessProtected` contract is used in `TokenVesting`, which essentially maintains the set of admins. However, while admins can add other admins, they can also remove every other admin, including themselves. If that would ever happen to be the case, no additional grants could ever be granted nor revoked. Furthermore, all unallocated tokens (i.e. tokens not contract balance - `numTokensReservedForVesting`) would be frozen.

LowPrivileged Roles and OwnershipFixed

Smart contracts will often have operations that can only be executed by a limited amount of addresses with special privileges. The access control mechanism of the current contract is mainly enforced based on allowing specific actions to addresses stored as state variables of the associated contracts. The contract `AccessProtected.sol` gives the following privileges: an address with the role `admin` can grant that role to or revoke that role from any address via the function `setAdmin()`. The contract `TokenVesting.sol` gives the following privileges: 1. an address with the role `admin` can allocate tokens owned by the contract to a given recipient through a vesting agreement via the functions `createGrant()` (one by one) and `createGrantBatch()` (batch). 2. an address with the role `admin` can withdraw unallocated tokens owned by the contract via the function `withdrawAdmin()`. 3. an address with the role `admin` can revoke an active grant for a given address via the function `revokeGrant()`. 4. an address with the role `admin` can withdraw any ERC20 token owner by the contract and different than the vested token via the function `withdrawOtherToken()`.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (1)

  • contracts/TokenVesting.sol

Part of TokenOps’s security record

TokenOps
Audits1 audit by 1 firmLast audit Sep 2023, by Quantstamp.
Critical findingsNo open critical findingsIn 1 report.
Open TokenOps’s security record

Security firm

Quantstamp

236 projects reviewed · 332 reports · latest Oct 2026

See Quantstamp’s audits

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