๐Ÿ“‹ Understanding EIP-170 and EIP-173: Contract Size Limits and Ownership Standards

Ifeoluwa SanniIfeoluwa Sanni
10 min read

๐ŸŒŸ Introduction

Ethereum Improvement Proposals (EIPs) are fundamental documents that define standards, protocols, and improvements for the Ethereum ecosystem. This comprehensive article explores two critical EIPs that address different but equally important aspects of smart contract development: EIP-170, which establishes contract code size limits, and EIP-173, which standardizes contract ownership patterns.

๐Ÿ“ EIP-170: Contract Code Size Limit

๐ŸŽฏ Overview

EIP-170 introduces a hard limit on the size of contract code that can be deployed on the Ethereum blockchain. Implemented as part of the Spurious Dragon hard fork, this proposal addresses a subtle but significant scalability concern in the Ethereum Virtual Machine (EVM).

โš™๏ธ Technical Specification

// EIP-170 Implementation Logic
if (block.number >= FORK_BLKNUM) {
    if (contract_creation_returns_data.length > MAX_CODE_SIZE) {
        throw OutOfGasError;
    }
}

Key Parameters:

  • MAX_CODE_SIZE: 24,576 bytes (24KB)

  • Implementation Block: Spurious Dragon hard fork

  • Error Handling: Out of gas error for oversized contracts

๐Ÿšจ The Problem EIP-170 Solves

โšก Quadratic Complexity Vulnerability

Before EIP-170, Ethereum faced a subtle quadratic vulnerability that could become problematic as gas limits increased:

  1. Disk I/O Costs: Reading large contract code from disk requires O(n) operations

  2. VM Preprocessing: Preparing code for execution scales linearly with code size

  3. Merkle Proof Overhead: Larger contracts add O(n) data to block validity proofs

  4. Light Client Concerns: Future light clients would struggle with oversized contract verification

๐Ÿ“Š Visual Representation of the Problem

Contract Size vs. Processing Time

Time โ”‚
     โ”‚     โ•ญโ”€ Quadratic growth potential
     โ”‚    โ•ฑ
     โ”‚   โ•ฑ
     โ”‚  โ•ฑ
     โ”‚ โ•ฑ
     โ”‚โ•ฑ
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Contract Size
     0    12KB   24KB    48KB
           โ”‚      โ”‚       โ”‚
           โ”‚      โ”‚    Blocked by EIP-170
           โ”‚   Limit
        Current practical limit

๐Ÿ› ๏ธ Implementation Details

โช Before EIP-170

// No size restriction - potential for abuse
contract LargeContract {
    // Could theoretically be megabytes of code
    // Limited only by gas costs
}

โฉ After EIP-170

// Size restricted to 24,576 bytes
contract OptimizedContract {
    // Must be carefully designed
    // Libraries and proxy patterns become important
}

โœ… Features and Benefits

1. ๐Ÿ›ก๏ธ Network Stability

  • Prevents potential DoS attacks through oversized contracts

  • Ensures predictable processing times for all nodes

  • Maintains network synchronization efficiency

2. ๐Ÿš€ Future-Proofing

  • Prepares for higher gas limits without introducing vulnerabilities

  • Ensures light client viability as network scales

  • Maintains reasonable storage requirements

3. ๐ŸŽฏ Non-Disruptive Implementation

  • Limit set above practical current usage (most contracts < 24KB)

  • No impact on existing deployed contracts

  • Gradual adoption without breaking changes

โš ๏ธ Cons and Limitations

1. ๐Ÿ”’ Development Constraints

  • Complex Logic Limitation: Large, monolithic contracts must be redesigned

  • Increased Architecture Complexity: Developers must use proxy patterns or libraries

  • Gas Cost Implications: Multiple contract calls may increase transaction costs

2. ๐Ÿ—๏ธ Design Pattern Requirements

// Traditional monolithic approach - potentially too large
contract MonolithicDApp {
    mapping(address => uint) balances;
    mapping(address => bool) authorized;
    // ... hundreds of functions
    // ... complex business logic
    // May exceed 24KB limit
}
// Required modular approach post-EIP-170
contract MainContract {
    address public logicContract;
    address public storageContract;

    function delegate(bytes calldata data) external {
        (bool success,) = logicContract.delegatecall(data);
        require(success);
    }
}

3. ๐Ÿ“ฆ Legacy Migration Challenges

  • Existing large contracts cannot be updated directly

  • Migration requires complete redesign and redeployment

  • Potential user confusion during contract transitions

๐ŸŒ Real-World Impact

๐Ÿ“ˆ Case Studies

1. ๐Ÿ’ฐ Compound Protocol

  • Pre-EIP-170: Single large contract architecture

  • Post-EIP-170: Modular design with separate interest rate models

  • Result: Improved upgradeability and gas efficiency

2. ๐Ÿ”„ Uniswap Evolution

  • V1: Simple, compact design (well under limit)

  • V2: Expanded features still within limits

  • V3: Complex features requiring careful optimization

๐Ÿ‘‘ EIP-173: Contract Ownership Standard (ERC-173)

๐ŸŽฏ Overview

EIP-173 establishes a standardized interface for contract ownership, providing a consistent way to manage administrative control over smart contracts. This standard has become fundamental to modern DeFi and dApp development.

โš™๏ธ Technical Specification

/// @title ERC-173 Contract Ownership Standard
interface ERC173 {
    /// @dev Emitted when ownership changes
    event OwnershipTransferred(
        address indexed previousOwner, 
        address indexed newOwner
    );

    /// @notice Get current owner address
    function owner() view external returns (address);

    /// @notice Transfer ownership to new address
    /// @param _newOwner Address of new owner (use address(0) to renounce)
    function transferOwnership(address _newOwner) external;
}

๐Ÿ”ง Core Components

1. ๐Ÿ” Owner Query Function

function owner() view external returns (address) {
    return _owner;
}

2. ๐Ÿ”„ Ownership Transfer

function transferOwnership(address _newOwner) external {
    require(msg.sender == _owner, "Not authorized");
    address previousOwner = _owner;
    _owner = _newOwner;
    emit OwnershipTransferred(previousOwner, _newOwner);
}

3. ๐Ÿ“ Event Logging

event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
);

๐Ÿ› ๏ธ Implementation Patterns

๐Ÿ—๏ธ Basic Implementation

contract BasicOwnable is ERC173 {
    address private _owner;

    constructor() {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    modifier onlyOwner() {
        require(owner() == msg.sender, "Ownable: caller is not the owner");
        _;
    }

    function owner() public view override returns (address) {
        return _owner;
    }

    function transferOwnership(address newOwner) public override onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }

    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }
}

๐Ÿ” Advanced Multi-Signature Implementation

contract MultiSigOwnable is ERC173 {
    address[] public owners;
    mapping(address => bool) public isOwner;
    uint public threshold;

    struct Transaction {
        address to;
        bytes data;
        bool executed;
        uint confirmations;
    }

    mapping(uint => Transaction) public transactions;
    mapping(uint => mapping(address => bool)) public confirmations;

    function transferOwnership(address _newOwner) external override {
        // Requires multi-signature approval
        require(isConfirmed(getCurrentTransactionId()), "Not confirmed");
        // Implementation logic
    }
}

โœ… Features and Benefits

1. ๐ŸŽฏ Standardization

  • Universal Interface: Consistent ownership management across all contracts

  • Tooling Compatibility: Wallets, explorers, and dApps can recognize ownership

  • Integration Simplicity: Easy integration with existing infrastructure

2. โš™๏ธ Administrative Control

contract ManagedToken is ERC173, ERC20 {
    function mint(address to, uint256 amount) external onlyOwner {
        _mint(to, amount);
    }

    function pause() external onlyOwner {
        _pause();
    }

    function setFees(uint256 _fee) external onlyOwner {
        fee = _fee;
    }
}

3. ๐Ÿ”„ Ownership Transfer Scenarios

  • Individual to Individual: Simple ownership transfer

  • Individual to Multisig: Enhanced security

  • Temporary Delegation: Time-limited administrative control

  • Ownership Renunciation: Permanent decentralization

๐Ÿ“Š Visual Representation of Ownership Patterns

ERC-173 Ownership Patterns
1. Single Owner Pattern
   [Owner] โ”€โ”€โ”€โ”€ownsโ”€โ”€โ”€โ–บ [Contract]
      โ”‚
      โ””โ”€can transferโ”€โ–บ [New Owner]2. Multi-Signature Pattern
   [Owner 1] โ”
   [Owner 2] โ”œโ”€jointly ownโ”€โ–บ [Contract]
   [Owner 3] โ”˜3. DAO Governance Pattern
   [Token Holders] โ”€โ”€voteโ”€โ”€โ–บ [Governance Contract] โ”€โ”€controlsโ”€โ”€โ–บ [Target Contract]4. Proxy Pattern
   [Owner] โ”€โ”€ownsโ”€โ”€โ–บ [Proxy Contract] โ”€โ”€delegatesโ”€โ”€โ–บ [Implementation Contract]

๐Ÿ’ผ Use Cases and Applications

1. ๐Ÿ’ฐ DeFi Protocols

contract DEXRouter is ERC173 {
    mapping(address => bool) public authorizedPairs;

    function addPair(address pair) external onlyOwner {
        authorizedPairs[pair] = true;
    }

    function updateFeeRecipient(address newRecipient) external onlyOwner {
        feeRecipient = newRecipient;
    }
}

2. ๐Ÿ–ผ๏ธ NFT Collections

contract NFTCollection is ERC173, ERC721 {
    string public baseURI;
    uint256 public maxSupply;

    function setBaseURI(string memory _baseURI) external onlyOwner {
        baseURI = _baseURI;
    }

    function mint(address to, uint256 tokenId) external onlyOwner {
        _mint(to, tokenId);
    }
}

3. ๐Ÿ“‹ Contract Registries

contract ContractRegistry is ERC173 {
    mapping(bytes32 => address) public contracts;

    function registerContract(bytes32 name, address addr) external {
        // Only contract owners can register their contracts
        require(ERC173(addr).owner() == msg.sender, "Not contract owner");
        contracts[name] = addr;
    }
}

โš ๏ธ Cons and Limitations

1. ๐ŸŽฏ Centralization Risks

  • Single Point of Failure: Owner key compromise affects entire contract

  • Censorship Potential: Owner can restrict user access or functionality

  • Trust Requirements: Users must trust the ownerโ€™s intentions

2. ๐Ÿ”‘ Key Management Challenges

// Problematic: No access recovery mechanism
contract RiskyOwnable is ERC173 {
    address private _owner;

    // If owner loses private key, contract becomes unmaintainable
    function criticalUpdate() external onlyOwner {
        // Cannot be called if key is lost
    }
}

3. ๐Ÿ›๏ธ Governance Limitations

  • Binary Control: Owner has full control or no control

  • No Gradual Transition: Difficult to implement progressive decentralization

  • Community Input: No built-in mechanism for community governance

4. ๐Ÿ›ก๏ธ Security Vulnerabilities

// Common vulnerability: Front-running attacks
contract VulnerableOwnable is ERC173 {
    function transferOwnership(address newOwner) external override onlyOwner {
        // Immediate transfer allows front-running
        _owner = newOwner;
        emit OwnershipTransferred(msg.sender, newOwner);
    }
}
// Safer implementation with time delays
contract SaferOwnable is ERC173 {
    address public pendingOwner;
    uint256 public transferInitiatedAt;
    uint256 public constant DELAY = 2 days;

    function transferOwnership(address newOwner) external override onlyOwner {
        pendingOwner = newOwner;
        transferInitiatedAt = block.timestamp;
    }

    function claimOwnership() external {
        require(msg.sender == pendingOwner, "Not pending owner");
        require(block.timestamp >= transferInitiatedAt + DELAY, "Delay not passed");
        emit OwnershipTransferred(_owner, pendingOwner);
        _owner = pendingOwner;
        pendingOwner = address(0);
    }
}

๐Ÿ”— Integration and Best Practices

๐Ÿ”„ Combining EIP-170 and EIP-173

// Example: Modular owned contract design
contract MainContract is ERC173 {
    address public logicModule;
    address public storageModule;

    function upgradeLogic(address newLogic) external onlyOwner {
        // Ensure new logic contract is within size limits
        require(getCodeSize(newLogic) <= 24576, "Logic too large");
        logicModule = newLogic;
    }

    function getCodeSize(address addr) internal view returns (uint256 size) {
        assembly { size := extcodesize(addr) }
    }
}
// Separate logic contract (must be < 24KB)
contract LogicModule {
    function complexCalculation() external pure returns (uint256) {
        // Implementation within size limits
    }
}

๐Ÿ“‹ Development Workflow

EIP-170 + EIP-173 Development Process
1. Design Phase
   โ”œโ”€ Plan modular architecture (EIP-170 compliance)
   โ”œโ”€ Define ownership requirements (EIP-173 implementation)
   โ””โ”€ Consider upgrade patterns2. Implementation Phase
   โ”œโ”€ Develop within 24KB constraints
   โ”œโ”€ Implement standard ownership interface
   โ””โ”€ Add size monitoring tools3. Testing Phase
   โ”œโ”€ Verify contract sizes
   โ”œโ”€ Test ownership transfers
   โ””โ”€ Validate upgrade mechanisms4. Deployment Phase
   โ”œโ”€ Deploy modules separately
   โ”œโ”€ Set initial ownership
   โ””โ”€ Document ownership procedures

๐ŸŒ Industry Impact and Adoption

๐Ÿ“Š Statistics and Adoption

EIP-170 Adoption:

  • Implementation Date: November 2016 (Spurious Dragon)

  • Affected Contracts: <0.1% of existing contracts exceeded limit

  • Current Compliance: 99.9% of new contracts comply naturally

  • Tool Integration: All major development frameworks include size checking

EIP-173 Adoption:

  • Standard Recognition: Widely adopted across DeFi protocols

  • Implementation Rate: >80% of administrative contracts use ERC-173

  • Ecosystem Support: Integrated into OpenZeppelin, Hardhat, and other tools

๐Ÿข Major Projects Using These Standards

๐Ÿ’ฐ DeFi Protocols

  1. Compound: Modular design respecting EIP-170, ERC-173 governance

  2. Aave: Proxy patterns with standard ownership

  3. Uniswap: Optimized contracts with owner-controlled parameters

๐Ÿ–ผ๏ธ NFT Platforms

  1. OpenSea: ERC-173 integration for collection management

  2. CryptoPunks: Early adopter of ownership patterns

  3. Art Blocks: Complex ownership hierarchies using ERC-173

๐Ÿš€ Future Developments and Considerations

๐Ÿ”ฎ Evolution and Extensions

๐Ÿ‘‘ Enhanced Ownership Standards

// Proposed extensions to ERC-173
interface ERC173Extended is ERC173 {
    function pendingOwner() external view returns (address);
    function transferOwnershipWithDelay(address newOwner, uint256 delay) external;
    function multiSigTransfer(address newOwner, bytes[] signatures) external;
}

๐Ÿ“ Dynamic Size Management

// Future considerations for dynamic size limits
contract AdaptiveContract {
    uint256 public maxSize;

    function adjustSizeLimit(uint256 newLimit) external onlyOwner {
        require(newLimit >= MIN_SIZE && newLimit <= MAX_SIZE, "Invalid limit");
        maxSize = newLimit;
    }
}

๐Ÿ› ๏ธ Challenges and Solutions

1. ๐Ÿ—œ๏ธ Contract Size Optimization Techniques

  • Library Usage: External libraries reduce deployment size

  • Proxy Patterns: Delegate calls to separate implementations

  • Code Compression: Optimize Solidity for smaller bytecode

  • Factory Patterns: Deploy minimal proxies for similar contracts

2. ๐Ÿ—๏ธ Advanced Ownership Patterns

  • Role-Based Access: Multiple permission levels

  • Time-Locked Operations: Delayed execution for security

  • Multi-Party Governance: Shared ownership with voting mechanisms

  • Upgradeable Ownership: Evolving permission structures

๐ŸŽฏ Conclusion

EIP-170 and EIP-173 represent fundamental building blocks in the Ethereum ecosystem, addressing critical aspects of smart contract development: size constraints and ownership management. While EIP-170 ensures network stability and scalability by preventing oversized contracts, EIP-173 provides a standardized approach to contract administration and governance.

๐Ÿ“š Key Takeaways

  1. EIP-170 forces developers to write modular, efficient code while protecting the network from potential vulnerabilities

  2. EIP-173 standardizes ownership patterns, enabling consistent tooling and user experiences across the ecosystem

  3. Both standards require careful consideration during development but provide significant long-term benefits

  4. Modern smart contract development must account for both size limitations and ownership requirements from the design phase

๐Ÿ’ก Recommendations for Developers

  • Plan for modularity early in the development process to avoid EIP-170 size constraints

  • Implement ERC-173 for any contract requiring administrative functions

  • Consider governance implications when designing ownership structures

  • Use established patterns like OpenZeppelinโ€™s implementations for security and compatibility

  • Monitor contract sizes during development with automated tools

  • Document ownership procedures clearly for users and future maintainers

The combination of these standards has shaped modern Ethereum development practices, encouraging better architecture, standardized interfaces, and more secure administrative patterns. As the ecosystem continues to evolve, these foundational standards will remain critical to building robust, interoperable smart contracts.

0
Subscribe to my newsletter

Read articles from Ifeoluwa Sanni directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ifeoluwa Sanni
Ifeoluwa Sanni

I am a Web3 Software developer