RTLabs security record

Arbitrum, Base, Solanademether.ioXGitHub

As of 30 Oct 2026, RTLabs has 2 audit reports by 1 security firm on Trustblock; the latest is by Resonance Security, dated 7 Feb 2025. Those reports list no open critical findings.

Critical findings
No open critical findings
Across the 2 reports, 1 critical finding was reported. It is marked fixed by the firm that reported it. See the findings
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 Oct 2026. Trustblock does not review code.

Audits2

Newest first

AuditSecurity firmDateScopeCritical findingsReport
RTLabsSecurity firm: Resonance SecurityDate: Scope: Not recorded (see the report)No open critical findingsOpen · IPFS
RTLabsSecurity firm: Resonance SecurityDate: Scope: Not recorded (see the report)1 critical finding, fixedOpen · IPFS

Findings18

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

SeverityOpenAcknowledgedFixed
Critical001
High001
Medium005
Low308
CriticalNo Threshold Or Heartbeat Update Mechanisms Implemented To Combat StalenessRTLabs · Resonance Security · 31 Aug 2024Fixed

The protocol implements bridging features between layer-1 and layer-2 blockchains to sync the rate at which shares of tokens are minted for the users. By calling the function syncRate() on the contract DepositsManagerL1, a message is sent to several layer-2 chains to sync their rates with the new rate calculated on the layer-1 chain. On the layer-2 chains, when such a message is received, the rate is updated while the variable rateSyncBlock tracks the last block of when the updated occurred.When minting tokens on a layer-2 chain, the function getConversionAmount() is called to calculate how many shares of the token should be minted for the user based on the current rate. The only verification being made simply guarantees that a single rate update was performed in the past. It does not guarantee that the rate is up to date. This opens up the possibility of financial attacks by malicious users that can take advantage of stale rates to take advantages during minting.

Open the report
HighPayable Function May Lead To Minting Of Less TokensRTLabs · Resonance Security · 31 Aug 2024Fixed

The function deposit() is marked as payable, allowing for transfer of native Ether into the smart contract. This function further calls the internal function _deposit() while providing _amountIn as an input parameter. This effectively means that the amount of minted tokens for the user will solely depend on the provided input parameter _amountIn. If the user mistakenly sends Ether when calling this function, they will not be able to mint those funds as tokens.

Open the report
MediumInsufficient Validation Of _feeRTLabs · Resonance Security · 31 Aug 2024Fixed

The fees used within the protocol are not sufficiently validated, and are therefore not restrictive enough of their upper and lower bounds. The fees can both be set to the max value and to the value 0, both of them being dangerous to the protocol that can eventually cause loss of funds, or confidence from users of the platform.

Open the report
MediumMissing Setter For Variable _minterRTLabs · Resonance Security · 31 Aug 2024Fixed

The variable _minter does not implement a setter function. If the entity responsible for controlling the address pointed by the variable _minter becomes compromised, the entire protocol may be at risk, and may ultimately lead to total loss of funds.

Open the report
MediumPossible To Bypass DepositsManager And Call LiquidityPool functions directlyRTLabs · Resonance Security · 31 Aug 2024Fixed

The Demether protocol defines a specific intended flow for adding liquidity to the protocol. Namely, in order to deposit ETH, users will need to call the depositETH function implemented in the DepositsManagerL1 contract. This function implements appropriate checks, fee calculation and token minting before it calls the addLiquidity function defined in the LiquidityPool contract. The addLiquidity function is mostly responsible for creating shares in the LiquidityPool contract. However, the addLiquidity function does not implement any access control that would allow it to be executed only if called by DepositsManagerL1 contract. As a consequence, anyone can call the addLiquidity function directly effectively bypassing the accounting done in DepositsManagerL1.Similarly, the processLiquidity function defined in the LiquidityPool contract can be called directly, without calling the processLiquidity function defined in the DepositsManagerL1 contract.

Open the report
MediumSending _fee On Local Minting May Cause Loss Of DETHRTLabs · Resonance Security · 31 Aug 2024Fixed

The local minting feature of both DepositsManagerL1 and DepositsManagerL2 contracts does not require a fee, since the fee should only be used for bridging purposes. However, it is possible to send a non-zero fee via the input parameter _fee, effectively allowing for users to lose unnecessary funds.

Open the report
MediumUnnecessary Usage Of receive() FunctionRTLabs · Resonance Security · 31 Aug 2024Fixed

The LiquidityPool contract is implementing a receive function. This indicates that this contract can successfully receive a native balance transfer. However, the fact that this receive implementation is actually empty makes such transfers be out-of-flow. Such transfers can lead to vulnerabilities related to the accounting in the extreme cases. However, they also can cause an inherent loss for any legitimate user who was tricked or made a genuine mistake. Such transfers will not be accounted for accordingly by the contracts so users will lose their native tokens without being able to use the protocol.

Open the report
LowIncorrect Function Visibility of Initializing FunctionsRTLabs · Resonance Security · 31 Aug 2024Fixed

Smart contract upgradeability using OpenZeppelin's standard, requires contracts to use initializer functions. The function to use on child contract should be named initialize() and should possess the initializer modifier, while parent contracts should have _init() and _init_unchained() functions with the modifier onlyInitializing, where there would otherwise be constructors called automatically on non-upgradeable smart contracts.The initializer functions on the parent smart contracts are meant to be initialized by the child contract, as such, their visibility can be constrained to internal. The following functions do not implement the proper visibility to encourage a principle of least privilege:The visibility of the function __OwnableAccessControl_init() is incorrectly set as public.

Open the report
LowIncorrect Usage Of Function __Ownable_init()RTLabs · Resonance Security · 31 Aug 2024Fixed

The function initialize() on the upgradeable smart contract LiquidityPool does not call its parent's OwnableAccessControl initializer function __OwnableAccessControl_init(). Instead, it is calling __Ownable_init().While it is possible to call some parents' initializer functions out of order or higher in the inheritance chain, it is not recommended to do so as it will lead to development errors and undefined behavior within the protocol.

Open the report
LowIncorrect Usage Of Initializing FunctionsRTLabs · Resonance Security · 31 Aug 2024Fixed

The functions _init() and _init_unchained() are an implementation of OpenZeppelin's Upgradeable Proxies design standard and are used to serve as the constructor of upgradeable contracts. Despite being both used as initializers, they possess slightly different use cases to correctly implement the analog linearization of smart contract constructors.The function _init() should be used and implemented to embed the linearized calls to all parent initializers. The function _init_unchained() should be used to perform the initialization of the variables for the current contract only.As a consequence of this design, it is possible that, due to the lack of automatic linearization, the calling of _init() functions initializes the same contract multiple times. For these cases, the _init_unchained() function may be used manually to avoid double initialization, however it will break the upgradeability design and compatibility between smart contracts on the blockchain.Additionally, the inherited smart contracts should be initialized according to their inheritance order, from the most base-like to the most derived.There are multiple instances where contracts do not follow the design standard in the following account:_init_unchained() function is not used.Initialization according to inheritance order is incorrect

Open the report
Show 5 more
LowMissing Validation Of msg.valueRTLabs · Resonance Security · 31 Aug 2024Fixed

The function depositETH() does not validate the Ether received from the user identified within the global variable msg.value. This variable is then used in an arithmetic operation along with another input variable _fee, which is controlled by the user. This effectively means that it may be possible for a user to trigger an integer underflow condition.

Open the report
LowMissing Zero Address Validation Of messengerRTLabs · Resonance Security · 31 Aug 2024Fixed

Throughout the DepositsManagerL2 smart contract the messenger state variable is used to perform external calls. However, this variable is not validated against the Zero Address, allowing for undefined behavior within the protocol.

Open the report
LowMissing Zero Address Validation Of sfrxETHRTLabs · Resonance Security · 31 Aug 2024Fixed

Throughout the LiquidityPool smart contract the sfrxETH state variable is used to perform external calls. However, this variable is not validated against the Zero Address, allowing for undefined behavior within the protocol.

Open the report
LowMissing Zero Address Validation Of tokenRTLabs · Resonance Security · 31 Aug 2024Fixed

Throughout the DepositsManagerL1 and DepositsManagerL2 smart contracts the token state variable is used to perform external calls. However, this variable is not validated against the Zero Address, allowing for undefined behavior within the protocol.

Open the report
LowRedundant Code On Arithmetic OperationsRTLabs · Resonance Security · 31 Aug 2024Fixed

Throughout the source code of the protocol, there are several instances where uint256 variables are being compared to 0. The comparison of these variables being lesser than or equal to 0 is redundant as uint256 variables can only contain 0 or positive values.

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.

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="rtlabs"
></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