Algo Ssstablecoinsss

AI First Flight #2
Beginner FriendlyDeFi
EXP
View results
Submission Details
Impact: high
Likelihood: medium
Invalid

Fee-on-transfer or rebasing collateral over-credits the depositor by recording the requested amount instead of the amount received

Fee-on-transfer / rebasing collateral over-credits the depositor because deposit records the requested amount, not the amount received

Description

_deposit_collateral credits the user's balance with amount_collateral and only afterwards pulls the tokens via transferFrom, never measuring how much the contract actually received.

# dsc_engine.vy:223-229 (_deposit_collateral)
self.user_to_token_address_to_amount_deposited[msg.sender][
token_collateral_address
] += amount_collateral # @> credits requested amount, not received
log CollateralDeposited(msg.sender, amount_collateral)
success: bool = extcall IERC20(token_collateral_address).transferFrom(
msg.sender, self, amount_collateral
)

For a fee-on-transfer token the contract receives amount_collateral - fee, but the depositor is credited the full amount_collateral. The internal accounting now exceeds the engine's real token balance.

Risk

Likelihood:
Medium. Fee-on-transfer and rebasing tokens are common; the constructor accepts any token address with no exclusion.

Impact:
High. The depositor is credited collateral the protocol never received, inflating their borrowing power and letting them mint DSC against phantom value. When users redeem, the last redeemers' transfer reverts because the engine is short on tokens, locking funds — a direct over-credit / theft of value from other depositors.

Proof of Concept

Deposit a 2%-fee token and compare credited vs received.

# token charges 2% transfer fee
engine.deposit_collateral(fee_token, 100 * 10**18)
# contract received 98e18 but user credited 100e18
assert engine.get_collateral_balance_of_user(user, fee_token) == 100 * 10**18 # over-credited

Recommended Mitigation

Credit the measured balance delta, not the requested amount.

- self.user_to_token_address_to_amount_deposited[msg.sender][
- token_collateral_address
- ] += amount_collateral
- log CollateralDeposited(msg.sender, amount_collateral)
- success: bool = extcall IERC20(token_collateral_address).transferFrom(
- msg.sender, self, amount_collateral
- )
+ balance_before: uint256 = staticcall IERC20(token_collateral_address).balanceOf(self)
+ success: bool = extcall IERC20(token_collateral_address).transferFrom(msg.sender, self, amount_collateral)
+ assert success, "DSCEngine_TransferFailed"
+ received: uint256 = staticcall IERC20(token_collateral_address).balanceOf(self) - balance_before
+ self.user_to_token_address_to_amount_deposited[msg.sender][token_collateral_address] += received
+ log CollateralDeposited(msg.sender, received)
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 5 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!