EIP-7495: SSZ StableContainer

I have extended EIP-7495 with a section describing an additional type safety layer built on top of StableContainer: PR

# Serialization and merkleization format
class Shape(StableContainer[4]):
    side: Optional[uint16]
    color: uint8
    radius: Optional[uint16]

# Valid variants
class Square(Variant[Shape]):
    side: uint16
    color: uint8

class Circle(Variant[Shape]):
    radius: uint16
    color: uint8

class AnyShape(OneOf[Shape]):
    @classmethod
    def select_variant(cls, value: Shape, circle_allowed = True) -> Type[Shape]:
        if value.radius is not None:
            assert circle_allowed
            return Circle
        if value.side is not None:
            return Square
        assert False

In code, could pass around Square / Circle for type-safety. While both of them would serialize / merkleize as Shape. Example usage


Why should we care about stable serialization / merkleization?

  • Someone may create a client today that is solely interested in the color of the shapes. They use a hypothetical API that provides them with just the color + Merkle proof that it is actually the shape’s color.
  • This client should not break, just because a future software upgrade adds rectangles with a width/height instead of side.

In context of Ethereum: A decentralized staking pool should not have to continuously issue software updates just because the location where information about slashing status of a validator and their balance is stored may change between forks. It should be possible to build forward-compatible clients that only require an update if actually used functionality changes. Likewise, a smart contract validating that someone paid their bill using a SSZ transaction / receipt merkle proof shouldn’t have to upgrade their contract just because a future transaction type adds an access list or a priority fee field – both those features are irrelevant for the smart contract’s purpose.