31Third security record

Ethereum, Optimism, Polygon (POS)31third.com

As of 3 Nov 2026, 31Third has 2 audit reports by 1 security firm on Trustblock; the latest is by Quantstamp, dated 4 Apr 2024. Those reports list no open critical findings.

Critical findings
No open critical findings
Across 2 reports.
Open the latest report
Your label, live
Get the label for your site

Record last updated . It holds audits and findings, contracts and incidents up to Nov 2026. Trustblock does not review code.

Audits2

Newest first

AuditSecurity firmDateScopeCritical findingsReport
31Third - Diff - UpdateSecurity firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com
31ThirdSecurity firm: QuantstampDate: Scope: Files named in the reportNo open critical findingsOpen · certificate.quantstamp.com

Findings18

Statuses are the security firm’s own, from each report.

SeverityOpenAcknowledgedFixed
Critical000
High001
Medium002
Low258
HighUser Can Pass Any Calldata31Third · Quantstamp · 1 Mar 2023Fixed

31Third is highly dependant on external exchanges. As external exchanges can add or remove functionalities, the 31Third team should be very careful when adding new exchanges and stay updated about possible vulnerabilities in these systems. <br><br> When users call `BatchTrade.batchTrade()`, they can pass call data for a swap that differs from what is specified in the `Trade` struct. For example, if a user is trading using the 0x adapter, the actual call data sent to the 0x contract could target any available function. This could result in the user being able to call unintended functions in external contracts that could in turn drain `BatchTrade` of any funds held within.

Open the report
MediumArbitrary Call Data to Exchange Can Circumvent Fee Collection31Third · Quantstamp · 1 Mar 2023Fixed

The batch trade functionality builds upon the 0x exchange in order to perform each trade in the batch. The 0x protocol supports the submitter of the order to be different from the actual taker in the case of both [limit orders](https://protocol.0x.org/en/latest/basics/orders.html#limit-orders) and [RFQ orders](https://protocol.0x.org/en/latest/basics/orders.html#rfq-orders). Since the `batchTrade` function allows the user to pass arbitrary call data for the 0x swap, the user can easily specify within the order that the `taker` address which receives the result from the trade is different from the `spender`. Since the attacker can specify their own address as the `taker` they can receive the result of the trade directly and avoid paying the fees. In order to subvert the token balance checks within the `BatchTrade` contract, the attacker can use their own custom attack tokens as described in the attack scenario.

Open the report
MediumInflation Of Approvals Through Failed Trades31Third · Quantstamp · 1 Mar 2023Fixed

The `BatchTrade.batchTrade()` function might not revert on a failed trade if `_batchTradeConfig.revertOnError ` is set to `false`. This lack of reversion may result in some undesirable state changes persisting. Of particular concern is that token approvals to the exchange spender contract are not reset. During a trade, the function `_claimAndApproveFromToken()` is called, which transfers the input tokens for the swap, as well as approves the exchange spender to spend these tokens as shown below: ``` IERC20(_trade.from).safeIncreaseAllowance( _exchangeAdapter.getSpender(), _trade.fromAmount ); ``` The approval above is not reversed if the trade fails and could potentially be exploited in subsequent transactions. Furthermore, failed trades could be repeatedly executed in order to repeatedly increase the allowance above without resetting it.

Open the report
LowIndex Event Parameters for Improved Application Monitoring31Third - Diff - Update · Quantstamp · 4 Apr 2024Fixed

Application monitoring can be improved by indexing specific parameters emitted in an event. By indexing event parameters, off-chain systems can more easily filter contract logs by the indexed data. The following event parameters could benefit from indexing: 1. `GenericDifferentSpenderAdapter`: 1. `name`, `handlerAddress`, and `spenderAddress` in the event `GenericDifferentSpenderAdapterDeployed`. 2. `GenericBasicAdapter`: 1. `name` and `handlerAndSpenderAddress` in the event `GenericBasicAdapterDeployed`.

Open the report
LowOptimizations and Improvements31Third - Diff - Update · Quantstamp · 4 Apr 2024Fixed

Certain changes can be made in order to improve the gas-efficiency of the contracts: 1. Use custom errors instead of `require()`. 2. The two contracts in scope are duplicates. Code duplication is detrimental as it leads to the maintenance of the same issues in different locations, and is therefore, error-prone. In the case of Solidity, it might also lead to larger bytecode which might hinder the deployment of the system. Consider using inheritance or only the `GenericDifferentSpenderAdapter` contract and slightly modify the constructor to manage the case of the `GenericBasicAdapter`.

Open the report
LowAmount Received Is Lower than `Trade.minToReceive`31Third · Quantstamp · 1 Mar 2023Fixed

A trader might reasonably expect that they would receive at least `Trade.minToReceive` from a trade. However, the actual minimum amount received by the user is actually `Trade.minToReceive - fees`. This is because the check involving `Trade.minToReceive` is performed immediately after the trade, as shown below: ``` if (toBalanceAfterTrade < toBalanceBeforeTrade + _trade.minToReceive) { revert NotEnoughReceived(_trade, _trade.minToReceive, toBalanceAfterTrade - toBalanceBeforeTrade); } ``` The fees are then subtracted from the amount received from the swap, leaving the resulting amount to be potentially less than `Trade.minToReceive`.

Open the report
LowIncorrect Use of ERC-20 Approvals31Third · Quantstamp · 1 Mar 2023Fixed

When transferring ERC20 tokens, approvals are only needed when the caller of the transfer is **not** the source address of the transfer. The following instances incorrectly use `IERC20.safeIncreaseAllowance()` to approve `BatchTrade` for transferring tokens out of `BatchTrade`: 1. `receiveFees()` 2. `_approveAndReturnToken()` 3. `_returnClaimedOnError()`

Open the report
LowInflationary/Yield Bearing Tokens Are Locked Forever31Third · Quantstamp · 1 Mar 2023Fixed

The `BatchToken` contract collects fees as a portion of the tokens received for each trade. The contract imposes no restrictions as to which tokens can be traded. Thus it is quite possible that inflationary or yield-bearing tokens could be collected as fees. One example of an inflationary token is `stETH`. If `stETH` is collected as fees for the contract, the contract's balance of `stETH` will grow over time, even if no more fees in `stETH` are collected. However, the increased balance will not be extractible since the fee amount is recorded at the time the fee was collected and stored in the contract, as shown below: ``` feeAmount = (_receivedAmount * feeBasisPoints) / 10000; if (feeAmount > 0) { accruedFees[_token] += feeAmount; } ``` Thus the `stETH` yield will remain locked in the contract forever.

Open the report
LowOwnership Can Be Renounced31Third · Quantstamp · 1 Mar 2023Fixed

If the owner renounces their ownership, all contracts inheriting from `Ownable` will be left without an owner. Consequently, any function guarded by the `onlyOwner` modifier will no longer be able to be executed. <br><br> Additionally, if ownership were to be revoked, the contracts would lose crucial functionality such as activating or deactivating the batch trading, modifying fees, feeless wallets, and fee recipients, as well as modifying the adapters used in the batch trading.

Open the report
LowTrades Can Be Executed with a Zero Value for `_minToReceive`31Third · Quantstamp · 1 Mar 2023Fixed

31Third relies on the 0x protocol for zero slippage. However, in the instance where an erroneous `Trade` struct is passed to `batchTrade()`, with a `_minToReceive` specified as zero, the trade will still execute normally. This could potentially lead to a loss of user funds, as `from` tokens will be received, but not `to` tokens.

Open the report
Show 1 more
LowZero Amount Transfers when Claiming Fees31Third · Quantstamp · 1 Mar 2023Fixed

`BatchTrade.receiveFees()` does not check if the accrued fees for that asset are not zero. This can lead to zero-amount transfers.

Open the report

Contracts

No deployed address is recorded for these audits.

The reports name a repository or files. Open a report to see its scope.

The repositories and files the reports name

Show this on your site

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.

Content

Facts

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.

Fixed as
Language

Style

Layout
Theme
Accent
Corners

Format

Size
Date
Embed as
HTML
<head>
<script src="https://widget.trustblock.run/project-widget.min.js" defer></script>
</head>
<body>
<div
data-tb-project-widget
data-tb-project-slug="31third-1"
></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