Download audit report
This document presents the security review performed by Nethermind Security for the Worldcoin team. The review focuses on the OperatorPayoutsWorldchain contract, which is designed to be called by the Operator backend to distribute rewards. These rewards are denominated in USD and are converted to an equivalent amount in WLD tokens for payout.
The audit comprises 78 lines of solidity code. The audit was performed using (a) manual analysis of the codebase, (b) automated analysis tools, and (c) creation of test cases.
| Audit assessment | |
| Audit Type | Security Review |
| Initial Report | May 09, 2025 |
| Final Report | May 14, 2025 |
| Repositories | helper-contracts |
| Initial Commit | f3147a8362 |
| Final Commit | 156e93bee5 |
| Documentation | PR description |
| Documentation Assessment | High |
| Test Suite Assessment | High |
Findings by severity
| # | Contract | LoC | Comments | Ratio | Blank | Total |
| 1 | OperatorPayoutsWorldchain.sol | 78 | 44 | 56.4% | 28 | 150 |
| Total | 78 | 44 | 56.4% | 28 | 150 |
| # | Finding | Severity | Update |
| 1 | Potential use of stale WLD price in payout calculations | Low | Fixed |
| 2 | High minWldPrice can lead to zero tokenAmount | Info | Fixed |
| 3 | Missing event emission in the setRelayer function | Best Practices | Fixed |
| 4 | Missing validation for zero dollarAmount | Best Practices | Fixed |
The OperatorPayoutsWorldchain contract enables the transfer of WLD token payouts by an authorized relayer, which is intended to be the Operator backend. The contract accepts a reward amount specified in USD, as a whole number with zero decimals, and converts it to the equivalent WLD amount using the WLD/USD price provided by the Chainlink oracle.

The contract exposes two main functions for token transfers:
function transfer(address payable to, uint256 dollarAmount) external onlyRelayerThis function transfers WLD tokens to the specified recipient address based on the current Chainlink oracle price. Transfers are executed through Worldcoin’s allowance module.
function transferWithMinimumWLDPrice(
address payable to,
uint256 dollarAmount,
uint256 minWldPrice
) external onlyRelayerThis variant allows the relayer to specify a minimum acceptable WLD/USD price. If the oracle price falls below this minimum, the transfer will use the specified minimum price instead, resulting in a lower WLD payout. This function is used as a safeguard in cases of large WLD price drops.
The risk rating methodology used by Nethermind Security follows the principles established by the OWASP Foundation. The severity of each finding is determined by two factors: Likelihood and Impact.
Likelihood measures how likely the finding is to be uncovered and exploited by an attacker. This factor will be one of the following values:
When defining the likelihood of a finding, other factors are also considered. These can include but are not limited to motive, opportunity, exploit accessibility, ease of discovery, and ease of exploit.
Impact is a measure of the damage that may be caused if an attacker exploits the finding. This factor will be one of the following values:
When defining the impact of a finding, other factors are also considered. These can include but are not limited to data and state integrity, loss of availability, financial loss, and reputation damage. After defining the likelihood and impact of an issue, the severity is determined according to the table below.
| Impact / Likelihood | Low | Medium | High |
| High | Medium | High | Critical |
| Medium | Low | Medium | High |
| Low | Info / Best Practices | Low | Medium |
| Undetermined | Undetermined | Undetermined | Undetermined |
To address issues that do not fit a High, Medium or Low severity, Nethermind Security also uses three more finding severities: Informational, Best Practices, and Undetermined.
| File | Fix commit | Type | Status |
OperatorPayoutsWorldchain.sol | 10d8ef6 | Low | Fixed |
The transfer and transferWithMinimumWLDPrice functions fetch the WLD token price via Chainlink's latestRoundData. However, they do not verify the freshness of this data using the updatedAt timestamp. As a result, the function may rely on stale prices, leading to inaccurate conversions during payout calculations.
function transfer(...) external onlyRelayer {
if (to == address(0)) revert ZeroAddress();
// @audit Potential stale price
(, int256 answer,,,) = ORACLE.latestRoundData();
if (answer <= 0) revert InvalidOraclePrice(answer);
// Add 2*18 decimals to the dollar amount to account for 18 decimals from oracle price and 18 decimals from WLD
uint256 tokenAmount = (dollarAmount * (10 ** 36)) / uint256(answer);
// ...
}Recommendation
Add a check for the updatedAt field to ensure the returned price is not older than a defined threshold.
minWldPrice can lead to zero tokenAmount| File | Fix commit | Type | Status |
OperatorPayoutsWorldchain.sol | 5183e10 | Info | Fixed |
In the transferWithMinimumWLDPrice function, the WLD price used for conversion is selected as the maximum between the oracle price and the minWldPrice. However, if minWldPrice is set to an unreasonably high value, it can cause the computed tokenAmount to round down to zero. This would result in zero tokens being transferred, despite a nonzero dollarAmount input.
function transferWithMinimumWLDPrice(
address payable to,
uint256 dollarAmount,
uint256 minWldPrice
) external onlyRelayer {
if (to == address(0)) revert ZeroAddress();
(, int256 answer,,,) = ORACLE.latestRoundData();
if (answer <= 0) revert InvalidOraclePrice(answer);
uint256 wldPrice = Math.max(uint256(answer), minWldPrice);
// @audit tokenAmount may round to zero if minWldPrice is too high
uint256 tokenAmount = dollarAmount * (10 ** 36) / wldPrice;
// ...
}Recommendation
Add a check to ensure that tokenAmount is non zero before proceeding with the transfer.
setRelayer function| File | Fix commit | Type | Status |
OperatorPayoutsWorldchain.sol | ff7b4bc | Best Practices | Fixed |
The setRelayer function updates the relayer address but does not emit an event when this change occurs. Emitting events for important parameter updates is a best practice, as it allows off-chain monitoring and improves transparency.
function setRelayer(address _relayer) external onlyOwner {
if (_relayer == address(0)) revert ZeroAddress();
relayer = _relayer;
//@audit Missing event emission
}Recommendation
Emit an event in the setRelayer function to log changes to the relayer address.
dollarAmount| File | Fix commit | Type | Status |
OperatorPayoutsWorldchain.sol | 574a7ec156e93b | Best Practices | Fixed |
Both transfer and transferWithMinimumWLDPrice functions lack a check to prevent execution when dollarAmount is zero. In such cases, the computed tokenAmount would also be zero, resulting in unnecessary execution and gas consumption.
Recommendation
Implement a check to ensure dollarAmount is not zero.
Software documentation refers to the written or visual information that describes the functionality, architecture, design, and implementation of software. It provides a comprehensive overview of the software system and helps users, developers, and stakeholders understand how the software works, how to use it, and how to maintain it. Software documentation can take different forms, such as user manuals, system manuals, technical specifications, requirements documents, design documents, and code comments. Software documentation is critical in software development, enabling effective communication between developers, testers, users, and other stakeholders. It helps to ensure that everyone involved in the development process has a shared understanding of the software system and its functionality. Moreover, software documentation can improve software maintenance by providing a clear and complete understanding of the software system, making it easier for developers to maintain, modify, and update the software over time. Smart contracts can use various types of software documentation. Some of the most common types include:
These types of documentation are essential for smart contract development and maintenance. They help ensure that the contract is properly designed, implemented, and tested, and they provide a reference for developers who need to modify or maintain the contract in the future.
Worldcoin's smart contract documentation was provided within the PR description, which thoroughly explained the contract's purpose and implementation logic.
Each function in the codebase is accompanied by NatSpec comments that describe its purpose and input parameters. Additionally, the Worldcoin team provided a comprehensive walkthrough of the project during the kick-off call, addressing all questions and concerns raised by the Nethermind Security team.
The Worldchain Operator Payouts's test suite is robust and clearly outlines the contract specifications. The test suite catches changes to the business logic. To assess the test coverage for these files, the Nethermind Security team applied a technique called mutation testing to uncover the untested paths. This technique introduces slight modifications to the code called "mutations" or "mutants." An example of a mutation is, for example, changing the operator in an expression (a + b) to (a - b), or removing a require(a > b) statement entirely from the code. With these changes, the code no longer follows the expected business logic of the application, and the test suite should reflect that by failing.
Evaluation of the test suite with mutation testing consists of two phases:
Only one modification can be tested at a time. If the contract has ten mutations, the test suite must run ten times (once for every mutation). If any of the tests fail, it means that the test suite caught the change in the code. Whenever that happens, the particular mutant is considered "slain" or "killed" and is removed from the mutant's set. If that does not occur, a new test case can be added to cover the code branch to "kill" the mutant.
The following table outlines the results of the analysis performed on the Worldchain Operator Payouts' core smart contract. The first column lists the contracts that were tested using mutation testing. The second column indicates the number of mutants generated and how many were "slain" (i.e., caught by the test suite). The third column provides the percentage of mutants slain, reflecting the effectiveness of the test suite in covering the particular contract. The higher the score, the better the test suite is at finding bugs.
| Contract | Mutants (slain / total generated) | Score |
OperatorPayoutsWorldchain.sol | 72 / 74 | 97.29% |
| Total | 72 / 74 | 97.29% |
The following is a list of code modifications not caught by the existing test suite. Each point highlights a scenario that could benefit from higher test coverage to enhance the protocol's overall security and resilience in the next code change iterations as the project evolves:
OperatorPayoutsWorldchain.sol
transferWithMinimumWLDPrice(...) function is only tested in scenarios where the provided to address is non-zero. Consider adding a test case that triggers the ZeroAddress error.transferWithMinimumWLDPrice(...) function doesn't test the scenarios where the answer value returned by the oracle is zero or less. Consider adding a test case that triggers the InvalidOraclePrice error.Remarks about the Worldchain Operator Payouts Test Suite
The test suite for the Worldchain Operator Payouts Protocol is robust in terms of unit testing for core functionality. Changes in business logic are effectively caught, ensuring that key components behave as expected under various conditions. However, the suite currently relies on mock contracts, such as the mock implementation of the allowance module. While this approach is useful for isolating components during unit testing, it limits the ability to detect integration issues that may arise in production. The test suite can be improved by incorporating more end-to-end tests using actual contract implementations and by addressing the missing flows outlined earlier.
All the relevant issues raised by the AuditAgent have been incorporated into this report. The AuditAgent is an AI-powered smart contract auditing tool that analyses code, detects vulnerabilities, and provides actionable fixes. It accelerates the security analysis process, complementing human expertise with advanced AI models to deliver efficient and comprehensive smart contract audits. Available at https://app.auditagent.nethermind.io.
As auditors, we recommend that any changes or updates made to the audited codebase undergo a re-audit or security review to address potential vulnerabilities or risks introduced by the modifications. By conducting a re-audit or security review of the modified codebase, you can significantly enhance the overall security of your system and reduce the likelihood of exploitation. However, we do not possess the authority or right to impose obligations or restrictions on our clients regarding codebase updates, modifications, or subsequent audits. Accordingly, the decision to seek a re-audit or security review lies solely with you.
This report is based on the scope of materials and documentation provided by you to Nethermind in order that Nethermind could conduct the security review outlined in 1. Executive Summary and 2. Audited Files. The results set out in this report may not be complete nor inclusive of all vulnerabilities. Nethermind has provided the review and this report on an as-is, where-is, and as-available basis. You agree that your access and/or use, including but not limited to any associated services, products, protocols, platforms, content, and materials, will be at your sole risk. Blockchain technology remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond the programming language, or other programming aspects that could present security risks. This report does not indicate the endorsement of any particular project or team, nor guarantee its security. No third party should rely on this report in any way, including for the purpose of making any decisions to buy or sell a product, service or any other asset. To the fullest extent permitted by law, Nethermind disclaims any liability in connection with this report, its content, and any related services and products and your use thereof, including, without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement. Nethermind does not warrant, endorse, guarantee, or assume responsibility for any product or service advertised or offered by a third party through the product, any open source or third-party software, code, libraries, materials, or information linked to, called by, referenced by or accessible through the report, its content, and the related services and products, any hyperlinked websites, any websites or mobile applications appearing on any advertising, and Nethermind will not be a party to or in any way be responsible for monitoring any transaction between you and any third-party providers of products or services. As with the purchase or use of a product or service through any medium or in any environment, you should use your best judgment and exercise caution where appropriate. FOR AVOIDANCE OF DOUBT, THE REPORT, ITS CONTENT, ACCESS, AND/OR USAGE THEREOF, INCLUDING ANY ASSOCIATED SERVICES OR MATERIALS, SHALL NOT BE CONSIDERED OR RELIED UPON AS ANY FORM OF FINANCIAL, INVESTMENT, TAX, LEGAL, REGULATORY, OR OTHER ADVICE.
The Leading Engineers of Blockchain Infrastructure