I Built the Same Escrow on Two Chains. The Architectures Couldn't Be More Different.
I maintain a non-custodial escrow protocol that runs on two blockchains: Base, an Ethereum L2, and TON, the chain behind Telegram. Same product, same core logic on paper: lock funds, deliver work, release on approval, handle disputes. I expected the second implementation to be a port. It wasn't. The two chains disagree so fundamentally about how a contract should be structured that writing the same feature twice forced me to rethink what "the same" even means. This post is about those differences, the design decisions each model pushed me toward, and what I'd tell anyone about to make the same jump. Light on code, heavy on the reasoning. The interesting part was never the syntax. The two mental models The single most important difference is not the language. It's the execution model underneath. On Base , a contract is an object with shared state. You write Solidity, and it behaves like a class instance sitting in memory that everyone calls into. A user calls a function, the function reads and writes contract storage synchronously, and either the whole thing succeeds or it reverts atomically. All my escrows live in one contract, in one big mapping, and every call reaches straight into that shared state. On TON , a contract is an actor that receives messages. You write Tact, and it behaves like an isolated process with a mailbox. You don't call a function; you send a message, and the contract handles it in its own turn. There is no synchronous cross-contract call in the EVM sense. Interaction between contracts is asynchronous message passing, and you design around that or you fight it the whole way. The shape of the entry point tells the whole story. On Base, an external caller invokes a named function: function approveWork(uint256 _contractId) external validContract(_contractId) nonReentrant whenNotPaused { // reads and writes shared contract storage, synchronously } On TON, nothing "calls" the contract. A message arrives, and a handler consumes it in the actor's own