# ERC721Pool's take will proceed with truncated collateral amount and full debt when borrower's collateral is fractional

ERC721Pool take() pays debt for fractional borrower collateral but delivers only truncated whole-NFT amount, gifting the remainder to the borrower at taker's expense.

- Payout: Contest reward
- Severity: high
- Program: Ajna
- Credited: hyh
- Disclosed: 2022-12-21
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-01-ajna-judging/issues/68
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-01-ajna%3AH-10
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:precision-loss

**Target:** ERC721Pool take()/bucketTake() auction settlement in Auctions.sol
**Root cause:** bucketTake() subtracts an unrounded fractional collateral amount from borrower.collateral, leaving an 18dp fraction; _take() then computes debt off min(params_.collateral, takeCollateral) but truncates collateralTaken to whole 1e18 units without refunding the difference.
**Steps:**
1. Call bucketTake() on an ERC721Pool borrower so borrower.collateral becomes fractional (e.g. 1.9e18).
2. Call ERC721Pool.take(borrower, 2, ...) which passes takeCollateral = 2e18 and params_.collateral = 1.9e18.
3. Observe _calculateTakeFlowsAndBondChange uses min = 1.9e18 to compute debt owed.
4. Observe collateralTaken = (1.9e18/1e18)*1e18 = 1e18; rounding-up branch skipped since params_.collateral < collateralTaken + 1e18.
5. Taker pays debt for 1.9 collateral but receives only 1.0; 0.9 remains with borrower.
**How found:** Code review of _take()'s ERC721 rounding branch, noticing the rounding-up path is gated on params_.collateral >= collateralTaken + 1e18, and tracing that params_.collateral = borrower.collateral can be fractional because bucketTake() subtracts an unrounded result.
**Exploitation:** Taker (or any caller) invokes take() on a borrower whose collateral was left fractional by a prior partial bucketTake(); the taker overpays quote tokens for debt corresponding to the fractional collateral while receiving only the truncated whole-NFT amount, with the fractional remainder retained by the borrower.
**Insight:** When a rounding-up branch is conditional on the source value being large enough, check whether that source value can itself be fractional from another code path (here bucketTake's unrounded subtraction); ERC721 collateral accounting must stay in whole-token units at every mutation.
