#41855 [SC-Insight] User is able to circumvent blocklist check by utilizing Solidity's implementation
Submitted on Mar 18th 2025 at 21:15:44 UTC by @okmxuse for Attackathon | Movement Labs
Report ID: #41855
Report Type: Smart Contract
Report severity: Insight
Target: https://github.com/immunefi-team/attackathon-movement-layerzero-devtools/tree/main/examples/oft-evm-move-adapters/deploy-eth/src/MOVEOFTAdapter.sol
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Description
Description
When examining move's
OFTAdapter implementation, we observe blocklist checks in both the debit_fungible_asset
and credit
flows, as highlighted below:
debit_fungible_asset
Flow:
assert_not_blocklisted(sender);
credit
Flow:
// Deposit the extracted amount to the recipient, or redirect to the admin if the recipient is blocklisted
primary_fungible_store::transfer(
escrow_signer,
metadata(),
=> redirect_to_admin_if_blocklisted(to, amount_ld),
amount_ld
);
In all cases, these checks ensure that blocklisted users cannot receive or process funds.
However, when analyzing the Solidity implementation, we find no blocklist checks throughout the entire flow, including the in-scope sections. For instance, in _debit
:
function _debit(address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid)
internal
virtual
override
returns (uint256 amountSentLD, uint256 amountReceivedLD)
{
_checkAndUpdateRateLimit(_dstEid, _amountLD);
return super._debit(_from, _amountLD, _minAmountLD, _dstEid);
}
This function is invoked within the send
flow, yet it lacks any blocklist verification.
Impact
Without blocklist enforcement in the Solidity implementation, a blocklisted user can bypass restrictions enforced in the .move
implementation simply by interacting with the Solidity contract.
As a result, a core security mechanism of the protocol—blocking users from sending or receiving bridge funds—is useless.
Recommendation
Include blocklist checks inside the Solidity implementation, this way users are not able to circumvent this core invariant.
Proof of Concept
POC
Bob wants to perform a cross-chain bridge call
Bob is blocklisted however, and is therefore unable to call
debit_fungible_asset
Bob calls solidity's
send
flow which does not perform a blocklist check effectively circumventing this check.Bob is now able to perform the same bridge operation while being blocklisted due to the absence of this check.
Was this helpful?