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
High`_claimDelegatorRewardsAndPendingUndelegates()` aOpen

The identified loop logic in `_claimDelegatorRewardsAndPendingUndelegates()` and `_calcDelegatorRewardsAndPendingUndelegates()` may exceed block gas limit when parameter `beforeEpochExclude`/`beforeEpoch` is far bigger than the epoch of last processed delegation. It can happen if functions `redelegateDelegatorFee()`/`claimDelegatorFee()`/`claimDelegatorFeeAtEpoch()` have not been called by a delegator for a long time. This is especially critical for `StakingPool` because it does not use `claimDelegatorFeeAtEpoch()` to process delegation little by little. Thus the modifier `advanceStakingRewards()` in `StakingPool` may always fail due to the use of `_claimDelegatorRewardsAndPendingUndelegates()`/`_calcDelegatorRewardsAndPendingUndelegates()`. Then the functions `stake()`/`unstake()`/`claim()` in `StakingPool` will always fail and users' funds are locked in the contract and lost.

HighCentralization Related RisksOpen

In the contract `ChainConfig`, the role `Governance` has authority over the following functions: - setActiveValidatorsLength() - setEpochBlockInterval() - setMisdemeanorThreshold() - setFelonyThreshold() - setValidatorJailEpochLength() - setUndelegatePeriod() - setMinValidatorStakeAmount() - setMinStakingAmount() Any compromise to the `Governance` account may allow a hacker to take advantage of this authority and consensus params. In the contract `DeployerProxy`, the role `Governance` has authority over the following functions: - addDeployer() - removeDeployer() - banDeployer() - unbanDeployer() - disableContract() - enableContract() Any compromise to the `Governance` account may allow a hacker to take advantage of this authority and - add/remove/ban/unban deployer - disable/enable the contract Any compromise to the `Governance` account may allow a hacker to take advantage of this authority and consensus params. In the contract `DeployerProxy`, the role `Coinbase` has authority over the following functions: - registerDeployedContract() Any compromise to the `Coinbase` account may allow a hacker to take advantage of this authority and register deployed contract In the contract `Governance`, the role `Governance` has authority over the following functions: - addProposer() - removeProposer() - activateProposerRegistry() Any compromise to the `Governance` account may allow a hacker to take advantage of this authority and - add/remove the proposer - activate the proposer registry In the contract `Governance`, the role `Proposer` has authority over the following functions: - proposeWithCustomVotingPeriod() - propose() - execute() Any compromise to the `Proposer` account may allow a hacker to take advantage of this authority and propose a new proposal and execute the proposal In the contract `RuntimeUpgrade`, the role `Governance` has authority over the following functions: - upgradeSystemSmartContract() - deploySystemSmartContract() Any compromise to the `Governance` account may allow a hacker to take advantage of this authority and upgrade/deploy system smart contract In the contract `SlashingIndicator`, the role `Coinbase` has authority over the following functions: - registerDeployedContract() Any compromise to the `Coinbase` account may allow a hacker to take advantage of this authority and slash the validator In the contract `SystemReward`, the role `Governance` has authority over the following functions: - updateDistributionShare() Any compromise to the `Governance` account may allow a hacker to take advantage of this authority and update distribution share In the contract `Staking` the role `Governance` has authority over the functions: - addValidator() - removeValidator() - activateValidator() - disableValidator() Any compromise to the `Governance` account may allow the hacker to take advantage of this authority and - adds a validator - removes a validator - activates a validator - disables a validator In the contract `Staking` the owner of the validator has authority over the functions: - changeValidatorCommissionRate() - changeValidatorOwner() - releaseValidatorFromJail() - claimValidatorFee() - claimValidatorFeeAtEpoch() Any compromise to the owner of the validator may allow the hacker to take advantage of this authority and - changes the commission rate of himself/herself - changes the owner of the validator - release himself/herself from jail - claims validator fee

HighValidators with non-zero amount of delegation orOpen

If a validator with non-zero delegation or pending validator rewards is removed, the functions `undelegate()`/`claimValidatorFee()`/`claimValidatorFeeAtEpoch()` will malfunction and revert when called by users/validator who still have funds left in the removed validator account. Thus users/validators' funds can not be withdrawn and lost.

MediumPotentially incompatible bytecode for deploying nOpen

Deploying new contracts and upgrading existing contracts use different bytecodes. Deploying new contracts run `contract creation bytecode` which runs constructor code and returns the actual runtime bytecode. Upgrading existing contracts involves using new runtime bytecode to replace existing runtime bytecode. The function `_upgradeSystemSmartContract()` does not run constructor code at all which is required by deploying new contracts. Thus any new contract with non-empty constructor will not initialize properly and malfunction afterwards. See https://docs.soliditylang.org/en/latest/contracts.html#immutable

LowLack of check contract does not existOpen

The function `checkContractActive()` is used to check that the contract is active, but the function only checks that the contract is not disabled, it does not check that the contract exists.

LowUninitialized State VariableOpen

One or more state variables are used without being initialized in the constructor. ```solidity=29 address internal _systemTreasury; ``` - `_systemTreasury` is never initialized, but used in `SystemReward._claimSystemFee`.

LowUnprotected InitializerOpen

One or more logic contracts do not protect their initializers. An attacker can call the initializer and assume ownership of the logic contract, whereby she can perform privileged operations that trick unsuspecting users into believing that she is the owner of the upgradeable contract. ```solidity=11 contract StakingPool is InjectorContextHolder, IStakingPool { ``` - `StakingPool` is an upgradeable contract that does not protect its initializer. ```solidity=62 function init() external initializer { ``` - `init` is an unprotected initializer function.

LowUnsafe Integer CastOpen

```solidity=236 return uint64(block.number / _chainConfigContract.getEpochBlockInterval() + 0); ``` - The type conversion `uint64(block.number / _chainConfigContract.getEpochBlockInterval() + 0)` from larger type uint256 to smaller type uint64 may truncate data. --- ```solidity=291 validatorSnapshot.totalDelegated += uint112(amount / BALANCE_COMPACT_PRECISION); ``` - The type conversion `uint112(amount / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=302 recentDelegateOp.amount += uint112(amount / BALANCE_COMPACT_PRECISION); ``` - The type conversion `uint112(amount / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=304 delegation.delegateQueue.push(DelegationOpDelegate({epoch : atEpoch, amount : recentDelegateOp.amount + uint112(amount / BALANCE_COMPACT_PRECISION)})); ``` - The type conversion `uint112(amount / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=308 delegation.delegateQueue.push(DelegationOpDelegate({epoch : atEpoch, amount : uint112(amount / BALANCE_COMPACT_PRECISION)})); ``` - The type conversion `uint112(amount / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=327 validatorSnapshot.totalDelegated -= uint112(amount / BALANCE_COMPACT_PRECISION); ``` - The type conversion `uint112(amount / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=336 uint112 nextDelegatedAmount = recentDelegateOp.amount - uint112(amount / BALANCE_COMPACT_PRECISION); ``` - The type conversion `uint112(amount / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=345 delegation.undelegateQueue.push(DelegationOpUndelegate({amount : uint112(amount / BALANCE_COMPACT_PRECISION), epoch : beforeEpoch + _chainConfigContract.getUndelegatePeriod()})); ``` - The type conversion `uint112(amount / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=534 _validatorSnapshots[validatorAddress][sinceEpoch] = ValidatorSnapshot(0, uint112(initialStake / BALANCE_COMPACT_PRECISION), 0, commissionRate); ``` - The type conversion `uint112(initialStake / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=538 delegation.delegateQueue.push(DelegationOpDelegate(uint112(initialStake / BALANCE_COMPACT_PRECISION), sinceEpoch)); ``` - The type conversion `uint112(initialStake / BALANCE_COMPACT_PRECISION)` from larger type uint256 to smaller type uint112 may truncate data. --- ```solidity=552 indexOf = int256(i); ``` - The type conversion `int256(i)` from type uint256 to type int256 may flip the value's sign. --- ```solidity=689 currentSnapshot.totalRewards += uint96(msg.value); ``` - The type conversion `uint96(msg.value)` from larger type uint256 to smaller type uint96 may truncate data.

LowUnused State VariableOpen

One or more state variables are never used in the codebase. Variable `__reserved` in `InjectorContextHolder` is never used in `ChainConfig`. ```solidity=55 uint256[100 - 8] private __reserved; ``` ```solidity=6 contract ChainConfig is InjectorContextHolder, IChainConfig { ```

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