Smart Contracts: What They Are and How to Build Them for Your Business

smart-contracts | | Cheesecake Labs
Summary
  • Smart contracts are self-executing, deterministic, immutable, transparent, and trustless programs that run automatically when predefined conditions are met, following a lifecycle of write, compile, deploy, and interact/execute.
  • Smart contracts cannot natively access off-chain data and rely on oracles or relay infrastructure for external inputs, which becomes especially relevant in cross-chain systems.
  • EVM (Solidity) and Soroban (Stellar/Rust) differ significantly in language, signature scheme, authorization model, storage model, events, and fee model, making cross-chain deployment a re-architecture rather than a simple translation, as shown in the VIA Labs engagement porting EVM modules to Soroban.
  • The VIA Labs Stellar implementation uses six Soroban contracts and a TypeScript relay driver centered on a Message Gateway V4 contract, featuring a unique transaction ID system based on chain prefixes and a three-tier signature validation process (chain signers, VIA signers, and project signers) to secure cross-chain messages.

Imagine a business agreement that executes itself: no intermediaries, no paperwork delays, no risk of someone not holding up their end of the deal. That’s the promise of smart contracts, and it’s no longer theoretical.

From decentralized finance to cross-chain infrastructure, smart contracts are quietly becoming the backbone of how modern digital businesses operate. Yet for most product and engineering leaders, the question isn’t whether smart contracts are relevant. It’s how to actually build and deploy them in production.

In this post, we break down what smart contracts are, how they work under the hood, and what a real-world implementation process looks like, drawing from our hands-on experience building cross-chain smart contract infrastructure at Cheesecake Labs.

What is a Smart Contract?

A smart contract is a self-executing program stored on a blockchain. It encodes the terms of an agreement directly into code, and runs automatically when predefined conditions are met,  without requiring any central authority or human intermediary.

Think of it as a vending machine: you insert the correct input (money + selection), and the machine delivers the output automatically. No cashier needed. The rules can’t be overridden mid-transaction.

The key properties:

  • Deterministic: given the same inputs, they always produce the same output
  • Immutable – once deployed, the code cannot be altered (unless explicitly designed with upgradeability)
  • Transparent – the code and transaction history are publicly verifiable on-chain
  • Trustless – parties don’t need to trust each other, only the code

Read more: The Role of User Experience in Blockchain and Web3 Adoption

How smart contracts work?

Smart contracts live on a blockchain network. When a user or another contract calls a function, the blockchain’s virtual machine executes it, updates state, and records the result on-chain permanently.

The lifecycle looks like this:

  1. Write: A developer writes contract logic in a smart contract language (Solidity for EVM-compatible chains, Rust for Soroban/Stellar)
  2. Compile: The code is compiled into bytecode the virtual machine can execute
  3. Deploy: The bytecode is submitted as a transaction and assigned a unique contract address
  4. Interact: Users or other contracts call functions on the deployed contract
  5. Execute: Blockchain nodes validate and execute the function, updating on-chain state

One important constraint: smart contracts can’t natively access off-chain data. They only know what’s on the blockchain. When they need external inputs like prices, real-world events, data from another chain, they rely on oracles or purpose-built relay infrastructure to bring that data on-chain.

That last point is where cross-chain systems get interesting.

The multi-chain reality: EVM vs. Soroban

Most developers start with Solidity on Ethereum or EVM-compatible chains (Polygon, Avalanche, BNB Chain). But the blockchain ecosystem is multi-chain, and each runtime has its own language, storage model, cryptographic primitives, and execution environment. That creates both opportunity and complexity.

At Cheesecake Labs, we’ve worked with clients navigating exactly this challenge. In our engagement with VIA Labs, a cross-chain messaging and validation protocol, we were tasked with porting EVM-based smart contract modules to Stellar’s Soroban environment, a fundamentally different smart contract runtime.

The differences aren’t cosmetic. Here’s a comparison between EVM and Stellar’s Soroban runtime, the two environments at the center of our VIA Labs work:

ConcernEVM (Solidity)Soroban (Stellar / Rust)
LanguageSolidityRust
Signature schemeECDSAEd25519 / CAP-0051
Authorization modelonlyOperator modifierSoroban authorization routines
Storage modelMappings, structsInstance / persistent / temporary (with TTL)
EventsSolidity event logsSoroban events (require explicit decoding)
Fee modelGas (post-execution)Resource pre-declaration + simulation

This kind of cross-chain deployment isn’t just a technical translation exercise. It’s a re-architecture that touches every layer of the stack, whichwhat requires deeply understanding both ecosystems and anticipating where assumptions break down.

Read more: What Are Stablecoins, and Why Should You Know About Them?

Key use cases for smart contracts in business

Before diving into what production development looks like, it’s worth grounding the why. Smart contracts are becoming standard infrastructure for:

Cross-chain asset transfers and messaging: Cross-chain communication is one of the hardest problems in blockchain infrastructure. And it’s also one of the best lenses for understanding what smart contracts really are. Not as a buzzword, but as production-grade, autonomous systems that encode business logic directly into code.

Protocols like VIA Labs enable assets and messages to move between blockchains. Smart contracts act as the validation and relay layer, ensuring a transfer confirmed on Chain A is properly verified and executed on Chain B, without a centralized bridge operator.

Decentralized Finance (DeFi): Lending, borrowing, yield farming, and automated market-making are all governed by smart contracts that enforce rules around collateral, liquidation, and fee distribution without a bank.

Tokenization of real-world assets: Real estate, commodities, and private equity can be represented as tokens on-chain, with smart contracts governing issuance, transfers, and compliance checks.

Supply chain and trade finance: Smart contracts can automate payment release upon delivery confirmation, reducing settlement times from days to seconds.

Subscription and payment automation: Recurring payments, royalty distributions, and revenue sharing codified directly in contract logic.

A real-world reference: VIA Labs on Stellar

VIA Labs is a cross-chain messaging and validation protocol. When they engaged Cheesecake Labs, the goal was to deploy their infrastructure on Stellar using Soroban smart contracts,  bringing trustless cross-chain communication to a network that operates very differently from the EVM ecosystem they had built on.

The VIA Labs protocol relies on two core modules:

  1. Off-Chain Validator: validates that messages crossing chains are legitimate, checking on-chain data and block confirmation rules
  2. Messaging System: handles the encoding, transmission, and reconstruction of cross-chain messages

The architecture

The VIA Labs Stellar stack is composed of six Soroban contracts (compiled to wasm32v1-none) and a TypeScript relay driver that bridges on-chain execution with off-chain coordination.

┌──────────────────────────────────────────────┐

│               Source Chain (Stellar)           │

│                                                │

│  [Application Contract]                        │

│        │  calls send()                         │

│        ▼                                       │

│  [Message Gateway V4]  ──► emits               │

│        │                   SendRequested       │

│        ▼                                        event               │

│  [Fee Handler]                                 │

└──────────────────────────────────────────────┘

               │

               │  Off-chain relayer picks up event

               ▼

┌──────────────────────────────────────────────┐

│          TypeScript Relay Driver                 │

│                                               │

│  1. Index SendRequested events                │

│  2. Collect signatures from signers            │

│  3. Call gateway.process() on destination      │

└──────────────────────────────────────────────┘

               │

               ▼

┌──────────────────────────────────────────────┐

│            Destination Chain (Stellar)         │

│                                                │

│  [Message Gateway V4]                          │

│        │  validates 3-tier signatures          │

│        │  checks POS handler (if set)          │

│        │  marks tx as processed                │

│        ▼                                       │

│  [Application Contract]                        │

│        message_process_from_gateway()          │

│        │                                       │

│        ▼                                       │

│  [Gas Handler]  ──► refunds relayer            │

└──────────────────────────────────────────────┘Code language: CSS (css)

Everything flows through the Message Gateway V4 contract, the core contract responsible for sending, validating, and delivering cross-chain messages.

Sending a message

When an application contract wants to send a cross-chain message, it calls gateway.send(). The gateway then verifies the caller is an authenticated contract (not a plain wallet), invokes the fee handler to collect protocol fees, generates a globally unique transaction ID, and emits a SendRequested event for off-chain relayers to index.

The transaction ID design is worth noting: each chain is assigned a message_prefix at deployment time, and the ID counter starts at message_prefix × 10²³. A chain with prefix 1 generates IDs starting at 100000000000000000000000, while prefix 2 starts at 200000000000000000000000. No two chains can produce the same ID without a deliberate collision in prefix assignment.

Three-tier signature validation

This is the security core of the protocol. Every inbound message must carry signatures from three independent validator sets, each with its own required threshold:

TierWho signsPurpose
Chain signersBlockchain-level validatorsAttest the event was observed on-chain
VIA signersVIA protocol infrastructureProtocol-level authorization
Project signersApplication-specific validatorsPer-contract business logic gates

On-chain, the gateway encodes the message to a canonical byte buffer and hashes it with keccak256. The TypeScript relay driver implements exactly the same encoding before signing — this is what makes cross-language signature verification possible. Both sides hash the same bytes, and the Ed25519 signature is valid on both.

For each signature in the delivery request, the gateway calls ed25519_verify(), looks up the public key in each signer set, increments the count for that tier, and rejects duplicate signers. Once all signatures are checked, it enforces that each tier’s count meets its configured threshold. If any tier is under-threshold, the entire transaction reverts.

The delivery flow also includes replay protection: the transaction ID is stored in persistent storage, and a second call with the same ID fails immediately. If any step in the delivery fails, the entire transaction reverts and the ID is never marked as processed, so the relayer can retry safely.

Read more: Cheesecake Labs Partners with VIA Labs to Power Real Cross-Chain Interoperability Across Stellar, Cardano, and EVM Networks

Storage and TTL: A Soroban specific challenge

One of the more nuanced aspects of Soroban development is storage management. Unlike EVM chains where storage persists indefinitely (at cost), Soroban persistent storage entries expire unless their TTL (time-to-live) is explicitly extended.

The gateway handles this explicitly:

  • Instance storage (configuration, signer sets, handler addresses): TTL extended on every contract invocation
  • Persistent storage (processed transaction IDs, per-contract settings): Minimum 100,000 ledgers (~15 days), maximum 200,000 ledgers (~30 days), extended on access

The processed-transfer tracking entries are the most critical here. If they expired, replay protection would silently disappear. The explicit TTL strategy ensures this can’t happen without a noticeable on-chain event.

The developer experience: Message client library

Rather than requiring every application contract to implement the full gateway interface from scratch, VIA ships a message-client library with a procedural macro that auto-generates the boilerplate.

Contracts that apply the macro get these methods generated automatically: gateway configuration, endpoint management, sender validation, and the inbound delivery hook. The only method a developer writes is message_process(env, message) — the actual business logic for handling an arriving message.

This is a meaningful DX decision: it separates protocol complexity from application logic, so teams building on top of VIA can focus on what their product does rather than how cross-chain delivery works.

The off-chain relay driver

The TypeScript relay driver is the glue between on-chain events and cross-chain delivery. It indexes SendRequested events from the source gateway, collects Ed25519 signatures from the validator sets, and submits delivery transactions to the destination gateway.

One important Soroban-specific detail: transactions require declaring resource usage upfront, before execution. The driver handles this by simulating the transaction first, extracting the minimum resource fee from the simulation response, and using that as the basis for the final fee before signing. This is fundamentally different from EVM gas, where you pay post-execution for what you actually used.

Porting these to Soroban required us to:

  • Decode Soroban events into human-readable format (since Soroban event encoding differs from EVM logs)
  • Reimplement ECDSA-based signature verification using Stellar’s native cryptographic primitives or CAP-0051
  • Translate complex storage structures (processedTransfers, enabledChains, bridgeOperators) into Soroban-compliant formats
  • Build an authorization control that mirrors Solidity’s onlyOperator modifier using Soroban’s authorization framework

This kind of work requires engineers who understand both ecosystems deeply — not just blockchain generalists, but specialists who can reason about protocol-level compatibility.

Read more: Blockchain Transactions: UTxO vs. Account-Based Models

What it takes to build smart contracts for production

The VIA Labs example illustrates something that’s easy to underestimate: the gap between writing a smart contract and building production-grade smart contract infrastructure.

Here are the decisions that matter most:

Choose the right chain and runtime

Your target blockchain determines the language, tooling, and constraints you’ll work within. EVM chains offer the largest developer ecosystem. Stellar/Soroban offers lower fees and faster finality. Solana offers high throughput. Each comes with real tradeoffs that affect your architecture.

Define your authorization model early

Who can call which functions? In Solidity, this is often handled with onlyOwner or onlyOperator modifiers. On Soroban, there are no modifiers, so you need to implement equivalent authorization explicit routines natively. Getting this wrong opens the door to unauthorized access or front-running.

Design your storage model deliberately

On EVM, storage persists indefinitely but costs gas per write. On Soroban, you have three storage types with different costs and TTL behaviors. Processed-transfer records, configuration, and application state may all need different storage strategies.

Handle storage carefully

On EVM chains, storage is expensive — every SSTORE operation costs gas. On Soroban, Stellar has distinct storage types (instance, persistent, temporary) with different cost profiles and expiration behaviors. Your data model needs to be designed with these constraints in mind.

Plan for upgradeability before you deploy

Immutability is a feature, but it’s also a risk. . If your contract has a bug, you need a migration plan. Common patterns include proxy contracts (EVM) or versioned deployments. Define your upgrade strategy before you deploy.

Audit before you ship

Smart contract bugs are often irreversible and can be catastrophic. A third-party security audit is non-negotiable for any contract that holds or moves real value. In the VIA Labs kickoff, one of the first questions was: Who is responsible for auditing contracts? That’s the right question to ask. A third-party security audit is non-negotiable for any contract that will hold or move real value.

Test against real network conditions

Unit tests are necessary but not sufficient. You need integration tests that simulate on-chain interactions, including edge cases like failed cross-chain messages, TTL expiration scenarios, and resource limit boundaries.

Build vs. Partner

If smart contracts are core to your product, you have two paths:

Build in-house: Requires hiring senior blockchain engineers with deep protocol knowledge, investing in tooling and security infrastructure, and staying current with rapidly evolving ecosystems. High cost, but full control and institutional knowledge.

Partner with a specialist firm: Faster time to market, access to battle-tested patterns, and lower risk for teams new to blockchain development. The right partner brings not just engineering, but protocol-specific expertise and cross-chain experience that’s hard to build from scratch.

The decision usually comes down to how central blockchain is to your long-term product. If it’s a foundational layer you’ll iterate on for years, building in-house makes sense. If you need to move fast or bridge a specific knowledge gap, a specialist partner is often the more pragmatic choice.

At Cheesecake Labs, we specialize in exactly this: helping product teams design, build, and deploy smart contract infrastructure — whether on EVM chains, Stellar/Soroban, or across multiple networks simultaneously.

Read more: Building a Passkey-Enabled Smart Wallet on the Stellar Network

Questions to answer before you start

Before writing a single line of contract code, align your team on:

  1. Which blockchain(s)? Single-chain or cross-chain? What are the fee, finality, and ecosystem tradeoffs for your use case?
  2. What’s the authorization model? Who can call what, and how is that enforced at the contract level?
  3. What data lives on-chain vs. off-chain? Storage costs money and has constraints — design your data model accordingly.
  4. How will upgrades work? What’s your migration plan if a critical bug is found post-deployment?
  5. Who audits the contracts? Budget for a third-party security audit before mainnet. This is not optional.
  6. What are the success criteria? Define what “done” looks like before you start building. Scope clarity is cheaper than scope creep.

These aren’t just technical questions — they’re product and business decisions that shape everything downstream.

Conclusion

Smart contracts are no longer a niche technology for crypto enthusiasts. They are maturing from experimental technology into foundational infrastructure. They’re becoming standard infrastructure for any business that needs automated, trustless, and auditable logic, from payments to asset management to cross-chain communication.

The patterns being established now, multi-tier signature validation, event-driven relay systems, explicit storage lifecycle management, are what production blockchain systems actually look like.

Building them well requires more than knowing a language. It requires deep ecosystem knowledge, rigorous security practices, and the architectural judgment to navigate tradeoffs that aren’t visible until you’re deep in implementation.

If you’re exploring how smart contracts could fit into your product, or if you’re facing the complexity of a multi-chain deployment, we’d love to talk.

legacy-app-ckl | | Cheesecake Labs

FAQ

What is a smart contract?

A smart contract is a self-executing program stored on a blockchain. It encodes the terms of an agreement directly into code and runs automatically when predefined conditions are met, without requiring a central authority or human intermediary. Its key properties are deterministic, immutable, transparent, and trustless.

How does a smart contract work from writing to execution?

The lifecycle includes: writing contract logic in a smart contract language (Solidity for EVM-compatible chains, Rust for Soroban/Stellar), compiling it into bytecode, deploying the bytecode as a transaction with a unique contract address, users or contracts interacting by calling functions, and blockchain nodes executing and validating the function while updating on-chain state. Smart contracts cannot natively access off-chain data and rely on oracles or relay infrastructure for external inputs.

What are the key differences between EVM and Soroban smart contract environments?

EVM (Solidity) uses ECDSA signatures, an operator modifier authorization model, mappings/structs for storage, Solidity event logs, and a post-execution gas fee model. Soroban (Stellar/Rust) uses Ed25519/CAP-0051 signatures, Soroban authorization routines, instance/persistent/temporary storage with TTL, Soroban events requiring explicit decoding, and a resource pre-declaration plus simulation fee model.

What are common business use cases for smart contracts?

Key use cases include cross-chain asset transfers and messaging, decentralized finance (lending, borrowing, yield farming, automated market-making), tokenization of real-world assets, supply chain and trade finance automation, and subscription/payment automation such as recurring payments and revenue sharing.

How does the VIA Labs cross-chain architecture on Stellar work?

The VIA Labs Stellar stack consists of six Soroban contracts and a TypeScript relay driver. An application contract calls gateway.send(), which verifies the caller, invokes a fee handler, generates a unique transaction ID, and emits a SendRequested event. Off-chain relayers index this event, collect signatures, and call gateway.process() on the destination chain, where the Message Gateway V4 contract validates three-tier signatures (chain signers, VIA signers, and project signers) before marking the transaction as processed and refunding the relayer via the Gas Handler.

About the author.

Maria Cecília Romão Santos
Maria Cecília Romão Santos

Computer science student. Marvel fan. Cooking lover. A dog person. Great travel companion. Curious about random and useless knowledge. And someone who marathons series like no one else.