hals - `_cancelOrderAccounting` in `SellOrderPeocessor` contract will revert if the `orderRequest.recipient` is a blacklisted account in `BridgedERC20` dShare token #69
_cancelOrderAccounting in SellOrderPeocessor contract will revert if the orderRequest.recipient is a blacklisted account in BridgedERC20 dShare token
Summary
_cancelOrderAccounting in SellOrderPeocessor contract will revert if the orderRequest.recipient is a blacklisted account in BridgedERC20 dShare token
Vulnerability Detail
In SellOrderProcessor contract: users are selling their dShare tokens (BridgedERC20) for paymentToken in return (which is USDC or USDT).
But dShare token (BridgedERC20) has a _beforeTokenTransfer hook that checks if the sender or the receiver of the tokens is blacklisted account or not, if blacklisted; the transfer will revert.
And since there's no check when creating a sellOrder if the orderRequest.recipient (the one who will receive the remaining dShare tokens when the sellOrder is cancelled) is a blacklisted account in BridgedERC20 dShare token or not: then when the operator tries to cancel the sell order by calling cancelOrder function in OrderProcessor contract; the _cancelOrderAccounting function will revert if the recipient is a blacklisted account.
Impact
This will prevent operators from deleting the invalid and un-fulfillabl sellOrders, or deleting the sellOrder as per the request of OrderState.requester (the one who adds the order) , so the assetToken (and paymentToken if the order is partially filled) of the order paid by the OrderState.requester will be stuck (unless manually sent to the requester).
Code Snippet
In SellOrderPeocessor.sol/ _cancelOrderAccounting function: Line 150
Line 150: IERC20(orderRequest.assetToken).safeTransfer(orderRequest.recipient, refund);
In BridgedERC20.sol/ _beforeTokenTransfer hook: L127-L136
function _beforeTokenTransfer(address from, address to, uint256) internal virtual override {
// Restrictions ignored for minting and burning
// If transferRestrictor is not set, no restrictions are applied
if (from == address(0) || to == address(0) || address(transferRestrictor) == address(0)) {
return;
}
// Check transfer restrictions
transferRestrictor.requireNotRestricted(from, to);
}
In TransferRestrictor .sol/ requireNotRestricted function: L53-L59
function requireNotRestricted(address from, address to) external view virtual {
// Check if either account is restricted
if (blacklist[from] || blacklist[to]) {
revert AccountRestricted();
}
// Otherwise, do nothing
}
Tool used
Manual Review
Recommendation
In OrderProcessor contract/requestOrder function:
check if the orderRequest.recipient is not dShare token blacklisted account before adding a sellOrder to the platform.
hals
medium
_cancelOrderAccounting
inSellOrderPeocessor
contract will revert if theorderRequest.recipient
is a blacklisted account inBridgedERC20
dShare tokenSummary
_cancelOrderAccounting
inSellOrderPeocessor
contract will revert if theorderRequest.recipient
is a blacklisted account inBridgedERC20
dShare tokenVulnerability Detail
In
SellOrderProcessor
contract: users are selling their dShare tokens (BridgedERC20
) forpaymentToken
in return (which is USDC or USDT).But dShare token (
BridgedERC20
) has a_beforeTokenTransfer
hook that checks if the sender or the receiver of the tokens is blacklisted account or not, if blacklisted; the transfer will revert.And since there's no check when creating a
sellOrder
if theorderRequest.recipient
(the one who will receive the remaining dShare tokens when the sellOrder is cancelled) is a blacklisted account inBridgedERC20
dShare token or not: then when the operator tries to cancel the sell order by callingcancelOrder
function inOrderProcessor
contract; the_cancelOrderAccounting
function will revert if the recipient is a blacklisted account.Impact
This will prevent operators from deleting the invalid and un-fulfillabl sellOrders, or deleting the sellOrder as per the request of
OrderState.requester
(the one who adds the order) , so theassetToken
(andpaymentToken
if the order is partially filled) of the order paid by theOrderState.requester
will be stuck (unless manually sent to the requester).Code Snippet
SellOrderPeocessor.sol
/_cancelOrderAccounting
function: Line 150BridgedERC20.sol
/_beforeTokenTransfer
hook: L127-L136TransferRestrictor .sol
/requireNotRestricted
function: L53-L59Tool used
Manual Review
Recommendation
In
OrderProcessor
contract/requestOrder
function: check if theorderRequest.recipient
is not dShare token blacklisted account before adding a sellOrder to the platform.Duplicate of #55