Assessment reports>USDT OFT>Informational findings>Owner's ability to bypass USDT recovery timelock
Category: Business Logic

Owner's ability to bypass USDT recovery timelock

Informational Severity
Informational Impact
N/A Likelihood

Description

The owner may use the RecoverUsdtInit and RecoverUsdt opcodes to begin the recovery process of USDT tokens (to send arbitrary amounts) and to recover tokens after the timelock finalizes, respectively.

However, the owner also has the ability to send USDT tokens arbitrarily because of the OApp configuration opcode SetPeer (among others). When receiving a packet from a remote peer, the _assertReceivePath function (and internally _assertUnpackedPath) ensures that the packet is from a trusted peer, as determined by the owner-configured peer mapping:

() _assertUnpackedPath(int srcEid, int srcOApp, int dstEid, int dstOApp) impure inline {
    cell $OAppStorage = getOAppStorage();

    ;; make sure peer exists
    (int peerAddress, int peerExists) = $OAppStorage
        .OApp::getPeers()
        .cl::dict256::get<uint256>(dstEid);

    ;; throw if any part of the path is incorrect
    throw_unless(ERROR::WrongSrcEid, srcEid == $OAppStorage.OApp::getEid());
    throw_unless(ERROR::PeerNotSet, peerExists);
    throw_unless(ERROR::WrongSrcOApp, srcOApp == getContractAddress());
    throw_unless(ERROR::WrongPeer, peerAddress == dstOApp);
}

The owner could simply change the peer address to a malicious EID and OApp configuration to send an arbitrary withdrawal packet (receiveOFT), thereby bypassing the USDT recovery timelock. Additionally, the owner could falsify a credit-receiving packet (receiveCredits) and then use the OP::WithdrawLocal or OP::WithdrawRemote opcodes to withdraw using the false liquidity.

Other LayerZero configuration functions may enable the same bypass (e.g., configuring DVNs maliciously) as well.

Impact

The owner can immediately bypass the USDT recovery timelock to send arbitrary amounts of USDT tokens (limited by the contractBalance but not constrained by any credit balance).

The severity is limited because the owner has the ability to change the planner address. An owner could send credits from other chains and then use the OP::WithdrawLocal or OP::WithdrawRemote opcodes.

Recommendations

Note that the owner's ability to configure the OApp is a feature intended to support future LayerZero upgrades, including security fixes and new features as technology advances. However, the ability to configure the OApp introduces centralization risk. It is up to LayerZero Labs to determine what risk is acceptable.

If LayerZero Labs determines that the ability for the owner to send USDT arbitrarily without a timelock is unacceptable, the configuration functions should include the same timelock requirement as the USDT recovery process. Otherwise, consider removing the timelock altogether for simplicity and to avoid a false reassurance about the centralization risks.

As a side note, consider checking whether the admin_address of the USDT minter contract (out of scope) is controlled by the same entity as the owner. If so, then the owner can directly mint, defeating the purpose of these credit checks in withdrawLocal, withdrawRemote, and the timelock on the recovery functions in the first place.

Remediation

Zellic © 2025Back to top ↑