Staff / Tech Lead Software Engineer — blockchain protocols & Web3 infrastructure, and production systems more broadly.
Where ideas become words (maybe). I write about blockchain protocols, Web3 infrastructure, and production systems more broadly — plus whatever else I run into building software day to day.
I worked on a production off-chain service: a system that watches Bitcoin activity and coordinates downstream operations on Ethereum for a cross-chain interoperability system, with more than one independent operator watching and acting on the same chain activity. It’s a monitoring and coordination role, not custody or key management: the service observes Bitcoin, decides what that activity means, and triggers the corresponding action elsewhere. Getting that decision right, without producing duplicate downstream effects, in the face of a chain that can change its mind, turns out to be most of the engineering problem.
A chain doesn’t hand you application state, it hands you a stream of events with a footnote attached: this stream can be revised. Ponder is one good vehicle for turning that stream into state you can actually query and trust, but the tool is secondary to the problem. This post is mostly about the problem.
The problem # A block your service already processed can stop being canonical. An RPC node can tell you two different things about the same height five minutes apart. An application built to read “current state” directly off the chain on every request has no principled way to handle any of that; it just re-derives an answer each time and hopes the chain agrees with itself in the meantime.
While researching vault standards to inform the design of a planned vault product on Rootstock, it became clear pretty quickly that “use ERC-4626” wasn’t the whole answer. The base standard covers a lot, but it also assumes a specific shape (one share token, one asset, everything settling synchronously) that doesn’t fit every vault a real product might need. I put together an internal walkthrough for the team, covering ERC-4626 and the standards that extend it, for exactly the cases where the base spec runs out. This post is that walkthrough.
At RootstockLabs, one of the products I owned the architecture for was the RootstockCollective dApp (frontend source) — a UI that needs to answer questions like “what’s this user’s balance,” “what has this contract emitted since block X,” and “show me the history of this account” on every page load. This is the story of how that UI went from asking the chain those questions directly, every time, to asking a decentralized indexing network instead — and why the process mattered as much as the destination.
A new user shows up with an address and no RBTC in it. Every transaction, including the very first one, needs gas, and gas on Rootstock is paid in RBTC. RIF Relay removes that requirement: a user pays with a token they already hold, or gets the transaction sponsored outright, while a separate account submits it and pays the actual gas.
At RootstockLabs, I led the team that extended and productionized RIF Relay, including the smart-contract changes required to support Boltz’s Rootstock integration, a non-custodial Bitcoin and Lightning swap service. This post covers how RIF Relay’s relay flow and smart-wallet architecture work, and what changed when a real integration stopped fitting the generic model.