DeFiFoundry
20,000 USDC
View results
Submission Details
Severity: medium
Valid

Token Lock in Factory Due to Misaligned Ownership in Auction Contract

Summary

A critical vulnerability has been identified in the auction system where unsold tokens can become locked in the factory contract due to incorrect ownership assignment in the auction contract. This occurs because the auction contract sets its owner to the factory address instead of the original auction creator, leading to potential permanent loss of tokens in no-bid scenarios.

Vulnerability Details

The vulnerability stems from the following factors:

  1. The AuctionFactory.createAuction function deploys a new auction contract.

  2. The auction contract's constructor sets owner = msg.sender.

  3. In this context, msg.sender is the factory contract address, not the original caller of createAuction.

  4. When an auction ends with no bids, tokens are returned to the owner.

  5. As a result, unsold tokens are sent to the factory contract instead of the auction creator.

Impact

The impact of this vulnerability is severe:

  1. Financial Loss: Auction creators will permanently lose access to their tokens if no bids are placed.

  2. Trust Issues: This could lead to a loss of trust in the auction system and the broader platform.

  3. Locked Assets: A significant amount of tokens could accumulate in the factory contract, becoming inaccessible, due to the fact there is no way to withdraw tokens from the factory.

  4. System Dysfunction: The auction system fails to function as intended, not returning tokens to their rightful owners.

Tools Used

Manual code review

Recommendations

Modify Factory Contract: Update AuctionFactory.createAuction to pass the original caller's address

Modify Auction contract to accept owner parameter in the constructor.

constructor(
address _fjordPoints,
address _auctionToken,
uint256 _biddingTime,
uint256 _totalTokens,
address _owner
) {
// .... other code
owner = _owner;
// .... other code
}

PoC

forge test --match-test test_owner -vvvv

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity =0.8.21;
import {Test, console2} from "forge-std/Test.sol";
import {AuctionFactory} from "../../src/FjordAuctionFactory.sol";
import {FjordAuction} from "../../src/FjordAuction.sol";
import {FjordPoints} from "../../src/FjordPoints.sol";
import {ERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol";
contract ERC20BurnableMock is ERC20, ERC20Burnable {
constructor(
string memory name_,
string memory symbol_
) ERC20(name_, symbol_) {}
function mint(uint amount) external {
_mint(msg.sender, amount);
}
}
contract AuctionTest is Test {
FjordPoints points;
AuctionFactory factory;
function setUp() public {
points = new FjordPoints();
factory = new AuctionFactory(address(points));
}
function test_owner() public {
ERC20BurnableMock auctionToken = new ERC20BurnableMock("Token", "T");
auctionToken.mint(100 ether);
auctionToken.approve(address(factory), 100 ether);
FjordAuction auction = FjordAuction(
factory.createAuction(
address(auctionToken),
1 days,
100 ether,
bytes32("3.14")
)
);
vm.warp(1 days + 1 seconds);
// factory has no tokens
assertEq(auctionToken.balanceOf(address(factory)), 0);
auction.auctionEnd();
// factory owns all the tokens
assertEq(auctionToken.balanceOf(address(factory)), 100 ether);
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

If no bids are placed during the auction, the `auctionToken` will be permanently locked within the `AuctionFactory`

An auction with 0 bids will get the `totalTokens` stuck inside the contract. Impact: High - Tokens are forever lost Likelihood - Low - Super small chances of happening, but not impossible

Support

FAQs

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