AI Computer Institute
Expert-curated CS & AI curriculum aligned to CBSE standards. A bharath.ai initiative. About Us

Smart Contracts: Programmable Transactions

📚 Blockchain⏱️ 21 min read🎓 Grade 11
✍️ AI Computer Institute Editorial Team Updated: September 2026 CBSE-aligned · Peer-reviewed · 21 min read
Content curated by subject matter experts with IIT/NIT backgrounds. All chapters are fact-checked against official CBSE/NCERT syllabi.

When Rain Doesn't Fall, Money Should Move — On Its Own

A cotton farmer in Bathinda, Punjab, buys a rainfall insurance policy before the kharif sowing season. In the traditional system, if the monsoon fails, she must file a claim, wait for a surveyor to visit her specific 2-acre plot, argue about whether the crop loss was really caused by drought and not pest damage or poor seed quality, and then wait weeks or months for a payout that may or may not arrive at the amount she expected. The India Meteorological Department (IMD) already publishes district-level rainfall data in near real time. The information needed to decide whether she is owed money exists the moment the monsoon data is published — but the payout does not happen automatically, because the contract enforcing it lives in a filing cabinet, a PDF, or a clause interpreted by a claims officer with discretion, incentives, and a backlog.

A smart contract removes that gap between "the condition is true" and "the money moves." It is a program, deployed on a blockchain, that holds funds in escrow and releases them the instant a defined condition is satisfied — with no claims officer, no discretion, and no possibility of the insurer quietly delaying payment. This chapter builds the concept from first principles: what a smart contract actually is as a piece of software, how it differs from an ordinary program, what it means for a transaction to be "programmable," where its real weaknesses lie, and how to trace one executing step by step.

What "Smart" Actually Means — and What It Doesn't

Strip away the marketing language and a smart contract is nothing more than: a program whose code and current state are stored on a blockchain, executed identically by every node that maintains that blockchain, and triggered only by transactions. Three properties follow directly from that definition, and each one is doing real work.

Deterministic. Every node in the network must arrive at the exact same result after executing the same transaction against the same starting state, or the network cannot agree on what happened. This rules out anything non-deterministic in the contract's own logic — no floating-point arithmetic (rounding can differ across hardware), no unseeded randomness, no reading the system clock for "now" in a way that could differ node to node. A smart contract can only use integer arithmetic and data that is either passed in with the transaction or already stored on-chain.

Replicated and tamper-evident. The contract's bytecode and its state variables are part of the blockchain itself. Changing them without going through a valid transaction, executed by consensus, would break the hash chain and be rejected by every honest node — the same integrity guarantee that protects the ledger of a single cryptocurrency transfer now protects an entire program's state.

Triggered by transactions, not by requests. A traditional web server or app answers requests: a client sends an HTTP call, the server runs some logic, and answers. A smart contract has no owner watching a dashboard and deciding when to run it. Its functions execute only when someone submits a transaction that calls them, that transaction is included in a block, and the network's nodes each re-execute it locally to update their own copy of the state. There is no "server" that could be told to skip the run, delay it, or run it differently for one user than another.

None of this involves machine learning, inference, or anything resembling judgment. This is the single most important thing to get right about the term, and it is worth stating precisely before going further, because it is exactly the kind of claim a student coming from a deep-learning-heavy curriculum is primed to get wrong.

Turing-Completeness and Gas: Why a Contract Can't Run Forever

Bitcoin has a scripting language too, but it was deliberately designed to be not Turing-complete: it has no loops, so every script is guaranteed to terminate, and the range of programs you can express is narrow — mostly "does this signature match this public key." Ethereum's innovation, introduced by Vitalik Buterin in the 2013 Ethereum whitepaper, was to make the on-chain execution environment (the Ethereum Virtual Machine, or EVM) Turing-complete: it supports arbitrary loops and general-purpose computation, which is what makes it possible to encode something as elaborate as a rainfall insurance policy rather than just a signature check.

Turing-completeness creates an obvious danger: an accidental or malicious infinite loop, re-executed by every node in the network, could halt the entire chain. Ethereum's answer is gas. Every single EVM operation — adding two numbers, comparing values, writing to storage — has a fixed cost measured in gas units, and the transaction that calls a contract function must supply a gas limit along with a price the sender is willing to pay per unit. If execution consumes more gas than the limit before finishing, the EVM halts immediately and reverts every state change the transaction attempted, as if it had never been submitted, though the gas already spent is not refunded. This gives smart contract execution a crucial property: partial completion is impossible. A transfer either completes in full or leaves no trace in the contract's state at all. Note also that writing a new value into contract storage is drastically more expensive in gas than an arithmetic operation on values already in memory — which is why well-written contracts minimize how often they write to storage, and why the rainfall contract you'll trace below only ever writes a handful of state variables, once each.

The Oracle Problem: How Does the Chain Know It Rained?

A blockchain, by design, only has direct knowledge of what happens inside itself — the transactions submitted to it and the state changes they cause. It has no native way to know the score of a cricket match, the closing price of a stock, or how many millimetres of rain fell in Bathinda district last week. Yet the entire value of the rainfall insurance contract depends on exactly that fact. This gap is called the oracle problem, and it is one of the genuinely hard, still-debated aspects of smart contract design, not a solved footnote.

An oracle is any mechanism that feeds real-world data onto the chain as a transaction, so a contract can read it. The catch is that the moment a contract trusts a single oracle address, the contract's guarantees are only as strong as that oracle's honesty — the "trustless" execution that made smart contracts attractive in the first place now depends on trusting exactly one off-chain party to report rainfall figures correctly. Production systems mitigate this with decentralized oracle networks that aggregate reports from many independent data providers and require a threshold of agreement before accepting a value, but they never eliminate the underlying dependency — they only spread the trust across more parties. In the worked example below, the contract has exactly one oracle address as a simplification; a real deployment would need to address this directly, and that is one of the practice questions at the end of this chapter.

Worked Example: Tracing a Rainfall Insurance Contract Line by Line

Below is a complete, minimal smart contract in Solidity, the dominant language for Ethereum-family contracts. It escrows a payout from an insurer, accepts a premium from a farmer, accepts a rainfall reading from a designated oracle, and settles automatically: if recorded rainfall is below the drought threshold, the farmer receives the payout; otherwise, the insurer receives the premium.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract RainfallInsurance {
    address public insurer;
    address public farmer;
    address public oracle;

    uint16  public thresholdMM;
    uint16  public recordedRainfallMM;
    uint256 public payout;
    uint256 public premium;

    bool public policyActive;
    bool public dataReported;
    bool public claimPaid;

    constructor(
        address _farmer,
        address _oracle,
        uint16  _thresholdMM,
        uint256 _payout
    ) payable {
        require(msg.value >= _payout, "underfunded pool");
        insurer     = msg.sender;
        farmer      = _farmer;
        oracle      = _oracle;
        thresholdMM = _thresholdMM;
        payout      = _payout;
    }

    function buyPolicy() external payable {
        require(msg.sender == farmer, "only registered farmer");
        require(!policyActive, "already active");
        premium = msg.value;
        policyActive = true;
    }

    function reportRainfall(uint16 mm) external {
        require(msg.sender == oracle, "only oracle");
        require(policyActive, "no active policy");
        recordedRainfallMM = mm;
        dataReported = true;
    }

    function settle() external {
        require(policyActive, "no active policy");
        require(dataReported, "rainfall not yet reported");
        require(!claimPaid, "already settled");

        claimPaid = true;
        policyActive = false;

        if (recordedRainfallMM < thresholdMM) {
            payable(farmer).transfer(payout);
        } else {
            payable(insurer).transfer(premium);
        }
    }
}

Now trace it exactly, transaction by transaction, with concrete numbers: threshold set to 40 mm, payout set to 8000 (units of value on the chain), premium of 500 paid by the farmer, and an oracle reading of 22 mm — a drought year.

StepCall & senderWhat executesContract balance after
1constructor(farmer, oracle, 40, 8000), sent by insurer with msg.value = 8000require(8000 >= 8000) passes. insurer, farmer, oracle, thresholdMM = 40, payout = 8000 are written. All booleans default to false.8000
2buyPolicy(), sent by farmer with msg.value = 500Both require checks pass (sender is farmer; not yet active). premium = 500, policyActive = true.8500
3reportRainfall(22), sent by oracleBoth checks pass. recordedRainfallMM = 22, dataReported = true.8500
4settle(), sent by farmerAll three checks pass. claimPaid = true, policyActive = false. Condition: 22 < 40 is true, so payable(farmer).transfer(8000) executes.8500 − 8000 = 500

Every state variable in that trace is either a value passed directly into a call or a deterministic function of values already on-chain — nothing depended on wall-clock time, floating-point rounding, or any node's private view of the world, which is exactly the determinism property from the first-principles section made concrete. Notice the final balance: 500 units of value, the farmer's premium, are left sitting in the contract with no function anywhere in this code that can move them out. That is not a rounding artifact of the trace — it is a genuine bug in the contract as written, and it belongs to a real, well-known class of smart contract defects called stranded funds: value that a contract can receive but has no code path to release. It's flagged explicitly here, and returned to as a practice question, because "the code compiled and ran without reverting" is not the same as "the code is correct" — a distinction that matters more for smart contracts than for almost any other kind of software, since a deployed contract typically cannot be patched.

The Common Misconception: "Smart" Does Not Mean Intelligent

Given everything else on this site's curriculum — neural networks, transformers, large language models — the natural and wrong assumption is that a "smart" contract is smart the way a chatbot is smart: that it evaluates context, weighs evidence, or makes a judgment call about whether the farmer's crop loss was "really" due to drought. It does none of that. Look again at the settle() function: it is a single if/else on an integer comparison, recordedRainfallMM < thresholdMM. There is no model, no training data, no probability, no confidence score. The word "smart" in this context, coined in the 1990s by legal scholar and computer scientist Nick Szabo well before Ethereum existed, meant only that the contract's terms are expressed as executable code that enforces itself, rather than as prose that requires a court, a claims officer, or a counterparty's goodwill to enforce. A vending machine is the classic pre-blockchain analogy Szabo used: insert the correct coins, and the machine mechanically dispenses the item — no clerk, no negotiation, no discretion. A smart contract is a vending machine whose mechanism happens to be software replicated across a network instead of gears inside a metal box. Confusing "self-executing" with "intelligent" leads students to expect smart contracts to handle ambiguous, judgment-based situations well, when in fact they are good at exactly the opposite: situations where the triggering condition can be reduced, in advance, to an unambiguous number or boolean that some trusted feed can report.

A Real Failure Mode: Reentrancy and the Danger of Transfer Ordering

Because a smart contract's functions can call external addresses mid-execution — as settle() does when it calls payable(farmer).transfer(payout) — the order of operations inside a function is not a style preference; it is a security property. Look closely at settle() again: claimPaid = true and policyActive = false are set before the transfer happens. This ordering, known as "checks-effects-interactions," is deliberate. If the transfer happened first and the state updates second, a malicious recipient address could, in principle, be written so that receiving the funds triggers it to call back into settle() again before claimPaid had been flipped to true — draining the contract through repeated re-entrant calls before the guard condition ever updates. This exact bug, at a scale of roughly $60 million worth of Ether, is what destroyed "The DAO" in June 2016 and led to a contentious hard fork of the entire Ethereum blockchain to reverse the theft. It is mentioned here not as a security elective but because it is the sharpest illustration of what "programmable transaction" really means: the contract is not just moving money according to a condition, it is a general-purpose program, and every ordering decision inside it is part of its economic logic, not just its bookkeeping.

Active Recall

Attempt each question before reading its answer.

  1. A classmate says, "Smart contracts are called smart because they use AI to decide fair payouts." What is wrong with this statement, and what does "smart" actually refer to?
  2. In the RainfallInsurance trace, suppose the oracle had reported 55 mm instead of 22 mm. Re-trace settle(): which branch executes, who receives funds, and what is the contract's final balance?
  3. Why must Solidity avoid floating-point arithmetic and unseeded randomness inside contract logic, when ordinary Python or C++ programs use both freely?
  4. What is the oracle problem, and specifically, what single point of failure exists in the reportRainfall function of the contract above?
  5. The trace showed 500 units of premium permanently stranded in the contract after a drought payout. Write, in one or two lines of pseudocode, the smallest change to settle() that would prevent this.
  6. Explain why gas exists, and what would happen to the entire Ethereum network if it did not.

Answers

  1. It is wrong because nothing in a smart contract involves models, training, inference, or judgment. "Smart" (a term from Nick Szabo, pre-dating blockchains) means the contract's terms are executable code that enforces itself once deployed, the way a vending machine mechanically dispenses an item for the correct coins — not that it exercises intelligence. Every decision the contract makes is a plain comparison on data already available to it.
  2. With recordedRainfallMM = 55 and thresholdMM = 40, the condition 55 < 40 evaluates to false, so the else branch executes: payable(insurer).transfer(premium) sends 500 to the insurer. Before this call the balance was 8500 (8000 payout pool + 500 premium); after, it is 8500 − 500 = 8000, which is exactly the untouched payout pool — correctly stranded now in the sense that, symmetrically, this version of the contract also has no function to return that 8000 to the insurer once no drought occurs and the policy period is over.
  3. Every node on the network must execute the same transaction and reach an identical resulting state, or the network cannot agree on the blockchain's contents (a consensus failure). Floating-point rounding can differ subtly across hardware and compilers, and unseeded randomness is by definition not reproducible — either would let two honest nodes compute two different "correct" answers from the same input, which breaks consensus. Restricting execution to deterministic integer arithmetic on data already agreed upon avoids this entirely.
  4. The oracle problem is that a blockchain has no native way to observe real-world facts outside its own transaction history, so any contract depending on external data (rainfall, prices, scores) must trust some off-chain reporter to submit it as a transaction. In reportRainfall, the single point of failure is the hardcoded oracle address: whoever controls that one address can report any rainfall figure they choose, honest or not, and the contract has no way to check it against a second source.
  5. Add an insurer-only withdrawal path, for example: after the if/else in settle(), when the drought branch pays the farmer, also transfer the leftover premium to the insurer (payable(insurer).transfer(premium)) instead of leaving it in the contract; symmetrically, when the no-drought branch pays the insurer the premium, also return any unused portion of the payout pool to the insurer via a separate withdrawUnusedPool() function restricted to msg.sender == insurer.
  6. Gas exists because the EVM is Turing-complete and therefore cannot guarantee, just by reading a contract's code, that any given execution terminates. Without a gas limit that a transaction must pay for and that halts execution once exhausted, a single buggy or malicious infinite loop, once submitted, would have to be re-executed by every node in the network trying to process that block, and none of them could ever finish — halting the entire chain rather than just failing one transaction.
Rainfall insurance smart contract: escrow, oracle trigger, and automatic settlement Insurer funds the contract, farmer pays premium, oracle reports rainfall, and the contract self-executes settle() to pay either the farmer or the insurer, replicated identically across network nodes. Insurer deploys contract funds payout pool: 8000 Farmer buyPolicy() pays premium: 500 Smart Contract RainfallInsurance thresholdMM = 40 recordedRainfallMM = 22 policyActive, dataReported claimPaid settle(): 22 < 40 ? true → pay farmer Oracle IMD rainfall feed reportRainfall(22) ① deploy + fund ② buyPolicy() ③ reportRainfall(22) ④ payout 8000 (else) refund 500 Same bytecode, same state, executed independently by every node: Node A settle() → pay farmer Node B settle() → pay farmer Node C settle() → pay farmer No single node can produce a different outcome — the result is recomputed, not looked up.

Think About It

Think about this: How would you explain smart contracts: programmable transactions to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.

Key Takeaways — Summary and Recap

Let us recap what we covered: the core ideas behind smart contracts: programmable transactions, how they connect to real-world applications, and why they matter for your journey in computer science. Remember these key points as you move forward. For competitive exam preparation (CBSE, JEE, BITSAT), focus on understanding the WHY behind each concept, not just the WHAT.

← Blockchain: Distributed Immutable LedgerCryptographic Hash Functions: Digital Fingerprints →

Found this useful? Share it!

📱 WhatsApp 🐦 Twitter 💼 LinkedIn