1.4. UUPS Proxy Pattern (EIP-1967)
The Fhenix-FairMarket protocol implements the Universal Upgradeable Proxy Standard (UUPS) compliant with EIP-1967 to decouple persistent user funds and state variables from the executable business logic. This architectural pattern enables seamless protocol iterations, safe adaptation to CoFHE SDK updates, and strict, time-delayed governance over contract modifications without risking fund migration or storage corruption.
By storing all auction state, escrow balances, and bidder mappings in a dedicated proxy contract while delegating execution to an upgradable logic implementation, the protocol guarantees continuity, auditability, and mathematical integrity across its lifecycle.
Core Design Principles
| Principle | Technical Implementation |
|---|---|
| Logic/Storage Separation | FhenixFairMarketProxy.sol (EIP-1967) holds all storage variables. FhenixFairMarket.sol contains only executable bytecode, accessed via delegatecall. |
| Zero Fund Migration | Storage layout remains immutable during upgrades. User balances, bid histories, and NFT locks persist atomically without manual state migration scripts. |
| SDK Isolation via Adapter | All @cofhe/sdk and FHE library calls are routed through CofheAdapter.sol. Upgrading the adapter does not require touching the core auction logic. |
| Timelocked Governance | A mandatory 48-hour Timelock enforces a review window between upgrade proposal and execution, allowing community scrutiny and emergency intervention. |
| Multisig Authorization | _authorizeUpgrade() is restricted to a 5-of-9 multisig council (devs, auditor, AVS operator, community rep, legal/compliance). |
️ Technical Implementation
1. Proxy & Logic Contract Architecture
The protocol follows OpenZeppelin’s UUPSUpgradeable standard with strict initialization guards.
// FhenixFairMarket.sol (Logic Implementation)
contract FhenixFairMarket is
UUPSUpgradeable,
OwnableUpgradeable,
ReentrancyGuardUpgradeable
{
// Storage variables are inherited via proxy layout
mapping(address => uint256) public escrowBalances;
mapping(uint256 => Auction) public auctions;
/**
* @notice Secure initialization function (called exactly once)
*/
function initialize(
address initialOwner,
address cofheAdapter,
address slashingPot
) external initializer {
__Ownable_init(initialOwner);
__ReentrancyGuard_init();
__UUPSUpgradeable_init();
// Register core dependencies
}
/**
* @notice Restricts upgrade capability to authorized governance
*/
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {
// Enforced via Multisig + 48h Timelock at governance layer
// Unauthorized calls revert immediately
}
}2. Deployment & Initialization Sequence
Upgrades are executed atomically using upgradeToAndCall(), ensuring state transitions and dependency updates occur in a single transaction.
// Deployment Script: 01_deploy_core_proxy.ts
const Logic = await ethers.getContractFactory("FhenixFairMarket");
const Proxy = await ethers.getContractFactory("ERC1967Proxy");
// 1. Deploy Logic Implementation (no init called yet)
const logicImpl = await Logic.deploy();
await logicImpl.deployed();
// 2. Deploy Proxy, pointing to Logic + calling initialize() in constructor
const proxy = await Proxy.deploy(
logicImpl.address,
Logic.interface.encodeFunctionData("initialize", [
multisigAddress,
cofheAdapter.address,
slashedPot.address
])
);
await proxy.deployed();3. Safe Upgrade Execution
All upgrades pass through the governance timelock contract, which validates the payload and enforces the delay window.
// Timelock Controller (Governance Layer)
function executeUpgrade(
address proxy,
address newLogic,
bytes calldata initData
) external onlyTimelock {
// 1. Verify newLogic passes static analysis (Slither/Mythril)
// 2. Verify no storage layout collisions
// 3. Execute atomic swap
(bool success, ) = proxy.call(
abi.encodeWithSignature("upgradeToAndCall(address,bytes)", newLogic, initData)
);
require(success, "Upgrade failed");
}Architectural Impact & Gas Comparison
| Metric | Traditional Non-Upgradeable | Fhenix-FairMarket UUPS v2.0 |
|---|---|---|
| Upgrade Cost | Full redeployment + manual state migration scripts (~500k–2M gas) | Single proxy.upgradeTo() transaction (~40k gas) |
| Downtime | Hours/days for fund migration, verification, and user re-approval | Near-zero (atomic bytecode swap, state preserved) |
| State Integrity | High risk of data loss or layout collision during migration | Guaranteed (EIP-1967 standardizes storage slots) |
| SDK Dependency | Hardcoded FHE imports break core logic on @cofhe/sdk version bumps | Decoupled via CofheAdapter; core contract remains stable |
️ Security & Governance Guarantees
- Storage Collision Protection: EIP-1967 reserves specific storage slots for proxy administrative variables (
_owner,_implementation), preventing overlap with business logic variables. Layout changes require explicit audit review. - Unauthorized Upgrade Prevention: The
_authorizeUpgrademodifier strictly validates caller identity. Even if the proxy admin key is compromised, the 48-hour timelock and multisig requirement prevent immediate malicious execution. - Emergency Halt Compatibility: If a critical vulnerability is detected during the timelock window, the governance council can trigger
EmergencyHaltbefore the upgrade executes, prioritizing capital recovery over logic deployment. - Audit Gate Compliance (P0):
UUPS Proxyisolation — no logic in storage contractinitialize()callable only once_authorizeUpgraderestricted to multisig- Zero
selfdestructor uncontrolleddelegatecallin logic
Upgrade Lifecycle Workflow
Pre-Upgrade Verification Checklist
Before any upgradeToAndCall execution, the following must pass:
- [] Storage layout comparison shows zero collisions (
@openzeppelin/upgrades-core) - []
Slither&Mythrilscans return zeroHigh/Criticalfindings - [] Test coverage ≥90% for new logic + regression tests pass 100%
- []
CofheAdapterinterface compatibility verified - [] Governance multisig approves payload + 48h timelock initiated
- [] Post-upgrade monitoring KPIs configured in Tenderly/Defender
Next Steps
- Proceed to 1.5. ERC-4337 Account Abstraction to understand user-facing signature abstraction and XSS mitigation.
- Review Governance & Timelock Configuration for multisig setup, voting thresholds, and emergency halt procedures.
- See Security Model → Audit Readiness Matrix for P0 proxy isolation verification steps.