During my recent security research into the CoW Protocol (Gnosis Protocol v2), I focused on how the protocol handles fractional settlements. While the protocol is architecturally sound, a classic smart contract pitfall—precision loss—can lead to cumulative fee leakage.
In this post, I’ll show how a malicious solver can exploit integer division in GPv2Settlement to execute trades with zero protocol fees.
The Vulnerability: Death by a Thousand Cuts
The core of the issue lies in how fees are calculated for partiallyFillable orders. In GPv2Order.sol, users can sign orders that allow solvers to fill them in multiple steps.
When a solver executes a partial fill, the protocol calculates the proportional fee using the following formula:
executedFeeAmount=
sellAmount
feeAmount⋅executedAmount
Since Solidity doesn't support floating-point numbers, it uses integer division, which always rounds down.
The Attack Vector
A malicious solver can split a large order into thousands of "dust" transactions. If the solver ensures that (feeAmount⋅executedAmount)<sellAmount, the result will be 0.
Proof of Concept (PoC)
To verify this, I wrote a test using the Foundry framework. My goal was to prove that a trade with a valid fee amount could be processed while contributing exactly 0 to the protocol's treasury.
Solidity
// test/DustAttack.t.sol
function test_RoundingFeeToZero() public view {
uint256 sellAmount = 100 ether;
uint256 feeAmount = 1 ether;
// Solver executes a "dust" trade of 1000 wei
uint256 executedAmount = 1000;
// Proportional fee calculation: (1e18 * 1000) / 100e18
uint256 executedFeeAmount = (feeAmount * executedAmount) / sellAmount;
console.log("Executed Amount (wei):", executedAmount);
console.log("Calculated Fee (wei): ", executedFeeAmount);
assertEq(executedFeeAmount, 0, "Fee should be rounded to zero");
}
As shown in my terminal, the test passed with a zero fee result, confirming the "Fee Leakage" vulnerability.
Impact & Mitigation
While a single transaction might only leak a few wei, an automated solver can repeat this thousands of times. This results in:
Protocol Revenue Loss: The DAO loses its intended cut of the volume.
Unfair Advantage: Solvers can bypass the cost of doing business on the protocol.
Recommended Fix:
Implement a "minimum fee" check or use a rounding-up mechanism (like fixedPoint.mulDivUp) to ensure the protocol always collects at least 1 unit of the fee token for any non-zero execution.
Conclusion
Precision matters—especially in DeFi. This research is part of my ongoing work in smart contract security, where I analyze top-tier protocols for subtle economic vulnerabilities.
You can find the full PoC and my research notes in my GitHub repository:
https://github.com/rdin777/contracts_cowprotocol
About the Author:
I am a Smart Contract Auditor and Security Researcher specializing in vulnerability research (Log Injection, DoS, and Math errors). Currently looking for remote opportunities in Web3 security.
Top comments (0)