Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
Submission Details
Severity: medium
Invalid

Not using SafeERC20 prevents some tokens' usability with Treasury contract

Author Revealed upon completion

Summary

The Treasurycontract (contracts/core/collectors/Treasury.sol) uses IERC20's transfer() and transferFrom(), which won't work for certain tokens like USDT.

Vulnerability Details

The documentation () states that the Treasury contract has multi-token support. But it won't support all the tokens.

  • Inside Treasury::deposit function, IERC20(token).transferFrom() is being called, and inside Treasury::withdraw function, IERC20(token).transfer() is called.

  • Old ERC20 tokens like USDT don't return bool upon calling these two functions, causing these calls to revert due to incompatibility. So any deposit or withdraw of those tokens would fail.

Impact

  • USDT or other tokens that slightly differ from the latest ERC-20 specs wouldn't be able to be managed by the Treasury contract.

Tools Used

Manual review

Recommendations

Use SafeERC20 library. Here is the full diff which can be applied to Treasury.sol:

diff --git a/contracts/core/collectors/Treasury.sol b/contracts/core/collectors/Treasury.sol
index fc8cad6..23709a8 100644
--- a/contracts/core/collectors/Treasury.sol
+++ b/contracts/core/collectors/Treasury.sol
@@ -2,6 +2,7 @@
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "../../interfaces/core/collectors/ITreasury.sol";
@@ -17,6 +18,8 @@ import "../../interfaces/core/collectors/ITreasury.sol";
* - Fund allocation system
*/
contract Treasury is ITreasury, AccessControl, ReentrancyGuard {
+ using SafeERC20 for IERC20;
+
// Access control roles
bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); // Can withdraw funds
bytes32 public constant ALLOCATOR_ROLE = keccak256("ALLOCATOR_ROLE"); // Can allocate funds
@@ -47,7 +50,7 @@ contract Treasury is ITreasury, AccessControl, ReentrancyGuard {
if (token == address(0)) revert InvalidAddress();
if (amount == 0) revert InvalidAmount();
- IERC20(token).transferFrom(msg.sender, address(this), amount);
+ IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
_balances[token] += amount;
_totalValue += amount;
@@ -72,7 +75,7 @@ contract Treasury is ITreasury, AccessControl, ReentrancyGuard {
_balances[token] -= amount;
_totalValue -= amount;
- IERC20(token).transfer(recipient, amount);
+ IERC20(token).safeTransfer(recipient, amount);
emit Withdrawn(token, amount, recipient);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 9 days ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

[INVALID] SafeERC20 not used

LightChaser Low-60

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.