ERC-1967: Standard Proxy Storage Slots
Ethereum bytecode is immutable: once deployed, you cannot change the runtime code. Upgradeable contracts work around this with a proxy pattern: a small, intentionally-stable proxy contract delegatecalls into a separate "implementation" contract whose address it stores. ERC-1967 standardises where the proxy stores the implementation address so explorers can find it.
Costs of the Proxy Pattern
- Per-call overhead: every external call routes through
delegatecall. - Storage layout fragility: implementation upgrades must preserve storage layout exactly.
selfdestructtraps: implementation callingselfdestructdestroys the proxy.- Initializer races: first call must initialize before adversary does.
- Audit complexity: two contracts to audit; storage-collision audits required.
Neo Equivalent: NEP-22 Native Update (No Proxy)
Neo contracts upgrade in place via ContractManagement.Update(nef, manifest, data). Replaces bytecode and manifest atomically, preserves all storage, runs _deploy(data, update: true) for migrations, requires owner witness. The contract hash never changes — every reference, every NEP-17 holder, every NFT, every approval continues to work.
Live on Neo TestNet
Both implementations deployed on Neo N3 TestNet.
| Implementation | TestNet Address | Contract Hash |
|---|---|---|
Solidity (neo-solc) | NRiL2gKGW5L8YgRcudr8mFNjrDUkkWZHR3 | 0x48f6d58a…bfdbd245 |
Neo C# (nccs) | NTgmiKbdcnknygAtt2ssWEjfPsJUM9hWGV | 0x096f01e4…481be976 |
Verified: initial version is 1, owner is the deployer. The Neo C# contract uses NEP-22's Update method for in-place upgrades — calling it bumps the version counter via _deploy(data, update: true), the standard Neo lifecycle hook. docs/standards-mirror/deployments/erc-1967/.
