Bidder can cheat auction by placing bid much higher than reserve price when there are still open liens against a token
When a token still has open liens against it only the value of the liens will be paid by the bidder but their current bid will be set to the full value of the bid. This can be abused in one of two ways. The bidder could place a massive bid like 500 ETH that will never be outbid or they could place a bid they know will outbid and profit the difference when they're sent a refund.\\n```\\nuint256[] memory liens = LIEN_TOKEN.getLiens(tokenId);\\nuint256 totalLienAmount = 0;\\nif (liens.length > 0) {\\n  for (uint256 i = 0; i < liens.length; ++i) {\\n    uint256 payment;\\n    uint256 lienId = liens[i];\\n\\n    ILienToken.Lien memory lien = LIEN_TOKEN.getLien(lienId);\\n\\n    if (transferAmount >= lien.amount) {\\n      payment = lien.amount;\\n      transferAmount -= payment;\\n    } else {\\n      payment = transferAmount;\\n      transferAmount = 0;\\n    }\\n    if (payment > 0) {\\n      LIEN_TOKEN.makePayment(tokenId, payment, lien.position, payer);\\n    }\\n  }\\n} else {\\n  //@audit-issue logic skipped if liens.length > 0\\n  TRANSFER_PROXY.tokenTransferFrom(\\n    weth,\\n    payer,\\n    COLLATERAL_TOKEN.ownerOf(tokenId),\\n    transferAmount\\n  );\\n}\\n```\\n\\nWe can examine the payment logic inside `_handleIncomingPayment` and see that if there are still open liens against then only the amount of WETH to pay back the liens will be taken from the payer, since the else portion of the logic will be skipped.\\n```\\nuint256 vaultPayment = (amount - currentBid);\\n\\nif (firstBidTime == 0) {\\n  auctions[tokenId].firstBidTime = block.timestamp.safeCastTo64();\\n} else if (lastBidder != address(0)) {\\n  uint256 lastBidderRefund = amount - vaultPayment;\\n  _handleOutGoingPayment(lastBidder, lastBidderRefund);\\n}\\n_handleIncomingPayment(tokenId, vaultPayment, address(msg.sender));\\n\\nauctions[tokenId].currentBid = amount;\\nauctions[tokenId].bidder = address(msg.sender);\\n```\\n\\nIn `createBid`, `auctions[tokenId].currentBid` is set to `amount` after the last bidder is refunded and the excess is paid against liens. We can walk through an example to illustrate this:\\nAssume a token with a single lien of amount 10 WETH and an auction is opened for that token. Now a user places a bid for 20 WETH. They are the first bidder so `lastBidder = address(0)` and `currentBid = 0`. `_handleIncomingPayment` will be called with a value of 20 WETH since there is no lastBidder to refund. Inside `_handleIncomingPayment` the lien information is read showing 1 lien against the token. Since `transferAmount >= lien.amount`, `payment = lien.amount`. A payment will be made by the bidder against the lien for 10 WETH. After the payment `_handleIncomingPayment` will return only having taken 10 WETH from the bidder. In the next line currentBid is set to 20 WETH but the bidder has only paid 10 WETH. Now if they are outbid, the new bidder will have to refund then 20 WETH even though they initially only paid 10 WETH.
In `_handleIncomingPayment`, all residual transfer amount should be sent to `COLLATERAL_TOKEN.ownerOf(tokenId)`.
Bidder can steal funds due to `_handleIncomingPayment` not taking enough WETH
```\\nuint256[] memory liens = LIEN_TOKEN.getLiens(tokenId);\\nuint256 totalLienAmount = 0;\\nif (liens.length > 0) {\\n  for (uint256 i = 0; i < liens.length; ++i) {\\n    uint256 payment;\\n    uint256 lienId = liens[i];\\n\\n    ILienToken.Lien memory lien = LIEN_TOKEN.getLien(lienId);\\n\\n    if (transferAmount >= lien.amount) {\\n      payment = lien.amount;\\n      transferAmount -= payment;\\n    } else {\\n      payment = transferAmount;\\n      transferAmount = 0;\\n    }\\n    if (payment > 0) {\\n      LIEN_TOKEN.makePayment(tokenId, payment, lien.position, payer);\\n    }\\n  }\\n} else {\\n  //@audit-issue logic skipped if liens.length > 0\\n  TRANSFER_PROXY.tokenTransferFrom(\\n    weth,\\n    payer,\\n    COLLATERAL_TOKEN.ownerOf(tokenId),\\n    transferAmount\\n  );\\n}\\n```\\n