By Sara Deleyto · Guest article · With a BACS legal commentary
“Code is law” and its promise
“Code is law” is one of the principles most closely associated with the blockchain ecosystem. The idea rests on a powerful promise: replacing certain trust-based human systems with rules executed automatically through smart contracts. No judges, no intermediaries and, in theory, no need to trust any person or institution. Just deterministic code executing previously defined rules.
On paper, it looks like an entirely new way of making agreements. If the code defines a condition and the blockchain executes it, the outcome should be beyond question.
And yet there is a difference between code executing exactly what we programmed and that outcome necessarily being the one we wanted.
What code actually guarantees
To understand this, we go back to 2016, when The DAO appeared — one of the most ambitious experiments of the Ethereum community. The idea was to create a decentralised organisation whose funds and rules were managed through smart contracts. Participants could contribute ETH and take part in decisions on how to use those funds.
The problem emerged in the implementation of one of its withdrawal functions. An attacker managed to exploit a reentrancy vulnerability to call the function repeatedly before the contract updated the internal state recording how much ETH they were owed.
The result was the extraction of an enormous amount of ETH from The DAO.
From a purely technical standpoint, the contract had executed the code it contained; the transaction was valid for the network. The blockchain had no concept of “this is not what the participants wanted”.
But the community did.
Ethereum then had to face a decision that could not be resolved by writing a new function in Solidity: should the outcome be accepted because the code had allowed it, or should the community intervene to reverse its consequences?
The debate ended up splitting the community. A hard fork eventually produced the chain we know today as Ethereum, while those who kept the original history continued as Ethereum Classic.
For me, The DAO shows a first major limitation of “code is law”.
A smart contract can guarantee that rules execute deterministically. It can guarantee what happens when certain conditions are met within the system. But it cannot guarantee that those rules are correct, that they cover every possible scenario, or that they represent exactly the intention of those who designed them.
Nor does immutability mean a system is necessarily untouchable. It means that, once deployed, the code and state have properties that make it difficult or impossible to directly modify what is already on the chain. If we want upgrade, pause or recovery mechanisms, we must have built them into the architecture beforehand.
And that difference — between executing a rule and knowing whether the rule is the right one — sits at the centre of many of the limits of smart contracts.
The real world does not fit on-chain
One of the most important things I have learned working with smart contracts is that, however secure and deterministic they are, they are isolated by design.
A blockchain can verify information that exists within its own network: balances, transactions, signatures, permissions or contract states. But it cannot directly access what is happening outside it.
A smart contract cannot know by itself the current price of an asset on an external market, whether a flight has landed, whether a physical product has been delivered, or whether a given real-world condition has been met.
This limitation matters because it means a contract cannot simply react to any external event. That information must first enter the blockchain.
This is where oracles come in.
Oracles work as a bridge between the blockchain and external sources of information. They can take data from markets, APIs, databases, sensors or other networks and bring it on-chain so a smart contract can use it.
Thanks to them, a contract can execute logic based on information that did not originally exist inside the blockchain: asset prices, weather conditions, event results, flight statuses, or any other data that can be turned into an input the contract can interpret.
But this mechanism introduces a new risk surface. The smart contract can verify that it has received a given price. What it cannot do by itself is check that the price correctly represents reality.
This became especially clear in the Harvest Finance incident in 2020. The protocol suffered an attack in which large trades and flash loans were used to cause temporary price movements in certain assets within the pools the system relied on. The attacker was able to exploit those discrepancies to interact with the protocol on favourable terms and extract value.
What is interesting about the case is not just that an economic vulnerability existed. It is that the smart contract was executing its rules on information that, from its own perspective, was valid.
The contract could not look outside the blockchain and say: “this price movement is artificial” or “this price does not really represent the market”. It simply received the available data and executed the programmed logic on it.
Here a distinction appears that I consider fundamental in the design of on-chain systems: the integrity of the code does not guarantee the integrity of the data it receives.
We can have a perfectly programmed, audited, deterministic smart contract and still get an incorrect result if one of the inputs on which it bases its decisions can be manipulated.
That is why, when we connect blockchain to the real world, it is not enough to ask what the contract does. We also have to ask where the information comes from, how it is obtained, how it is validated, how far it can deviate, and what happens when the data stops behaving as we expected.
When something goes wrong
One of the differences that has struck me most while developing smart contracts is that not all errors have the same chance of being corrected.
During the execution of a transaction, the EVM temporarily holds the changes the contract is making. If an operation fails and execution reverts, those changes never consolidate into the blockchain’s state. A reverted transaction does not leave behind a state partially modified by the reverted operations.
But this only works while the transaction is executing.
If the contract correctly executes an operation and it is recorded on-chain, the situation is different. The blockchain does not know whether the outcome was intended, whether it resulted from a programming error, or whether the user simply made a bad decision.
From the EVM’s point of view, the operation executed correctly.
Here an important difference appears between an execution error and a logic error.
An execution error can trigger a revert. A logic error, by contrast, can produce exactly the result the code defined — even if that result is completely different from what we expected.
And once that result has already modified the blockchain’s state, there is no general operation that simply allows an “undo”.
That is why the ability to fix a problem depends largely on the architecture we designed before deploying the contract.
A system can include pauses, limits, administrative roles, recovery functions or upgrade mechanisms. It can also be designed with patterns that allow part of the logic to be replaced later.
But all these mechanisms have something in common: the ability to correct the system had to be anticipated in advance.
If a contract includes no upgrade or intervention mechanism and a vulnerability allows its state to be modified in an unforeseen way, the options for acting directly on that contract can be extremely limited.
And this is where immutability stops being merely an interesting property and becomes an architectural decision.
Deploying a contract means accepting rules that, depending on how it was designed, may be very difficult to change afterwards. That is why security is not only about writing a function that works correctly. It is also about thinking through what happens when that function does not behave as we expected.
In many traditional systems, a typical response would be to fix the software and amend the affected data. On a blockchain, the response can be far more limited. Even if we can deploy a new version of the contract, the changes that already happened on-chain do not automatically disappear. The new architecture will have to decide how to live with that previous state and what mechanisms exist to protect affected users.
The limits, seen from the developer’s side
The more I work with smart contracts, the clearer it becomes to me that their main strength — the ability to execute rules deterministically — is also one of their main limitations.
Code can do exactly what it was designed to do. It can check a condition, update a state, transfer an asset or reject an operation. But it cannot decide whether the rule we are executing was the right rule in the first place.
Nor can it anticipate every way a user might interact with it, every piece of data it might receive, or every situation that may arise once the contract is running in a real environment.
This changes the way you think about development quite a bit.
In a traditional application, we can think of code as a tool to solve a specific problem. On a blockchain, code is part of a much wider system: contracts, users, economic incentives, interfaces, external data, governance mechanisms and, in many cases, real-world assets.
An error in any of those layers can end up affecting the behaviour of the entire system.
The DAO and Harvest Finance show two different versions of the same problem. In The DAO, the code executed logic that contained a vulnerability. In Harvest Finance, the protocol correctly executed its rules based on information that could be manipulated.
In both cases, the code never stopped working. The problem was that the whole system was more complex than the logic we had managed to represent inside the contract.
And I think that is where the true limit of what a smart contract can resolve begins.
A contract can automate rules, but it cannot fully automate the reality those rules try to act upon. It can remove certain intermediaries and make certain operations verifiable without relying on a central authority. But that does not mean every form of trust, governance or human intervention disappears.
On the contrary: the more value we place inside automated systems, the more important it becomes to properly design everything that exists around the code.
For me, this is one of the most interesting parts of building on blockchain.
It is not simply a matter of asking what we can put on-chain. We also have to ask what should be on-chain, what information the contract needs to work, where that information comes from, and what happens when the real world does not behave as our code expected.
Perhaps the limit of smart contracts is not in what they can execute. It is in everything they cannot understand by themselves.
BACS legal commentary: where code ends, law begins
Sara’s article ends exactly where legal analysis must begin: the limit of smart contracts lies not in what they can execute, but in everything they cannot understand by themselves. In legal terms, that sentence has a precise translation — and practical consequences.
The first consequence is conceptual. The two cases the article walks through show that “code is law” is an incomplete metaphor: in The DAO, the code faithfully executed a defective rule; in Harvest Finance, it faithfully executed a correct rule over manipulated data. In both, execution was flawless and the outcome unjust. The law has known this situation for centuries: it is the difference between the formal validity of an act and its material legitimacy — between what was done according to procedure and what ought to have been done. No serious normative system has survived on the first alone; that is why they all developed review mechanisms: nullity, annulment, unjust enrichment, restitution. Faced with The DAO, the Ethereum community improvised exactly that — a review mechanism — through a hard fork. It worked once, at the cost of splitting the chain in two. That is not a procedure; it was an exception.
The second consequence concerns design. Sara notes that the ability to correct a contract must be built into the architecture before deployment — pauses, roles, upgrade mechanisms. The BACS thesis is that the same logic reaches the legal layer: dispute resolution is not an external patch to the system but part of its architecture, and it must be designed with the same anticipation as a pause mechanism. In practice, that means arbitration clauses embedded in the protocol’s or product’s terms from day one, designed for this environment: defining which technical records (governance logs, oracle data, audit reports) are admissible as evidence and under what authenticity standard; providing for technical expert evidence and who bears its cost; and contemplating urgent measures at the speed assets move, not at the pace of cross-border court proceedings.
The third consequence closes the circle. If code cannot understand reality, someone must translate between the two: from external fact to on-chain data (the oracles the article describes) and — the reverse journey, still largely unexplored — from legal decision to on-chain execution. An arbitral award that can trigger, within the system’s own rules, the pause or recovery mechanisms already built into the architecture turns dispute resolution into what it should always have been: not paper chasing assets, but one more function of the system. That layer — call it legal oracles — is, in our view, the infrastructure the ecosystem is missing, and building it is BACS’s reason for being.
Code automates rules. Law answers for them. A mature ecosystem needs both to be designed to meet.
BACS operates a Court of Arbitration specialised in digital assets and therefore has a direct institutional interest in the mechanisms described in this commentary.
Sara Deleyto is a Solidity and Web3 full-stack developer, specialised in smart contracts, DeFi and artificial intelligence. She writes about the technical limits of on-chain systems from the perspective of someone who builds them. This article is published as a guest contribution at BACS.