Summary
In the current implementation price
is never changed once set.
In case buyer sent more token to increase escrow pot size, then price
should be updated to contract's token balance so that price would be final price not initial price.
Vulnerability Details
function confirmReceipt() external onlyBuyer inState(State.Created) {
s_state = State.Confirmed;
emit Confirmed(i_seller);
i_tokenContract.safeTransfer(i_seller, i_tokenContract.balanceOf(address(this)));
}
function resolveDispute(uint256 buyerAward) external onlyArbiter nonReentrant inState(State.Disputed) {
uint256 tokenBalance = i_tokenContract.balanceOf(address(this));
uint256 totalFee = buyerAward + i_arbiterFee;
if (totalFee > tokenBalance) {
revert Escrow__TotalFeeExceedsBalance(tokenBalance, totalFee);
}
s_state = State.Resolved;
emit Resolved(i_buyer, i_seller);
if (buyerAward > 0) {
i_tokenContract.safeTransfer(i_buyer, buyerAward);
}
if (i_arbiterFee > 0) {
i_tokenContract.safeTransfer(i_arbiter, i_arbiterFee);
}
tokenBalance = i_tokenContract.balanceOf(address(this));
if (tokenBalance > 0) {
i_tokenContract.safeTransfer(i_seller, tokenBalance);
}
Impact
Price
might not less than final price of audit.
Tools Used
Manual Review
Recommendations
As there's no way to hook transfer event, price
should be updated to balanceOf(address(this))
at confirmReceipt()
, and resolveDispute()
- uint256 private immutable i_price;
+ uint256 private i_price;
function confirmReceipt() external onlyBuyer inState(State.Created) {
s_state = State.Confirmed;
emit Confirmed(i_seller);
- i_tokenContract.safeTransfer(i_seller, i_tokenContract.balanceOf(address(this)));
+ price = i_tokenContract.balanceOf(address(this));
+ i_tokenContract.safeTransfer(i_seller, price);
}
function resolveDispute(uint256 buyerAward) external onlyArbiter nonReentrant inState(State.Disputed) {
uint256 tokenBalance = i_tokenContract.balanceOf(address(this));
uint256 totalFee = buyerAward + i_arbiterFee;
if (totalFee > tokenBalance) {
revert Escrow__TotalFeeExceedsBalance(tokenBalance, totalFee);
}
s_state = State.Resolved;
emit Resolved(i_buyer, i_seller);
if (buyerAward > 0) {
i_tokenContract.safeTransfer(i_buyer, buyerAward);
}
if (i_arbiterFee > 0) {
i_tokenContract.safeTransfer(i_arbiter, i_arbiterFee);
}
- tokenBalance = i_tokenContract.balanceOf(address(this));
+ price = i_tokenContract.balanceOf(address(this));
+ tokenBalance = price - totalFee;
if (tokenBalance > 0) {
i_tokenContract.safeTransfer(i_seller, tokenBalance);
}