Owner's ability to bypass USDT recovery timelock
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.