F-2024-0001·unchecked-return-value

Implement Safe Transfer Methods for ERC20 Tokens

Acknowledgedvaulthealthfipoints
TL;DR

The vault calls ERC20 transfer functions without checking return values. Non-standard tokens like USDT silently fail and break vault accounting across six entry points.

Severity
MEDIUM
Impact
MEDIUM
Likelihood
MEDIUM
Method
MManual review
CAT.
Complexity
LOW
Exploitability
MEDIUM
02Section · Description

Description

The error pertains to an Unchecked Transfer vulnerability in the code. This error arises when the return value of an external transfer call is not checked.

The return value of an external transfer call is not checked. Several tokens do not revert in case of failure and instead return false. Without checking the return value, the contract may assume a successful transfer even if it fails, leading to potential exploits.

The protocol aims to support all ERC20 tokens but uses the original transfer functions. Some tokens, like USDT, do not implement the EIP20 standard correctly and their transfer/transferFrom function return void instead of a success boolean. Calling these functions with the correct EIP20 function signatures will revert.

03Section · Impact

Impact

Not checking the return value of transfer calls can result in incorrect balances and allow attackers to perform operations that should fail. For example, an attacker could call deposit without transferring tokens, gaining an incorrect balance. Tokens that do not correctly implement EIP20, like USDT, will revert transactions, making them unusable in the protocol.

The following call sites are affected:

  • vault.withdrawfees(address) (src/ribbonVault.sol#145)
  • vault.claimPointsAdmin(address,uint256) (src/ribbonVault.sol#152)
  • vault.swapToPaymentCoinAdmin(address,uint256) (src/ribbonVault.sol#166, 167)
  • vault.permitClaimPoints(address,uint256,uint256,uint8,bytes32,bytes32) (src/ribbonVault.sol#177)
  • vault.permitSwapToPaymentCoin(address,uint256,uint256,uint8,bytes32,bytes32) (src/ribbonVault.sol#193, 194)
  • vault.emergencyWithdraw(address,address,uint256) (src/ribbonVault.sol#201)
04Section · Recommendation

Recommendation

Ensure return values of transfer calls are checked. Use libraries like SafeERC20 or manually check the return values in the code.

  • Use the SafeERC20 library to handle token transfers safely and ensure all return values are checked.
  • Manually check the return values of transfer calls.
  • Update the protocol to handle non-standard-compliant tokens using OpenZeppelin's SafeERC20 versions with safeTransfer and safeTransferFrom functions.
F-2024-0001

oog
zealynx

Smart Contract Security Digest

Monthly exploit breakdowns, audit checklists, and DeFi security research — straight to your inbox

© 2026 Zealynx