Smart contracts

Smart Contract Examples From Production: What We've Shipped and What It Taught Us

Smart Contracts
Published: April 4, 2025Updated: October 15, 2026
Smart Contract Examples From Production: What We've Shipped and What It Taught Us

On Ethereum, the code you deploy is, by default, the code you live with. There's no patch release and no rollback. If a contract holds funds and has a bug, the bug holds the funds too. That single fact shapes almost every decision in smart contract work, and it's why we'd rather show real examples than another list of industries that "could use smart contracts."

Below are three pieces of production work from our own case studies, what each contract actually does, and what each one taught us. We've left out usage and volume figures on purpose. The engineering is the useful part.

DEX223: when the token standard is the bug

DEX223 is a decentralized exchange built around the ERC-223 token standard. To see why that matters, start with how ERC-20 tokens get lost.

An ERC-20 transfer just updates two balances in the token contract. If the recipient is another contract, that contract isn't told anything happened. If it was never written to handle that token, there's no function to send it back out, and the tokens sit there permanently. That's why DEXs built on ERC-20 use the two-step approve-then-transferFrom pattern for deposits: the exchange pulls tokens it has been allowed to take, so it knows who deposited what. Users who skip that and send tokens straight to the contract address lose them.

ERC-223 changes the transfer itself. When the recipient is a contract, the token calls tokenReceived(from, value, data) on it. If the recipient doesn't implement that function, the whole transfer reverts and the sender keeps the tokens. The EIP-223 spec lays this out in a page or two.

For an exchange, that turns a deposit into one transaction, and the contract learns the sender and amount at the moment tokens arrive. But DEX223 also supports ERC-20, with unified liquidity across both standards, because that's where the market is. So the contracts carry two accounting paths: a pull path for ERC-20 and a push path for ERC-223. Getting both to land in the same pool state, with no way to credit a deposit twice, is the real work.

Lesson one: a callback is an external call. Any token standard that notifies the recipient also lets the token run code in the middle of your logic, so the usual discipline applies (update state before calling out, guard against reentrancy, and never assume the token contract is friendly).

Permissionless listings mean hostile tokens

DEX223 lists tokens through contracts rather than through an admin. Anyone can create a market, and the listing mechanism is extensible, with different listing contract types supporting different fee structures. No gatekeeper is good for openness. It also means the exchange will interact with tokens nobody has reviewed.

Our view is that a permissionless venue has to assume some tokens are adversarial. That means measuring the balance change a transfer actually produced instead of trusting the amount argument (fee-on-transfer tokens deliver less than they claim), treating rebasing balances with suspicion, and making sure one broken token can't block withdrawals of anything else.

Margin inside the protocol

DEX223 also builds lending and margin trading into the protocol layer, which the project calls encapsulated margin trading. Lending and liquidation are coordinated by outside actors who are paid an incentive to act, rather than by a company running a liquidation bot. The lesson there is about incentives as much as code: a liquidation system only works if someone is always profitable to call it, including on a bad day for gas prices.

One more structural choice: the user interface is decoupled from the contracts. Anyone can build a different frontend against the same deployed logic. If one frontend goes down, the exchange keeps working.

Blokstorage: store the proof, not the file

The second example is much smaller in code and, for many businesses, more relevant. Blokstorage lets you prove a file existed at a point in time and hasn't changed since. It does that by hashing the file and storing a proof record on chain. The file itself never goes on chain.

That's the right call, and the reasons are worth spelling out. On-chain storage is expensive, and a 32-byte hash costs the same whether the file is a one-page letter or a large dataset. Files often contain information that shouldn't be public forever, and a hash reveals nothing about the content. And immutable storage is a bad home for anything someone may later have a legal right to have deleted.

The less obvious lesson is about bytes. A hash proves that one exact sequence of bytes existed. Re-save a PDF, change a line ending, or encode the file differently, and you get a different hash, even though a person would call it the same document. Blokstorage supports several encodings (ZIP with Base64, Base85 and Base91) and its verification step checks across those encodings, precisely because a proof is only useful if the verifier can reproduce the exact input. If you design a proof system, define the canonical form of the input before you write the contract.

And be clear with users about what the proof says. It shows existence and integrity. It says nothing about who authored the file or whether its contents are true.

Vaulta and Antelope: a different contract model

Our third set of examples comes from Antelope chains, mainly Vaulta (the network formerly called EOS), where we built Blocksfinity and run block producer infrastructure. Much of Blocksfinity's work is calling contracts we didn't write: system actions for resources, and the swap between EOS and A, which is a 1:1 conversion handled by a system contract on the same chain.

Antelope contracts look different from Solidity in ways that change how you design.

Contracts are written in C++ and compiled to WebAssembly. Every contract lives on a named account, and accounts have hierarchical permissions (owner and active by default, plus any custom ones you define). A custom permission can be linked to specific actions on a specific contract, which is a clean way to give a backend service a key that can do one job and nothing else.

Users don't pay gas per transaction in the Ethereum sense. An account needs CPU and NET to send transactions, which can be rented through the powerup mechanism, and RAM to store state, which is bought. Contracts decide whose RAM pays for each table row. Get that wrong and either your contract account funds every user's storage or users hit errors they don't understand. A big part of Blocksfinity's job is turning CPU, NET and RAM into controls an ordinary person can act on.

Contracts are upgradeable by default. Whoever controls the account's active authority can deploy new code. That's handy for fixing bugs and a real trust question for users. If a team wants to prove a contract can no longer change, it has to give that authority away, typically by assigning the account's permissions to an account nobody controls. When you integrate with someone else's Antelope contract, look at who holds its permissions before you trust it with anything.

Blocksfinity also keeps reads and writes apart. The explorer side indexes and queries chain data; the action side builds transactions and hands them to the user's wallet to sign. That separation made each half simpler to test, and it kept signing entirely in the user's hands.

What production taught us about shipping contracts

Across all three, a few lessons repeat.

Decide on upgradeability up front, and say it out loud. On EVM chains you can use proxy patterns; on Antelope upgrades are the default. Either way, an upgrade path is an admin key, and an admin key is a target. If you keep one, put it behind a multisig and a timelock so users can see changes coming. If you give it up, accept that a bug becomes permanent.

Audits are necessary and not sufficient. A good audit catches implementation errors: reentrancy, missing access checks, arithmetic and rounding mistakes. It's much weaker at catching a broken economic design, such as a liquidation incentive that doesn't pay when it matters. Scope the audit to the final code, fix findings, and get the fixes reviewed too.

Test on a real testnet as well as in a local simulator. Local tests are fast and you need lots of them. But resource limits, permission setups, wallet behavior and RPC quirks only show up on a live network. For Vaulta we use the Jungle testnet; for Ethereum, Sepolia. Run the full user flow there, including the failure cases: insufficient resources, rejected signatures, a token that reverts.

Keep the UI replaceable. The contract is the product's guarantee; the frontend is a convenience. If your contracts only make sense through your own website, you've rebuilt a centralized service at a higher cost.

And put as little on chain as you can get away with. State transitions that need to be trustless belong there. Files, personal data and anything that might need correcting usually don't. We go deeper on how a transaction becomes final in our post on transaction verification.

If you're planning a contract system and want people who've shipped on both EVM and Antelope to look at the design, talk to us.

ShareXLinkedIn

Keep Reading