You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Improper Implementation of Upgradable Contract Design in AuctionHouse Contract
SUMMARY
The contract appears to be designed as an upgradable contract as it uses openZepplin upgradeable pattern but lacks critical implementation details, raising questions about its compliance with best practices for upgradable proxy patterns. Specifically, issues related to the initializer modifier, unprotected initialization logic, and improper deactivation of the initializer post-deployment are highlighted.
The constructor is marked with the initializer modifier, but there is no mechanism to prevent reinitialization after deployment, leading to potential state corruption.
No initializing state check is implemented post-deployment to ensure immutability of the initialization process.
Lack of Proxy-Compatible Storage Layout Management:
The initialize function does not explicitly indicate compatibility with a proxy-based storage layout (e.g., storage gaps are missing).
Misalignment of Upgradable Contract Practices:
Key contract-level initializations (e.g., __Pausable_init(), __Ownable_init()) are correctly called but lack defensive programming to ensure proper initialization occurs only once. example if it decides to follow the UUPS patern the constructor should be called _disableInitializers() function in it's contrctor logic.
INTERNAL PRECONDITION
The constructor and initialize function can both be invoked during deployment due to improper safeguards, allowing for potential overwriting of critical state variables.
EXTERNAL PRECONDITION
An attacker or malicious actor with external access to the initialize function after deployment could:
Reset state variables.
Alter auction parameters such as reservePrice, timeBuffer, and minBidIncrementPercentage.
ATTACK PATH
Deploy the contract, calling the constructor.
Exploit the unprotected initialize function to overwrite sensitive data or initialize the contract multiple times.
IMPACT
High: Contract functionality and state integrity are compromised. Initialization logic is a critical security concern, especially in upgradable contracts, as it determines the integrity of deployed contracts.
Potential Exploits: Attackers could reset critical configurations, bypass access control mechanisms, or disrupt auction logic.
PROOF OF CONCEPT (PoC)
Deploy the contract using the provided constructor:
Invoke the initialize function post-deployment with attacker-controlled parameters:
initialize(1 ether, 120, 5);
Observe overwritten auction parameters:
reservePrice = 1 ether
timeBuffer = 120
minBidIncrementPercentage = 5
MITIGATION
Use the Correct Constructor-Initializer Approach for Upgradable Contracts:
Remove the initializer modifier from the constructor. Constructors should be empty in upgradable contracts.
Restrict Initialization Logic:
Ensure initialize is callable only once by the proxy. Use OpenZeppelin's Initializable library correctly, which includes _initialized and _initializing safeguards.
Deactivate Initializer Post-Deployment:
Include explicit checks and a mechanism to mark the initialization as complete:
Conduct a thorough review to ensure the contract adheres to the proxy storage and initialization rules.
OR
strictly follow the UUPS INITIALIZATION PROXY PATTERN AND ensure that the _disableInitializers() is added to the constructor.
The text was updated successfully, but these errors were encountered:
sherlock-admin4
changed the title
Generous Peanut Platypus - **Improper Implementation of Upgradable Contract Design in AuctionHouse Contract**
OlaHamid - **Improper Implementation of Upgradable Contract Design in AuctionHouse Contract**
Dec 4, 2024
OlaHamid
Medium
Improper Implementation of Upgradable Contract Design in AuctionHouse Contract
SUMMARY
The contract appears to be designed as an upgradable contract as it uses openZepplin upgradeable pattern but lacks critical implementation details, raising questions about its compliance with best practices for upgradable proxy patterns. Specifically, issues related to the
initializer
modifier, unprotected initialization logic, and improper deactivation of the initializer post-deployment are highlighted.https://github.com/sherlock-audit/2024-11-nounsdao/blob/8b6fb94f103134e751cf016e5c3f4185be89bb49/nouns-monorepo/packages/nouns-contracts/contracts/NounsAuctionHouseV2.sol#L83
ROOT CAUSE
Incorrect Use of
initializer
:initializer
modifier, but there is no mechanism to prevent reinitialization after deployment, leading to potential state corruption.initializing
state check is implemented post-deployment to ensure immutability of the initialization process.Lack of Proxy-Compatible Storage Layout Management:
initialize
function does not explicitly indicate compatibility with a proxy-based storage layout (e.g., storage gaps are missing).Misalignment of Upgradable Contract Practices:
__Pausable_init()
,__Ownable_init()
) are correctly called but lack defensive programming to ensure proper initialization occurs only once. example if it decides to follow the UUPS patern the constructor should be called_disableInitializers()
function in it's contrctor logic.INTERNAL PRECONDITION
The constructor and
initialize
function can both be invoked during deployment due to improper safeguards, allowing for potential overwriting of critical state variables.EXTERNAL PRECONDITION
An attacker or malicious actor with external access to the
initialize
function after deployment could:reservePrice
,timeBuffer
, andminBidIncrementPercentage
.ATTACK PATH
constructor
.initialize
function to overwrite sensitive data or initialize the contract multiple times.IMPACT
PROOF OF CONCEPT (PoC)
Deploy the contract using the provided constructor:
Invoke the
initialize
function post-deployment with attacker-controlled parameters:Observe overwritten auction parameters:
reservePrice = 1 ether
timeBuffer = 120
minBidIncrementPercentage = 5
MITIGATION
Use the Correct Constructor-Initializer Approach for Upgradable Contracts:
initializer
modifier from the constructor. Constructors should be empty in upgradable contracts.Restrict Initialization Logic:
initialize
is callable only once by the proxy. Use OpenZeppelin'sInitializable
library correctly, which includes_initialized
and_initializing
safeguards.Deactivate Initializer Post-Deployment:
Audit Storage and Initialization Patterns:
OR
_disableInitializers()
is added to the constructor.The text was updated successfully, but these errors were encountered: