As of 21 Oct 2026, Dora Factory has 4 audit reports by 2 security firms on Trustblock; the latest is by Oak Security, dated 13 Jun 2024. Those reports list 1 critical acknowledged and not fixed. It also holds 1 deployed contract on 1 chain.
Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Dora Vota audit | Security firm: Oak Security | Date: | Scope: Not recorded (see the report) | 1 critical acknowledged, not fixed | Open · GitHub |
| DORA ERC20 Contract Update-Audit | Security firm: CertiK | Date: | Scope: 1 address on Ethereum | No open critical findings | Open · skynet.certik.com |
| Dora Grant DAO V4 | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
| Aptos Grant DAO-Audit | Security firm: CertiK | Date: | Scope: Not recorded (see the report) | No open critical findings | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 1 | 0 |
| High | 2 | 5 | 1 |
| Medium | 0 | 0 | 1 |
| Low | 8 | 2 | 12 |
The report gives no description here.
Open the reportThe `min_area` is updated mistakenly. In the `else-if` condition, the `min_area` may not be the current project's `area`. Because the current project's `area` increases at this time, the real `min_area` may come from the previous second smallest project. For example: - Project A has the smallest area at this moment, and its `area` is 10. - Project B is the second smallest project at this moment,, and its `area` is 12. - Someone votes the project A again, and its `area` is 15 now. In this time, the `else-if` condition is met and the `min_area` will be updated to `15`. However, the real `min_area` should be 12, and the `min_area_index` should be the id of project B. ```rust=538 if(area < round.min_area || round.min_area == 0) { round.min_area = area; round.min_area_index = project_id; } else if(round.min_area_index == project_id) { round.min_area = area; }; ``` ```rust=550 if(area < track.min_area || track.min_area == 0) { track.min_area = area; track.min_area_index = project_id; } else if(track.min_area_index == project_id) { track.min_area = area; }; ```
Open the reportThe report gives no description here.
Open the reportThe function `exit()` requires the `_amount` less than the `stakingAmount` of users, which means users cannot withdraw all staked tokens. ```solidity=82 function exit(uint256 _amount) external nonReentrant { User storage u = user[msg.sender]; require(u.stakingAmount > _amount); u.stakingAmount -= _amount; u.exitAmount += _amount; u.exitTime = block.timestamp + EXIT_BUFFER_TIME; emit Exit(msg.sender, _amount); } ``` In the `slashTo`, users on the whitelist cannot withdraw all staked tokens from penalized accounts. ```solidity=143 function slashTo( address _slashed, address _to, uint256 _amount ) external { ... uint256 totalAmount = u.stakingAmount + u.exitAmount; require(_amount < totalAmount); require(slashedAmount[_slashed] + _amount < totalAmount); ... } ```
Open the reportThe variable in the above lines should be named `_reentrancyLock`.
Open the reportThe contract has unlocked compiler version. An unlocked compiler version in the source code of the contract permits the user to compile it at or above a particular version. This, in turn, leads to differences in the generated bytecode between compilations due to different compiler versions. This can lead to an ambiguity when debugging as compiler specific bugs may occur in the codebase that would be hard to identify over a span of multiple compiler versions rather than a specific one.
Open the reportOne 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=7 contract BuidlDonation { ``` - `BuidlDonation` is an upgradeable contract that does not protect its initializer. ```solidity=66 function init(IERC20 _token, DoraChecker _checker) external { ``` - `init` is an unprotected initializer function. --- ```solidity=6 contract DoraChecker { ``` - `DoraChecker` is an upgradeable contract that does not protect its initializer. ```solidity=52 function init(IERC20 _token) public { ``` - `init` is an unprotected initializer function.
Open the reportPlease confirm which one of following restrictions is more suitable. - `amount > pow_10_decimals / round.voting_unit` - `amount >= pow_10_decimals / round.voting_unit`
Open the reportThe `round_id` is never changed in the while-loop, so it only needs to be checked once. It would be a waste of gas to check every iteration. ```rust=474 while(i < length) { let project_id = *vector::borrow(&project_ids, i); check_project_id(round_id, project_id); let amount = *vector::borrow(&amounts, i); let data = borrow_global_mut<Data>(@QF); let round = vector::borrow_mut(&mut data.rounds, round_id-1); assert!( round.status == ROUND_STATUS__OK, error::invalid_state(ERR_ROUND_STATUS_NOT_OK) ); ... ```
Open the reportThe `event` module is declared in the `aptos_framework`. However, the module `qf` import `event` from the package `aptos_std` as below. ```rust=13 use aptos_std::event; ```
Open the report```rust=144 assert!( exists<Data>(@QF), error::already_exists(ERR_NOT_PUBLISHED), ); ``` The error code will be issued when `@QF` has no resource `Data`, so it is not appropriate to use `error::already_exists` here.
Open the reportAccuracy loss may occur in the calculation of the `votes`. ```rust=508 let votes = amount * round.voting_unit / pow_10_decimals; ```
Open the reportMany constant variables are declared but never used in the project.
Open the report```rust=557 event::emit_event(&mut data.events, QFEvent { type: EVENT_TYPE__VOTE, account: account_addr, round: round_id, project: round.project_number, amount, }); ``` According to the logic of the function `batch_vote()`, the event emitted should record the id of the project being voted.
Open the report| Address | Chain | Source code |
|---|---|---|
| 0x70b7…38b20x70b790d0948a760e80bc3f892b142f7779b538b2 | Chain: Ethereum | Source code: Verified source |
Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.
Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="dora-factory"></div></body>
Paste the code where the label should appear. It uses no API credit and updates by itself.
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