Protocol does not work correctly with tokens that do not revert on failed transfer
withdrawERC20 and _processERC20Payment use plain transfer / transferFrom calls. Non-standard tokens like USDT do not return booleans on failure, so silent failures cause inaccurate accounting or stuck funds.
Description
Some tokens do not implement the ERC20 standard properly but are still accepted by most code that accepts ERC20 tokens. For example, Tether (USDT)'s transfer() and transferFrom() functions on L1 do not return booleans as the specification requires and instead have no return value. With the current code, if such a call fails but does not revert it will result in inaccurate calculations or funds stuck in the protocol.
/// @notice Withdraws all of a specific ERC20 token held by the contract to the owner's address/// @param _token The ERC20 token address/// @dev This function can only be called by the contract ownerfunction withdrawERC20(address _token) public onlyOwner {IERC20 token = IERC20(_token);token.transfer(owner(), token.balanceOf(address(this)));}
/// @notice Processes an ERC20 payment for the subscriptionfunction _processERC20Payment(SubStorage storage sub) internal {IERC20 token = IERC20(sub.erc20Token);uint256 balance = token.balanceOf(address(this));require(balance >= sub.amount, "Insufficient token balance");token.transferFrom(address(this), sub.initiator, sub.amount);}
Impact
For tokens that do not revert on failed transfer (e.g. USDT), silent failures can leave the protocol in an inconsistent state, with payments appearing successful while no funds actually moved.
Recommendation
Use OpenZeppelin's SafeERC20 library and its safe methods for ERC20 transfers.
Resolution
Team Response: Acknowledged and fixed as suggested.

