CertiK reviewed Bancor (Bancor Governence) on 9 Oct 2020: 9 findings, 0 critical; 5 marked fixed, 4 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 | 0 | 2 |
| Medium | 0 | 0 | 0 |
| Low | 4 | 0 | 3 |
`tallyVotes` function (L390 - L405) which is executed in the `execute` function (L370 - L383) is marked as a public function. During the `execute` function, `tallyVotes` changes the `proposals[_id].open` property from `true` to `false`. This param is used in the `proposalEnded` modifier, leading to an `ERR_NOT_OPEN` throw if the proposal is closed and reverting the transaction. `tallyVotes` can be called by anyone who knows the `id` of the proposal to close it and thus stoping further execution of the proposal. This attack vector is especially exploitable via a front-running attack whereby one inspects the transaction mempool of Ethereum, detects an `execute` contract call and invokes `tallyVotes` beforehand with a higher gas fee.
The `unstake` and `revokeVotes` functions affect the `totalVotes` variable of the contract, however they do not adjust already-voted-on proposals. This leads to proposals reporting invalid quorums and total votes available as they are re-set on each vote. This is especially exploitable in case a proposal's expiration is before the vote lock mechanism, meaning a double-vote can occur without losing balance. To replicate this issue, simply `stake` some new tokens for 2 different accounts. Have account A vote for a proposal and then instantly revoke his votes and have account B vote against a proposal. The `totalVotesAvailable` and `quorum` variables of the proposal will be incorrect, leading to invalid calculations on all functions relating to a proposal's acceptance.
The `onlyVoter()` modifier uses a boolean value to compare with a boolean literal.
modifiers `proposalNotEnded` and `proposalEnded` share the same code in the first `require` which could be put into its own modifier code. This can cause some confusion and potential issues when one code block is updated and other one not.
`IExecutor(proposals[_id].executor).execute(_id, forRatio, againstRatio, quorumRatio)` function call is an external function call. While re-entrancy is not possible for the `execute` function of the `BancorGovernance` contract, other unintended re-entrancy interactions may occur by the external contract should the quorum of Bancor not have vetted its code properly.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (4)
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