Steep Velvet Guppy
High
Incorrect Initialization will make OnlyOwner
functions inaccessible ,owner will not receive funds meant for him and the contracts will remain in a paused state.
When initializing the OwnableUpgradeable library from openzeppelin, you normally use the __Ownable_init(_owner); , with your owner address, this will successfully set the right address for the contract.
function __Ownable_init(address initialOwner) internal onlyInitializing {
__Ownable_init_unchained(initialOwner);
}
However this does not happen, as the both AuctionsHOuse contracts NounsAuctionHouseV2.sol
and NounsAuctionHouseV3.sol
have the initializer set __Ownable_init();
instead of __Ownable_init(_owner);
NounsAuctionHouseV2.sol
* @notice Initialize the auction house and base contracts,
* populate configuration values, and pause the contract.
* @dev This function can only be called once.
*/
function initialize(
uint192 _reservePrice,
uint56 _timeBuffer,
uint8 _minBidIncrementPercentage
) external initializer {
__Pausable_init();
__ReentrancyGuard_init();
-> __Ownable_init();
_pause();
reservePrice = _reservePrice;
timeBuffer = _timeBuffer;
minBidIncrementPercentage = _minBidIncrementPercentage;
NounsAuctionHouseV3.sol
/**
* @notice Initialize the auction house and base contracts,
* populate configuration values, and pause the contract.
* @dev This function can only be called once.
*/
function initialize(
uint192 _reservePrice,
uint56 _timeBuffer,
uint8 _minBidIncrementPercentage,
uint16 _immediateTreasuryBPs,
uint16 _streamLengthInTicks,
address _streamEscrow
) external initializer {
__Pausable_init();
__ReentrancyGuard_init();
-> __Ownable_init();
_pause();
reservePrice = _reservePrice;
timeBuffer = _timeBuffer;
minBidIncrementPercentage = _minBidIncrementPercentage;
immediateTreasuryBPs = _immediateTreasuryBPs;
streamLengthInTicks = _streamLengthInTicks;
streamEscrow = IStreamEscrow(_streamEscrow);
}
Both contracts also call the pause function in the initializer, which would mean that the paused state of the contract could not be reversed back.
When an aunction gets settled he owner is meant to receive ETH/WETH from _settleAuction
inside NounsAuctionsHouseV2.sol
and ``NounsAuctionHouseV3.sol` which will not send to the owner as the owner is never set!
if (amountToSendTreasury > 0) {
_safeTransferETHWithFallback(owner(), amountToSendTreasury);
}
if (_auction.amount > 0) {
_safeTransferETHWithFallback(owner(), _auction.amount);
}
In both bothNounsAuctionHouseV2.sol
and NounsAuctionHouseV3.sol
the ownable_init()
is missing the owner's address inside the initializer function __ownable_init(owner)
.
If you do not provide the address this will cause the owner never to be set for the OwnableUpgradeable.sol
.
No response
No response
No response
- All the onlyOwner cannot be called by the owner as the owner is never set.
- The contract will remain in a paused state ,as in the initializer
_pause
is called and there is no owner to unpause it. - Owner will never receive the funds meant for the Owner.
No response
// NounsAuctionHouseV2.sol
function initialize(
uint192 _reservePrice,
uint56 _timeBuffer,
uint8 _minBidIncrementPercentage
+ address _owner
) external initializer {
__Pausable_init();
__ReentrancyGuard_init();
- __Ownable_init();
+ __Ownable_init(_owner);
_pause();
reservePrice = _reservePrice;
timeBuffer = _timeBuffer;
minBidIncrementPercentage = _minBidIncrementPercentage;
}
NounsAuctionHouseV3.sol
function initialize(
uint192 _reservePrice,
uint56 _timeBuffer,
uint8 _minBidIncrementPercentage,
uint16 _immediateTreasuryBPs,
uint16 _streamLengthInTicks,
address _streamEscrow
+ address _owner
) external initializer {
__Pausable_init();
__ReentrancyGuard_init();
- __Ownable_init();
+ __Ownable_init(_owner);
_pause();
reservePrice = _reservePrice;
timeBuffer = _timeBuffer;
minBidIncrementPercentage = _minBidIncrementPercentage;
immediateTreasuryBPs = _immediateTreasuryBPs;
streamLengthInTicks = _streamLengthInTicks;
streamEscrow = IStreamEscrow(_streamEscrow);
}