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

Predictable Auction Address in `createAuction` Function

Summary

See Bellow

Vulnerability Details

The createAuction function in the AuctionFactory contract deploys new FjordAuction contracts using the create2 opcode, which allows for the deterministic generation of contract addresses. The address generated by create2 is derived from the deployer’s address, a user-provided salt, and the bytecode of the contract being deployed. The function implementation is as follows:

function createAuction(
address auctionToken,
uint256 biddingTime,
uint256 totalTokens,
bytes32 salt
) 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 predictability arises because the salt provided by the caller, combined with other known factors (like the bytecode and the address of the AuctionFactory), allows anyone to calculate the address of the auction contract before it is deployed. If the salt used is predictable, such as a simple sequential number or timestamp, an attacker could preemptively determine the address where the auction contract will be deployed.

Impact

An attacker could exploit the predictable nature of the auction contract address to perform actions such as pre-funding the address or deploying another contract at the address before the intended auction contract is deployed. This could lead to disruptions in the auction process or manipulation of the auction outcomes.

Tools Used

Manual

Recommendations

The salt used in the createAuction function should be derived from unpredictable sources. One approach is to generate the salt using a combination of random values and hashes of current blockchain state variables, such as block timestamps and numbers, ensuring that it is unique and difficult to predict.

Example implementation:

function createAuction(
address auctionToken,
uint256 biddingTime,
uint256 totalTokens,
bytes32 salt
) external onlyOwner {
// Predict the auction address
bytes32 bytecodeHash = keccak256(
abi.encodePacked(
type(FjordAuction).creationCode,
abi.encode(fjordPoints, auctionToken, biddingTime, totalTokens)
)
);
address predictedAddress = address(
uint160(uint256(keccak256(
abi.encodePacked(bytes1(0xff), address(this), salt, bytecodeHash)
)))
);
// Check if the address already has a contract deployed
require(predictedAddress.code.length == 0, "Address already in use");
// Deploy the auction
address auctionAddress = address(
new FjordAuction{ salt: salt }(fjordPoints, auctionToken, biddingTime, totalTokens)
);
// Transfer tokens
IERC20(auctionToken).transferFrom(msg.sender, auctionAddress, totalTokens);
emit AuctionCreated(auctionAddress);
}

This approach adds a check to ensure that the predicted address does not already have a contract deployed at it, preventing address collisions and mitigating the risk of exploitation due to predictable contract addresses.

Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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