DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: low
Invalid

Possible Dust Attack Vulnerability in TradingAccountBranch Contract

Summary

The TradingAccountBranch contract is susceptible to dust attacks due to the absence of minimum deposit and withdrawal limits, as well as the lack of transaction rate limiting. This vulnerability could potentially be exploited to degrade contract performance, increase gas costs for other users, and manipulate market dynamics.

Vulnerability Details

The depositMargin and withdrawMargin functions allow for transactions of any non-zero amount. There is no mechanism to limit the frequency of transactions for a single account and it uses complex financial calculations that could potentially be manipulated by many small transactions.

function depositMargin(uint128 tradingAccountId, address collateralType, uint256 amount) public virtual {// ...UD60x18 amountX18 = marginCollateralConfiguration.convertTokenAmountToUd60x18(amount);_requireAmountNotZero(amountX18);// ...}
function withdrawMargin(uint128 tradingAccountId, address collateralType, uint256 amount) external {// ...UD60x18 amountX18 = marginCollateralConfiguration.convertTokenAmountToUd60x18(amount);_requireAmountNotZero(amountX18);// ...}
function _requireAmountNotZero(UD60x18 amount) internal pure {if (amount.isZero()) {revert Errors.ZeroInput("amount");}}

Impact

Numerous small transactions can increase the gas costs for all users interacting with the contract.

  • State Bloat: Many small balance entries could bloat the contract's state, leading to higher operational costs over time.

  • Economic Attacks: Potential manipulation of market dynamics or exploitation of rounding errors in financial calculations.

  • Griefing: An attacker could use dust transactions to congest the network or make the contract less usable for legitimate users.

  • Performance Degradation: Processing many small transactions could lead to decreased performance of the contract and associated systems.

Tools Used

Manual code review

Recommendations

  • Implement minimum deposit and withdrawal amounts for each collateral type.

  • These minimums should be configurable by the contract owner to allow for adjustments based on market conditions.

  • Add a cooldown period between transactions for each account.

  • This prevents rapid successive small deposits or withdrawals from a single account.

  • Strengthen input validation to reject transactions that don't meet the new criteria.

contract TradingAccountBranch {
mapping(address => UD60x18) public minDepositAmount;
mapping(address => UD60x18) public minWithdrawAmount;
uint256 public constant TRANSACTION_COOLDOWN = 1 hours;
mapping(uint128 => uint256) public lastTransactionTimestamp;
function setMinimumAmounts(address collateralType, UD60x18 minDeposit, UD60x18 minWithdraw) external onlyOwner {
minDepositAmount[collateralType] = minDeposit;
minWithdrawAmount[collateralType] = minWithdraw;
}
function depositMargin(uint128 tradingAccountId, address collateralType, uint256 amount) public virtual {
UD60x18 amountX18 = marginCollateralConfiguration.convertTokenAmountToUd60x18(amount);
_requireAmountNotZero(amountX18);
_requireMinimumAmount(amountX18, minDepositAmount[collateralType], "deposit");
_enforceTransactionCooldown(tradingAccountId);
// ... rest of the function ...
lastTransactionTimestamp[tradingAccountId] = block.timestamp;
}
function withdrawMargin(uint128 tradingAccountId, address collateralType, uint256 amount) external {
UD60x18 amountX18 = marginCollateralConfiguration.convertTokenAmountToUd60x18(amount);
_requireAmountNotZero(amountX18);
_requireMinimumAmount(amountX18, minWithdrawAmount[collateralType], "withdrawal");
_enforceTransactionCooldown(tradingAccountId);
// ... rest of the function ...
lastTransactionTimestamp[tradingAccountId] = block.timestamp;
}
function _requireMinimumAmount(UD60x18 amount, UD60x18 minAmount, string memory operation) internal pure {
if (amount.lt(minAmount)) {
revert Errors.BelowMinimumAmount(amount.intoUint256(), minAmount.intoUint256(), operation);
}
}
function _enforceTransactionCooldown(uint128 tradingAccountId) internal view {
require(block.timestamp >= lastTransactionTimestamp[tradingAccountId] + TRANSACTION_COOLDOWN, "Cooldown period not elapsed");
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

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