Modular Stack Solutions (Execution + DA + Settlement)

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Modular Stack Solutions (Execution + DA + Settlement)
Complex
from 2 weeks to 3 months
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1215
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1043
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Development of Modular Stack (execution + DA + settlement)

A monolithic blockchain does everything itself: executes transactions, ensures data availability, finalizes state. The modular approach splits these functions between specialized layers. Result—an ecosystem where you choose components like modules: Celestia for DA, Ethereum for settlement, OP Stack or Arbitrum Orbit for execution. This is not theory—this is how dozens of mainnet L2s and L3s are built in 2024–2025.

Typical request: "we want our own appchain with low fees and custom logic, but with Ethereum security." This is a correctly formulated task, and a modular stack is the right answer.

Layers and Their Roles

Execution Layer

Executes transactions, maintains state. This is your chain—with its own rules, gas token, precompiles.

OP Stack (Optimism, Base, Zora) is the most mature framework for Optimistic Rollup-based L2/L3. EVM-equivalent. op-geth + op-node + op-batcher + op-proposer.

Arbitrum Orbit is Arbitrum-based L2/L3. Supports Stylus (WASM smart contracts in Rust/C++). More flexible gas and permission model customization.

Polygon CDK is a ZK-based chain development kit. zkEVM under the hood. More complex in operation, but ZK finality instead of fraud window.

Sovereign rollup via Rollkit is execution layer with any execution environment, settlement in any chain (or without settlement at all). Maximum flexibility, minimum maturity.

Data Availability Layer

Blocks must be available for download—otherwise fraud proofs and state reconstruction are impossible. DA layer stores transaction data (calldata or blobs).

Ethereum L1 (EIP-4844 blobs) has maximum security, highest cost. After EIP-4844: ~3–6 blobs per block, each blob ~128KB, blob gas cost is separate from execution gas. Blobs are removed via ~18 days, but commitment (KZG) remains forever.

Celestia is a specialized DA layer. Data availability sampling (DAS): light nodes verify availability via random sampling, not downloading the full block. Cost is orders of magnitude lower than Ethereum blobs with comparable security guarantees for most use cases.

EigenDA is a DA layer on top of Ethereum via EigenLayer restaking. Economic security from restaked ETH. Significantly higher throughput than Ethereum L1 with higher security guarantees than Celestia (currently).

Avail is a DA layer with data availability sampling, forkless upgrades. Good alternative to Celestia.

Settlement Layer

Finalization: determines what is canonical state of rollup. Handles withdrawals, resolves disputes.

For most projects—Ethereum mainnet via L1 bridge contract. Alternative for L3—use L2 as settlement layer (e.g., Arbitrum One as settlement for Orbit chain).

Practical Assembly: OP Stack + Celestia + Ethereum

Here's a specific configuration used in production.

Components

[Users/Apps]
     ↓
[op-geth (execution)] ← custom EVM, your precompiles
     ↓
[op-node (rollup node)] ← derive chain state, communicate with L1
     ↓
[op-batcher] → [Celestia] ← publishes batch data to Celestia
     ↓
[op-proposer] → [L1 Settlement Contract] ← publishes state roots to Ethereum

Celestia DA Setup

// Celestia client for sending blobs
import (
    "github.com/celestiaorg/celestia-node/api/rpc/client"
    "github.com/celestiaorg/celestia-openrpc/types/blob"
)

type CelestiaDA struct {
    client    *client.Client
    namespace blob.Namespace
}

func (c *CelestiaDA) Submit(ctx context.Context, data []byte) (uint64, error) {
    b, err := blob.NewBlob(0, c.namespace, data)
    if err != nil {
        return 0, fmt.Errorf("create blob: %w", err)
    }
    
    height, err := c.client.Blob.Submit(ctx, []*blob.Blob{b}, blob.DefaultGasPrice())
    if err != nil {
        return 0, fmt.Errorf("submit blob: %w", err)
    }
    
    return height, nil
}

func (c *CelestiaDA) Retrieve(ctx context.Context, height uint64) ([]byte, error) {
    blobs, err := c.client.Blob.GetAll(ctx, height, []blob.Namespace{c.namespace})
    if err != nil {
        return nil, err
    }
    if len(blobs) == 0 {
        return nil, ErrBlobNotFound
    }
    return blobs[0].Data, nil
}

Namespace is a 29-byte identifier of your rollup in Celestia. Need to reserve a unique namespace before launch.

op-batcher Configuration for Celestia

OP Stack batcher does not natively support Celestia—need custom DA provider via AltDA (Alternative DA) interface:

// AltDA provider implementation for Celestia
type CelestiaAltDA struct {
    da *CelestiaDA
}

func (c *CelestiaAltDA) GetInput(ctx context.Context, commitment []byte) ([]byte, error) {
    // Decode commitment → Celestia block height + namespace
    height, err := decodeCommitment(commitment)
    if err != nil {
        return nil, err
    }
    return c.da.Retrieve(ctx, height)
}

func (c *CelestiaAltDA) SetInput(ctx context.Context, data []byte) ([]byte, error) {
    height, err := c.da.Submit(ctx, data)
    if err != nil {
        return nil, err
    }
    return encodeCommitment(height), nil
}

In op-batcher configuration:

[da]
type = "celestia"
rpc = "http://celestia-light-node:26658"
auth_token = "${CELESTIA_AUTH_TOKEN}"
namespace = "0x0000000000000000000000000000000000yournamespace"

L1 Settlement Contracts

Two contracts deploy to Ethereum:

OptimismPortal is the entry/exit point for cross-domain messages and withdrawals. Handles challenge window for Optimistic.

L2OutputOracle stores state roots proposed by proposer. This is what withdrawal finality depends on.

// Simplified interaction scheme
contract L2OutputOracle {
    struct OutputProposal {
        bytes32 outputRoot;    // keccak256(state_root, msg_passer_storage_root, latest_block_hash)
        uint128 timestamp;
        uint128 l2BlockNumber;
    }
    
    OutputProposal[] public l2Outputs;
    address public proposer;
    uint256 public constant FINALIZATION_PERIOD = 7 days;
    
    function proposeL2Output(
        bytes32 _outputRoot,
        uint256 _l2BlockNumber,
        bytes32 _l1BlockHash,
        uint256 _l1BlockNumber
    ) external payable {
        require(msg.sender == proposer, "Not proposer");
        // Verify l1BlockHash matches _l1BlockNumber
        require(blockhash(_l1BlockNumber) == _l1BlockHash, "Bad L1 block");
        
        l2Outputs.push(OutputProposal({
            outputRoot: _outputRoot,
            timestamp: uint128(block.timestamp),
            l2BlockNumber: uint128(_l2BlockNumber)
        }));
    }
}

Execution Layer Customization

Custom Precompiles

Precompiles are pre-compiled contracts at fixed addresses with native implementation. For example, add BLS12-381 operations or custom hash algorithm:

// In op-geth: adding custom precompile
var CustomPrecompiles = map[common.Address]vm.PrecompiledContract{
    common.HexToAddress("0x0000000000000000000000000000000000000100"): &blsG1Add{},
    common.HexToAddress("0x0000000000000000000000000000000000000101"): &customHashFunction{},
}

type blsG1Add struct{}

func (c *blsG1Add) RequiredGas(input []byte) uint64 {
    return 500  // fixed cost
}

func (c *blsG1Add) Run(input []byte) ([]byte, error) {
    if len(input) != 128 {
        return nil, errors.New("invalid input length")
    }
    // BLS G1 point addition
    p1 := new(bls12381.G1Affine)
    p2 := new(bls12381.G1Affine)
    p1.Unmarshal(input[:64])
    p2.Unmarshal(input[64:])
    
    result := new(bls12381.G1Affine).Add(p1, p2)
    return result.Marshal(), nil
}

Gas Token Customization

OP Stack supports Custom Gas Token—a native gas token different from ETH. This allows using your ERC-20 token as gas.

Limitation: custom gas token must be deployed on L1, have standard ERC-20 interface, and have no transfer fees (rebasing/fee-on-transfer tokens not supported).

Fee Structure and Sequencer Revenue

User Transaction Fee = (base_fee + priority_fee) × gas_used    [L2 execution cost]
                     + L1 data fee                              [cost of DA]

Sequencer Revenue = collected fees - DA costs - L1 costs

When using Celestia instead of Ethereum for DA, L1 data fee decreases by 90–95% for most transactions. This is the main economic argument.

Modular Stack Monitoring

Monitor all three layers independently:

# Key metrics
execution_layer:
  - l2_block_time_seconds        # should be stable
  - sequencer_queue_depth        # load on sequencer
  - tx_pool_size                 # mempool size

da_layer:
  - celestia_blob_submission_latency_ms
  - celestia_blob_submission_cost_utia  # cost in TIA
  - da_submission_failures_total

settlement_layer:
  - l1_output_proposal_delay_blocks  # proposer not lagging?
  - l1_finalization_pending_count    # withdrawals awaiting finalization
  - l1_gas_price_gwei                # proposer transaction cost

Alerting: if DA submission starts lagging behind block production—this is a blocking issue. Without DA blocks are unverifiable, and challengers cannot get data for fraud proofs.

Decomposition by Timeline

Phase Content Duration
Design Choose stack, namespace, tokenomics, bridge design 2–3 weeks
Core setup op-stack deployment, L1 contracts, genesis 3–4 weeks
DA integration Celestia/EigenDA connector, batcher config 2–3 weeks
Testnet Public testnet, bridge testing, stress test 3–4 weeks
Security Bridge contract audit, fault proof testing 4–6 weeks
Mainnet Deploy, sequencer ops, monitoring 2–3 weeks

Critical path is bridge contract audit. Bridge is where user funds live, and it's where most L2s found critical vulnerabilities. Don't skimp on bridge audit.

Total: 16–23 weeks from start to mainnet. Team: 2–3 backend engineers with Go experience, 1 Solidity developer, DevOps/infrastructure engineer.