CertiK reviewed DeXit on 7 Sep 2022: 34 findings, 2 critical; 29 marked fixed, 5 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 | 2 |
| High | 0 | 0 | 2 |
| Medium | 0 | 0 | 1 |
| Low | 5 | 0 | 24 |
The variable `rewardClaimRecords` is used to record the last reward claim time of the validator/delegator. An EOA address can be both validator and delegator due to the lack of restrictions in the contract. As a result, recording the last reward claim time of the validator and delegator in the same variable will make an EOA combining the 2 roles not able to claim the rewards as validator and delegator at the same time.
[The glossary of Ethereum](https://ethereum.org/en/glossary/#account) writes that an account can be a contract account or an externally owned account (EOA). The `registerContract` function is used to register a pair of contract-reward recipients. In commit `1c2d45f56eab6a62d0416daf9ac012c79f61e1a7`, a require statement L36 was commented, which means that a pair of EOA-reward recipients could also be registered in the array `rewardAddresses`. ```solidity function registerContract(address contractAddr, address rewardAddr) external virtual returns (bool) { require( contractAddr != address(0x0) && rewardAddr != address(0x0), "0x0 found" ); require( rewardAddresses[contractAddr] == address(0), "Already registered" ); //require(isContract(contractAddr)), "contractAddr isn't contract"); rewardAddresses[contractAddr] = rewardAddr; rewardAmountOwner[rewardAddr] = 0; return true; } ``` However, from the input naming info of the `checkEligible` function that references the `rewardAddresses` array, only contract addresses can be passed in.
The function `stakeValidator()` is used to stake tokens by any user to become a validator. The `if` statements in L235-L254 already update the array `highestValidators`, but the statements in L265-L279 update the array `highestValidators` again after updating the validator's status and the array `currentValidators`. Is that designed as expected?
GovHub is the governance contract for `Dexit`, a contract that allows any validator to submit proposals with the initiator address stored in the `proposal.dst` field. \ Once a proposal is initiated, it enters the voting phase, but not all validators can vote, only those in the `highestValidators` array can. \ The `voteProposal` function checks whether `pass[proposals[id].dst]` is `True` or not at L314. \ If the condition is `False`, and if more than 51% of the nodes vote for the proposal, then the `voteProposal` function sets `pass[proposals[id].dst]` to `True` and calls `authchangevalues` to execute the proposal. As long as `pass[proposals[id].dst]` is `True`, the other proposals that the proposer submits can not be executed.\ But there is a particular case for the `highestValidators`. When a validator in `highestValidators` votes on his own proposal and the cumulative `votePowerOfAgree` reaches 51% of `totalVotePower` when he calls `voteProposal()`, the proposal is executed. In this case `proposals[id].dst` and `msg.sender` will be the same. Since `authchangevalues` will reset `pass[msg.sender]` to `False`, `pass[proposals[id].dst]` will also be `False`, meaning other proposals created by those validators will be executed normally, since they will be able to bypass the check L314. ```solidity if (pass[proposals[id].dst] || proposals[id].resultExist) { return true; //Do nothing if dst already passed or rejected. } ``` Is that designed as expected?
The function `getStakingInfo()` is a view function that returns the information of the given delegator's stake from the variable `stakingInfo`. In the contract `BSCValidatorSet`, both validator and delegator will be recorded in the variable `stakingInfo`; but to get the actual information of the validator, it is needed to combine the information from the variables `validatorInfo` and `stakingInfo`. As a result, the return value is not correct when calling the function `getStakingInfo()` with the parameter is a validator.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (23)
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