Introducing Stack Mainnet: An L3 OP-Stack Points Chain on Base

Stack introduces an ultra low-cost Ethereum L3 points chain, using the OP Stack and settling on Base for security. This allows us to bring loyalty points onchain sustainably and securely.

Today, we’re excited to announce Stack’s mainnet launch. Our L3 chain allows us to balance being a low-cost solution for loyalty management with the security of a verifiable blockchain, operating according to Ethereum community standards.

The chain runs a core points protocol that integrates with our points management UI and SDKs. The points protocol will lower costs, reduce platform risk, and increase reliability and security for loyalty management. Developers can learn more about integrating and extending the points protocol from our chain docs.

We are excited to bring loyalty points onchain in a sustainable way, showcasing points as a use case for blockchains that proudly sits alongside stablecoins, NFTs, and other tokens.

Why OP Stack on Base?

Stack first pitched the case for onchain point systems using L3s in October 2023 at the Coinbase Ventures Summit in Malibu. At the time, the only L3 solution was Arbitrum Orbit. Following the presentation we dove into whether L3s would be feasible on Base. While we prototyped our protocol using Orbit, the Base team executed on supporting L3s and Conduit stood out as a reliable service provider.

We are convinced that using a common standard like OP Stack with more developer tooling will reduce risks and that rolling up to Base aligns us with consumer apps who know and trust the Base chain.

Why an L3?

Following Ethereum’s rollup-centric roadmap in October 2020, the Ethereum ecosystem has seen a proliferation of new blockchains that provide a variety of security and performance tradeoffs. For example, Zora launched a chain for creative artists, while Base targets consumer crypto apps.

The latest development in blockchain infrastructure is known as a "layer 3 blockchain" or "L3" because it rolls up to a "layer 2" (L2) that, in turn, rolls up to the main Ethereum chain. It is prudent to use these layer classifications for their most suitable applications. While L3s are fully verifiable blockchains, they may not necessarily provide a secure solution for financial applications (also known as DeFi).

We believe that L3s are well-suited for attestations, particularly quantitative attestations in the form of point systems for loyalty programs. Bringing loyalty programs onchain is only possible with scalable, cheap blockchains.

Network Information

  • Network Name: Stack

  • Description: The public mainnet for Stack.

  • Chain ID: 78225

  • Currency Symbol: ETH

  • RPC Endpoint: https://rpc.stack.so

  • Bridge: https://bridge.stack.so

  • Block Explorer: https://explorer.stack.so

  • Points Protocol: 0x000000000c2B4A5816cbb76e9bb3f70D175940A3

  • Points Interface: IPoints.sol

  • Observer Interface: IPointsObserver.sol

The Points Protocol

The Points Protocol is a Solidity smart contract that enables the creation and management of point systems. It provides a flexible and modular approach to implementing point-based systems.

Features

  • Create multiple point systems, each with its own unique ID

  • Add and subtract points from user balances within a point system

  • Retrieve point balances and total points within a point system

  • Perform batch operations to add or subtract points for multiple users simultaneously

  • Manage administrators and external contracts (issuers)

  • Set and retrieve metadata (URI) for each point system

  • Observe point balance changes through onchain hooks

Usage

To interact with the Points Protocol, you can use the [IPoints interface](https://github.com/stack-so/protocol-interfaces). The contract is deployed at the address 0x000000000c2B4A5816cbb76e9bb3f70D175940A3.

Creating a Point System

To create a new point system, call the createPointSystem() function. It will return the ID of the newly created point system.

Managing Points

  • addPoints(uint256 systemId, address user, uint256 points): Add points to a user’s balance within a specific point system.

  • subtractPoints(uint256 systemId, address user, uint256 points): Subtract points from a user’s balance within a specific point system.

  • getPoints(uint256 systemId, address user): Retrieve the point balance of a user within a specific point system.

  • getTotalPoints(uint256 systemId): Retrieve the total points within a specific point system.

Batch Operations

  • addPointsBatch(uint256 systemId, address[] calldata users, uint256[] calldata points): Add points to multiple users’ balances within a specific point system in a single transaction.

  • subtractPointsBatch(uint256 systemId, address[] calldata users, uint256[] calldata points): Subtract points from multiple users’ balances within a specific point system in a single transaction.

  • addPointsBatchMultipleSystems(uint256[] calldata systemIds, address[] calldata users, uint256[] calldata points): Add points to multiple users’ balances across different point systems in a single transaction.

  • subtractPointsBatchMultipleSystems(uint256[] calldata systemIds, address[] calldata users, uint256[] calldata points): Subtract points from multiple users’ balances across different point systems in a single transaction.

Managing Administrators and Issuers

  • addAdmin(uint256 systemId, address admin): Add an administrator to a specific point system.

  • removeAdmin(uint256 systemId, address admin): Remove an administrator from a specific point system.

  • addIssuer(uint256 systemId, address contractAddress): Add an external contract (issuer) to a specific point system.

  • removeIssuer(uint256 systemId, address contractAddress): Remove an external contract (issuer) from a specific point system.

Observer Pattern

  • setObserver(uint256 systemId, address observer): Set an observer contract for a specific point system. The observer will be notified when points are added or subtracted from a user’s balance.

  • getObserver(uint256 systemId): Retrieve the observer contract for a specific point system.

Managing Metadata

  • setURI(uint256 systemId, string calldata uri): Set the URI (metadata) for a specific point system.

  • getURI(uint256 systemId): Retrieve the URI (metadata) for a specific point system.

Error Handling

The Points Protocol defines several custom errors to handle specific scenarios:

  • OnlyAdmin(uint256 systemId, address user): Thrown when a non-admin user tries to perform an admin-only action.

  • OnlyIssuer(uint256 systemId, address user): Thrown when a non-issuer contract tries to perform an issuer-only action.

  • InsufficientPoints(uint256 systemId, address user, uint256 available, uint256 required): Thrown when a user doesn’t have enough points for a specific operation.

  • ArrayLengthMismatch(): Thrown when the lengths of input arrays for batch operations don’t match.

Make sure to handle these errors appropriately in your code.

Subscribe to Stack
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.