ResolvedDelegateProxy
Table of Contents
Overview
The ResolvedDelegateProxy is a legacy proxy contract that dynamically resolves its implementation address through the AddressManager contract. It maintains backwards compatibility with pre-Bedrock versions of the Optimism system where proxy implementations were managed through a centralized name registry rather than standard proxy patterns.
Definitions
AddressManager
A legacy contract that maintains an Address Registry mapping string names to addresses. The ResolvedDelegateProxy queries the AddressManager to dynamically resolve its implementation address using a configured implementation name. See the AddressManager specification for details.
Assumptions
a01-001: AddressManager provides valid implementation addresses
The AddressManager contract returns valid, non-zero implementation addresses when queried with the configured implementation name. If the AddressManager returns the zero address or an invalid address, the proxy will fail to function.
Mitigations
- The fallback function explicitly checks for zero address and reverts with a clear error message
- AddressManager is controlled by governance with established processes for address updates
- Legacy contracts using this proxy pattern are being phased out in favor of standard proxy patterns
a01-002: Implementation storage layout compatibility
The implementation contract does not use mappings in storage slots 0 or 1, which would conflict with the proxy's
implementationName and addressManager mappings.
Mitigations
- This storage pattern was a known design constraint in the legacy system
- Implementation contracts were designed with awareness of these reserved slots
- Modern proxy patterns (used in current OP Stack) avoid this issue entirely
Invariants
i01-001: Transparent proxy behavior
The proxy MUST preserve the execution context for all calls, ensuring that msg.sender and msg.value remain unchanged
when execution is delegated to the implementation contract. From the end-user's perspective, interactions with the proxy
MUST be indistinguishable from direct interactions with the implementation contract.
Impact
Severity: Critical
If this invariant is violated, the proxy would break the fundamental contract of transparent proxies. Users would lose their identity in delegated calls, breaking authentication and authorization mechanisms in the implementation contract. ETH transfers would fail or be misdirected, potentially leading to fund loss.
i01-002: Implementation address resolution requirement
All calls to the proxy MUST resolve to a non-zero implementation address before delegatecall execution. The proxy MUST revert if the AddressManager returns the zero address for the configured implementation name.
Impact
Severity: Critical
If this invariant is violated and delegatecall proceeds to the zero address, the call would fail unpredictably. The explicit revert ensures clear failure semantics and prevents undefined behavior.
i01-003: Immutable configuration after deployment
The implementationName and addressManager configuration stored in the proxy MUST NOT change after deployment. These
values are set once in the constructor and have no update mechanism.
Impact
Severity: High
If this invariant were violated, the proxy could resolve to unintended implementations or query the wrong AddressManager, breaking the contract's intended behavior. However, the contract has no functions to modify these values, making violation impossible without storage manipulation.
Function Specification
constructor
Initializes the proxy with the AddressManager reference and implementation name.
Parameters:
_addressManager: Address of the AddressManager contract that will resolve implementation addresses_implementationName: String name used to query the implementation address from the AddressManager
Behavior:
- MUST store
_addressManagerinaddressManager[address(this)] - MUST store
_implementationNameinimplementationName[address(this)] - MUST use
address(this)as the mapping key to avoid storage slot conflicts with implementation contracts
fallback
Resolves the implementation address and delegates all calls to it.
Parameters:
- Accepts arbitrary calldata via
msg.data - Accepts ETH via
payablemodifier
Behavior:
- MUST query
addressManager[address(this)].getAddress(implementationName[address(this)])to resolve the implementation address - MUST revert if the resolved implementation address is the zero address
- MUST perform delegatecall to the resolved implementation address with
msg.data - MUST preserve
msg.senderandmsg.valuethrough the delegatecall - MUST return the full returndata from the delegatecall if the call succeeds
- MUST revert with the full returndata from the delegatecall if the call fails
- MUST handle returndata using inline assembly to properly forward dynamic-length data