Chiliz

CertiKFiles named in the report

CertiK reviewed Chiliz on 23 Dec 2022: 19 findings, 1 critical; 10 marked fixed, 9 open.

1 critical finding, fixed
Open the reportOpen Chiliz’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings19

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

SeverityOpenAcknowledgedFixed
Critical001
High301
Medium106
Low502
CriticalIncorrect calculation and potential integer underFixed

The `_stakingContract.getDelegatorFee()` returns the amount of delegator rewards plus undelegated tokens in `_stakingContract`. The `validatorPool.pendingUnstake` is the total amount of undelegated tokens, which is the sum of undelegated tokens in `_stakingContract` and withdrawn undelegated tokens in current `StakingPool`. The unclaimed rewards should be `_stakingContract.getDelegatorFee()` minus undelegated tokens in `_stakingContract`, NOT `validatorPool.pendingUnstake`. The incorrect calculation may cause integer underflow and revert. The incorrect calculation is used by most functions, including `stake()`, `unstake()` and `claim()`, which means the contract may become totally useless and users' funds are locked and lost forever.

HighUpgradeable contracts must inherit OpenZeppelin uFixed

All upgradeable contracts in an inheritance chain must follow the same rules for writing upgradeable contracts. See https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#use-upgradeable-libraries. Otherwise it will malfunction and may be vulnerable and completely stop working.

MediumBanned deployer should not be able to register coFixed

A banned deployer should not be able to perform any action. The code does not check if the specified deployer is banned. Thus a banned deployer can register contracts which may be malicious.

MediumImmutables in `EIP712` will not work after upgradFixed

The Governance indirectly inherits from the `EIP712` contract through the `Governor` contract. The immutables in `EIP712` contract will not work after upgrade because the runtime upgrade evm hook does not run deployment code during upgrade, so all the immutables are not initialized through constructor and are all zero values. See https://docs.soliditylang.org/en/latest/contracts.html#immutable. Thus the functions `castVoteBySig()/castVoteWithReasonAndParamsBySig()` in `Governor` will stop working after upgrade. See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.6.0/contracts/utils/cryptography/draft-EIP712.sol

MediumIncompatible calls of `_stakingContract.getValidaFixed

The function `_stakingContract.getValidators()` returns current validator array, which is used as the parameter of subsequent call of `_stakingContract.getValidatorByOwner()`, which actually expects owners of validators as the parameter, not validators. Thus the function `activateProposerRegistry()` will malfunction or even always revert.

MediumMissing check active validatorsFixed

The function `_getVotes()` checks only actived validators' power. However, the function `_votingSupply()` lacks a check on whether the validator is active. This results in an inaccurate minimum number of votes required for a proposal to be successful.

MediumMissing check that validator is activeFixed

In the modifier `onlyProposer`, only the active validator owner can be a proposer when the registry is not activated. In the function `activateProposerRegistry()`, governance can add the validator owner to the proposer list, but the function does not call the function `isValidatorActive()` to check that the owner's validator is active.

MediumPast active status of validators are not checkedFixed

The functions `_validatorVotingPowerAt()/_validatorOwnerVotingPowerAt()` are used to get validator/owner voting power at a specific block number which may be in the past. But the function `_stakingContract.isValidatorActive()` only checks if a validator is active currently. It is possible that a validator is active at present but is inactive at that specific past block, which makes `_validatorVotingPowerAt()/_validatorOwnerVotingPowerAt()` return incorrect values.

LowMissing Zero Address ValidationFixed

Addresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=19 _evmHookAddress = evmHookAddress; ``` - `evmHookAddress` is not zero-checked before being used.

LowUsage of `transfer`/`send` for sending EtherFixed

It is not recommended to use Solidity's `transfer()` and `send()` functions for transferring Ether, since some contracts may not be able to receive the funds. 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=179 payable(address(msg.sender)).transfer(amount); ``` - `StakingPool.claim` uses `transfer()`. --- ```solidity=104 payableTreasury.transfer(amountToPay); ``` - `SystemReward._claimSystemFee` uses `transfer()`.

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 (9)

  • contracts/Governance.sol
  • contracts/StakingPool.sol
  • contracts/RuntimeUpgrade.sol
  • contracts/Injector.sol
  • contracts/SystemReward.sol
  • contracts/ChainConfig.sol
  • contracts/SlashingIndicator.sol
  • contracts/DeployerProxy.sol
  • contracts/Staking.sol

Part of Chiliz’s security record

Chiliz
Audits8 audits by 3 firmsLast audit Jan 2026, by Halborn.
Critical findingsNo open critical findingsAcross the 8 reports, 1 critical finding was reported. It is marked fixed by the firm that reported it.
Open Chiliz’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’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