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

FjordAuction: All the auction tokens will get permanently locked in the factory contract due to incorrect ownership assumption of the auction contracts

Summary

This report demonstrates the bug that is caused by the incorrect assumption of the owner address. I will be demonstrating how all the auction tokens will get permanently locked in the factory contract.

Vulnerability Details

If the totalBids are 0 at the end of the auction, all the auction tokens in the FjordAuction contract get transferred back to the owner of FjordAuction contract.

function auctionEnd() external {
...
if (totalBids == 0) {
auctionToken.transfer(owner, totalTokens);
return;
}
...
}

How is the owner in FjordAuction proposed ?

constructor(/*@params*/) {
...
owner = msg.sender;
...
}

whoever deploys it, becomes its owner.

Since AuctionFactory contract is used to deploy auction contracts. The problem arizes when the owner triggers createAuction(/*@params*/), the deployer in the context of auction contract becomes the factory contract itself not the msg.sender -> factory_owner

function createAuction(/*@params*/) external onlyOwner {
address auctionAddress = address(
new FjordAuction{ salt: salt }(fjordPoints, auctionToken, biddingTime, totalTokens)
);
// Transfer the auction tokens from the msg.sender to the new auction contract
IERC20(auctionToken).transferFrom(msg.sender, auctionAddress, totalTokens);
emit AuctionCreated(auctionAddress);
}

The worse part is that the factory contract has no specific function implemented that can withdraw out or transfer these auction tokens once they get sent back from auction contracts to it.

That means whenever there are no bids in the auction contract at its end time, the tokens are sent back to the factory where these auction tokens get permanently locked. More the auctions with 0 biddings, more the tokens will get locked in the factory.

Now you might be thinking

  • "well, auction tokens are sent back to factory, they will be utilized while deploying another auction"

The Answer is: No

Because on every auction contract deploy, the auction tokens deposited into auction are taken from msg.sender -> factory_owner not the reserves of the factory contract itself

function createAuction(/*@params*/) external onlyOwner {
...
// Transfer the auction tokens from the msg.sender to the new auction contract
IERC20(auctionToken).transferFrom(msg.sender, auctionAddress, totalTokens);
...
}

POC: https://gist.github.com/burhankhaja/7d307b4ea9087af73585542d96583bb2

Impact

  • All the auction tokens get permanently locked in the factory contract in case when no bids are made and the auction tokens are sent back from auction contract to the owner.

  • Imagine, no bids are made in 10/20 auctions , all the auction tokens sent back from 10 different auctions will get permanently locked in the factory contract and there will be no way to retrieve or transfer these tokens.

Tools Used

Manual Analysis, Foundry

Recommendations

Add additional ownership parameter in the constructor of the auction contract and pass msg.sender as the owner parameter while deploying auction from the factory.

  • FjordAuction.sol

    constructor(
    address _fjordPoints,
    address _auctionToken,
    uint256 _biddingTime,
    uint256 _totalTokens,
    + address _owner
    ) {
    ...
    - owner = msg.sender;
    + owner = _owner;
    ...
    }
  • FjordAuctionFactory.sol

    function createAuction(
    address auctionToken,
    uint256 biddingTime,
    uint256 totalTokens,
    bytes32 salt
    ) external onlyOwner {
    - address auctionAddress = address(
    - new FjordAuction{ salt: salt }(fjordPoints, auctionToken, biddingTime, totalTokens)
    + new FjordAuction{ salt: salt }(fjordPoints, auctionToken, biddingTime, totalTokens, msg.sender)
    - );
    ...
    }

This design ensures that in case of 0 bidding, auction tokens get sent back to the one they were taken from during the deployment of auction contract and hence prevents the permanent loss of the auction tokens.

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.