6. Smart Contracts and Decentralized ApplicationsIntroduction and ContextBlockchain systems become operationally useful when they do more than record transfers. Smart contracts allow rules, obligations, and state transitions to be encoded and executed by a distributed network. Decentralized applications (dApps) combine these contracts with user interfaces, wallets, off-chain services, and sometimes decentralized storage. Together, they form an application architecture in which trust is shifted from a central operator toward publicly verifiable code, cryptographic authorization, and consensus. This shift does not eliminate trust. Users must still trust the blockchain protocol, the contract code, wallet software, oracle mechanisms, governance arrangements, and the assumptions made by application developers. A smart contract can enforce exactly what it is programmed to enforce, but it cannot determine whether the underlying program expresses the parties’ real intentions. This distinction is central to both cybersecurity and professional blockchain engineering. A dApp therefore has a broader lifecycle than a conventional web application. It must be specified, designed, coded, tested, audited, deployed, monitored, governed, and, where permitted, upgraded. Security decisions made at one stage can constrain all later stages. An immutable contract with a design flaw may be impossible to repair without migration or governance intervention, while an upgradeable contract introduces administrative and trust risks of its own. Learning ObjectivesAfter studying this chapter, students should be able to: 1. Explain the architecture and execution model of smart contracts and dApps. 2. Distinguish contract state, transactions, calls, events, wallets, and oracles. 3. Apply lifecycle, threat-modelling, testing, deployment, and upgrade frameworks. 4. Describe common token standards and assess their security implications. 5. Develop and evaluate a foundational Solidity contract using appropriate tools. 6. Analyse an applied dApp scenario from technical, organizational, ethical, and governance perspectives. The Smart-Contract Execution ModelA smart contract is a program deployed to a blockchain address. It contains executable logic and persistent state. On an Ethereum-compatible network, contract code runs in a virtual machine, commonly called the Ethereum Virtual Machine (EVM). The EVM is deterministic: given the same valid transaction, prior state, and execution rules, participating nodes should reach the same result. A transaction is an authenticated request, normally signed by a private key, that may transfer value, invoke contract code, deploy a contract, or alter blockchain state. Transactions consume computational resources measured as gas. Gas pricing discourages denial-of-service through unlimited computation and compensates validators or block producers. If execution fails, state changes are generally reverted, although the transaction fee may still be consumed. A contract function can be invoked in two fundamentally different ways. A state-changing transaction is signed, broadcast, included in a block, and paid for by the caller. A read-only call is executed locally or through a node without changing blockchain state and normally requires no transaction fee. The distinction is operationally important: a user interface may display a balance through a call but must submit a transaction to transfer assets. Blockchain state includes account balances, contract storage, nonces, and other protocol-defined data. Storage is persistent but expensive, so efficient data structures matter. Events provide an indexed, log-like record of significant actions. They are useful for user interfaces, analytics, and monitoring, but they are not a substitute for contract state: contracts cannot generally read historical event logs as ordinary storage. A contract does not automatically know facts about the external world. It cannot directly retrieve a currency price, determine whether a shipment arrived, or verify a weather condition. Such information must enter through an oracle mechanism. This creates an important boundary: blockchain consensus can establish what was submitted to the contract, but it cannot by itself establish whether the submitted external fact was true. From Contract to dAppA dApp usually contains several layers: - On-chain contracts: business rules, asset ownership, permissions, and settlement logic.
- Wallet and signing layer: key management, transaction approval, and user authentication.
- Client interface: web or mobile screens that read blockchain data and request signed actions.
- Node or provider layer: interfaces such as JSON-RPC through which clients access the network.
- Off-chain services: indexing, search, notifications, identity checks, computation, and data storage.
- Governance and operations: administrators, multisignature authorities, upgrade mechanisms, monitoring, and incident response.
Decentralization is not binary. A dApp may decentralize settlement while retaining centralized hosting, indexing, administration, or oracle infrastructure. Architectural claims should therefore identify which functions are decentralized and which remain dependent on organizations or service providers. A useful design question is not “Can this application use a blockchain?” but “Which properties require shared, tamper-evident state, and what costs follow from placing them on-chain?” Public blockchains offer transparency and composability, but they impose latency, transaction fees, data-visibility concerns, and limited computation. Sensitive personal data should generally not be placed directly on a public ledger. Hashes, commitments, encrypted references, or off-chain records may reduce exposure, but a public hash can still reveal information through correlation or dictionary attacks. Wallets, Keys, and User AuthorizationA wallet is primarily a key-management and transaction-signing system, not a container that physically stores coins. On many networks, assets are associated with addresses recorded by the ledger; the wallet controls the private keys that authorize transactions from those addresses. Externally owned accounts are controlled by private keys, whereas contract accounts are controlled by code. The loss, theft, or unauthorized use of a private key can lead to irreversible asset loss. Consequently, wallets must be evaluated as security boundaries. Hardware wallets isolate key operations; multisignature wallets require approval from multiple authorized parties; smart-contract wallets can implement recovery, spending limits, or social authorization, but add code and governance complexity. Wallet authentication should be distinguished from ordinary password authentication. A dApp may request a wallet signature to prove control of an address, but signed messages must have clear domain separation, expiration, purpose, and replay protection. A malicious interface can trick a user into signing a transaction or approval that appears unrelated to the intended task. Transaction simulation, human-readable signing prompts, and least-privilege approvals reduce this risk. Token Standards and Their Design ConsequencesToken standards provide common interfaces that allow wallets, exchanges, applications, and analytics systems to interoperate. The standard does not guarantee that an implementation is correct or that an economic design is sound. An ERC-20-style fungible token represents interchangeable units. Typical functions include balance queries, transfers, delegated allowances, and minting or burning controls where the design permits them. Allowance mechanisms create a recognized risk: a user may authorize a spender to use tokens, and a compromised or malicious spender can transfer the approved amount. Applications should request appropriate allowances, provide revocation facilities, and consider safer approval patterns. An ERC-721-style non-fungible token identifies individually distinguishable assets. Ownership, transfer, approval, metadata, and safe transfer interfaces are central concepts. The token contract may record ownership while metadata remains off-chain. If metadata is hosted on a mutable server, the apparent permanence of the asset may be weaker than users expect. ERC-1155-style multi-token contracts support multiple fungible or non-fungible token types in one contract and can reduce duplication for collections of assets. Batch operations improve efficiency but increase implementation complexity and the consequences of an authorization error. Token design requires more than selecting a standard. Developers must specify who can mint, whether supply is capped, how roles are administered, whether tokens are pausable or burnable, how transfers are restricted, and what legal or economic claims the token represents. Standards provide interoperability; they do not provide regulatory classification, consumer protection, or business legitimacy. Oracles and the External-World ProblemAn oracle supplies external information to a contract. Examples include market prices, identity attestations, delivery status, election results, and sensor readings. Oracle architectures vary: - A centralized oracle is simple but introduces a single point of failure and trust.
- A decentralized oracle aggregates multiple reporters or data sources.
- A user-submitted oracle uses economic incentives, disputes, or voting.
- A committee or institutional oracle may provide accountability but retains organizational dependence.
Oracle security involves data authenticity, freshness, availability, manipulation resistance, and correct interpretation. A price feed may be accurate in general but unsafe if it is stale during extreme volatility. A contract should check timestamps, acceptable deviation, answer ranges, and failure conditions. Applications should also assess what happens when an oracle is unavailable: pause settlement, use a fallback, or continue with bounded assumptions. A Lifecycle for Secure dApp EngineeringA disciplined lifecycle begins with requirements and threat modelling rather than code. The design team should identify assets, actors, trust assumptions, privileged roles, invariants, failure states, and legal constraints. An invariant is a property that must remain true, such as “the total recorded token supply equals the sum of balances” or “a withdrawal cannot exceed a user’s escrowed amount.” The next stage is architecture. Designers decide what belongs on-chain, what can remain off-chain, how identities are represented, how oracle data enters, and how users recover from errors. The architecture should document external dependencies and distinguish safety properties, such as preventing unauthorized withdrawal, from liveness properties, such as ensuring withdrawals can eventually be processed. Implementation should use established libraries where appropriate, explicit access control, checked arithmetic or compiler-supported overflow protection, pull-based payments, and carefully bounded loops. Code should be small enough to review. Comments should explain why a security-sensitive decision exists rather than merely restating syntax. Testing must operate at several levels. Unit tests examine individual functions and edge cases. Integration tests examine interaction among contracts, wallets, providers, and oracle adapters. Property-based or invariant testing explores many generated inputs. Fuzzing searches for unexpected states. Fork or staging-network tests examine behavior against realistic dependencies. Static analysis identifies suspicious patterns but cannot replace human review. Before deployment, teams should compile with a pinned compiler version, verify dependencies, review generated artifacts, inspect access-control initialization, and conduct independent security assessment. Deployment scripts should be reproducible and should record addresses, network identifiers, compiler settings, and configuration. Verification of source code on a public explorer improves transparency but does not prove correctness. After deployment, monitoring should track privileged actions, abnormal transfers, failed transactions, oracle deviations, administrative changes, and unusual gas usage. Incident response must define who can pause a system, communicate with users, preserve evidence, and execute recovery or migration procedures. In a blockchain setting, response may limit future damage but cannot necessarily reverse confirmed transactions. Foundational Solidity ExampleThe following illustrative contract records deposits and permits each depositor to withdraw its own balance. It is intentionally simple and is not presented as production-ready financial software. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Escrow { mapping(address => uint256) private deposits; event Deposited(address indexed account, uint256 amount); event Withdrawn(address indexed account, uint256 amount); function deposit() external payable { require(msg.value > 0, "zero deposit"); deposits[msg.sender] += msg.value; emit Deposited(msg.sender, msg.value); } function balanceOf(address account) external view returns (uint256) { return deposits[account]; } function withdraw(uint256 amount) external { require(amount > 0, "zero withdrawal"); require(deposits[msg.sender] >= amount, "insufficient balance"); deposits[msg.sender] -= amount; (bool success, ) = payable(msg.sender).call{value: amount}(""); require(success, "transfer failed"); emit Withdrawn(msg.sender, amount); } } ``` The example illustrates state, events, payable functions, access through `msg.sender`, and a checks-effects-interactions sequence: validate conditions, update internal state, and then interact externally. Updating the balance before the external call reduces the classic reentrancy risk. Nevertheless, a professional review would ask whether forced ether can enter the contract, whether emergency recovery is needed, whether denial of service is possible, and whether the intended accounting invariant is preserved. A typical development workflow may use Foundry, Hardhat, or another framework for compilation, local networks, testing, scripting, and deployment. The tool is less important than the discipline: tests should verify successful deposits, partial withdrawals, unauthorized withdrawals, zero values, failed transfers, repeated calls, and conservation of balances. Upgradeability and GovernanceImmutability provides predictability but makes errors costly. Upgradeability permits changes but introduces an administrative trust boundary. Common patterns include proxy contracts, where a stable address delegates execution to an implementation contract, and migration, where users move assets or state to a new deployment. Proxy systems require careful handling of storage layout, initialization, delegate-call context, authorization, and implementation upgrades. A proxy administrator with unilateral authority is a high-value target. Multisignature control, timelocks, public upgrade notices, independent review, and emergency procedures can reduce governance risk, although they cannot guarantee benevolent behavior. Upgrade decisions should be evaluated as governance decisions, not merely technical maintenance. Stakeholders need to know who can upgrade, what changes are permitted, how users can exit, whether an upgrade can alter balances or fees, and how disputes are handled. A formally verified version can still become unsafe if governance later points the system to unreviewed code. Applied Case: Illustrative Renewable-Energy Certificate dAppBackgroundAssume a consortium of small solar producers wants to issue digital certificates representing verified units of renewable electricity. Producers submit generation data, an oracle reports validated output, and buyers acquire certificates through a dApp. The consortium proposes a token contract, a marketplace contract, and a web interface connected to user wallets. Situation and ProblemThe initial design places producer-submitted generation data directly into the token contract and gives one consortium administrator authority to mint certificates. The business team values rapid deployment, while buyers expect certificates to be unique, auditable, and resistant to double issuance. Cybersecurity reviewers identify risks involving false data, administrator compromise, privacy leakage, replayed submissions, and ambiguous retirement of certificates. AnalysisThe core asset is not merely the token; it is the credible relationship between measured generation and the certificate. The blockchain can show that a minting transaction occurred, but it cannot independently prove that the reported generation happened. The oracle and verification process are therefore part of the security model. The administrator is a privileged actor, not an incidental account. Directly storing detailed production data creates unnecessary exposure and long-term data-governance obligations. The team defines the following invariants: a certificate can be minted only once for a unique verified production record; retired certificates cannot be transferred or retired again; the total issued amount cannot exceed verified output; and minting authority cannot be exercised by one key alone. It also separates public certificate identifiers from sensitive producer information. Approach and SolutionThe consortium uses a token contract with explicit roles for verification, minting, and emergency pause. Minting requires an attestation containing a unique production-period identifier, a bounded quantity, a timestamp, and a signature from an authorized verification service. A nonce or unique identifier prevents replay. Sensitive records remain off-chain, while a cryptographic commitment and relevant public metadata are recorded on-chain. Minting authority is placed behind a multisignature wallet. An oracle adapter rejects stale or malformed submissions. The marketplace uses pull-based settlement and avoids arbitrary external calls during accounting updates. A retirement function marks certificates as consumed rather than merely transferring them to an inaccessible address. The interface shows the source, verification status, retirement status, contract address, and applicable governance rules. The team tests duplicate attestations, altered signatures, stale data, unauthorized minting, unexpected token callbacks, paused operation, and recovery from oracle failure. A staged deployment is followed by independent review and monitoring of privileged actions. OutcomeThe revised design does not make the energy claim automatically true, but it makes the trust assumptions visible and reduces opportunities for duplication, unilateral abuse, and replay. Buyers can distinguish blockchain evidence from off-chain verification evidence. The consortium accepts higher operational complexity in exchange for stronger accountability. Learning PointsThe case demonstrates that tokenization is an assurance problem as much as a programming problem. Oracle governance, privileged keys, data minimization, lifecycle states, and user-facing transparency must be designed together. A technically valid token can still fail if its real-world reference, administrative controls, or retirement semantics are weak. Security Risks, Limitations, and Common MistakesSmart-contract vulnerabilities include reentrancy, incorrect access control, arithmetic errors, insecure randomness, denial of service, price manipulation, signature replay, unsafe external calls, storage collisions in proxies, and flawed business logic. Some vulnerabilities are syntactic and detectable by tools; many are semantic and arise because the code implements an unsafe interpretation of the requirements. Common mistakes include assuming that an audit guarantees security, using an oracle without freshness checks, granting unlimited token approvals, storing personal data publicly, relying on block variables for unpredictable randomness, failing to test failed external calls, and leaving deployment keys in scripts or repositories. Developers also underestimate economic attacks. An attacker may exploit incentives, liquidity conditions, oracle timing, governance voting, or transaction ordering without violating any programming-language rule. Public visibility creates both accountability and attack surface. Source code, addresses, events, and transaction histories can support monitoring, but they can also reveal operational patterns and enable targeted exploitation. Privacy-enhancing approaches must be assessed against the transparency required by the application. Ethical, Regulatory, and Professional ConsiderationsA dApp may affect property, finance, identity, employment, or access to essential services. Code-based execution does not remove duties of fairness, informed consent, consumer protection, accessibility, or accountability. Users may not understand irreversible approvals, gas costs, or the consequences of losing a key. Interfaces should communicate risks in plain language and avoid presenting speculative tokens as guaranteed investments. Regulatory obligations vary by jurisdiction and by the economic and legal characteristics of the application. Token issuers, custodians, exchanges, payment services, and identity systems may face different requirements. Privacy law can conflict with the permanence of public ledgers, especially where personal data is involved. Professional teams should obtain appropriate legal advice, document decisions, preserve audit evidence, and avoid claiming decentralization where meaningful control remains centralized. Current Developments and Emerging DirectionsLayer-two networks and rollups seek to reduce transaction costs and increase throughput while retaining a connection to a base blockchain. Account abstraction aims to make smart-contract wallets more usable by supporting programmable authorization, recovery, and transaction sponsorship. Zero-knowledge techniques can support selective disclosure and scalable verification, although they introduce specialized cryptographic and operational requirements. Formal verification is increasingly used to prove selected properties of contracts, while automated analysis and AI-assisted tools can help identify patterns, generate tests, and review code. These tools remain assistants: they may miss business-logic flaws, produce false positives, or reproduce insecure assumptions. Cross-chain bridges and interoperability protocols continue to require special caution because they connect separate trust domains and often concentrate large asset values. Best Practices for Professional PracticeA mature dApp team should: - specify assets, roles, invariants, trust assumptions, and failure responses before coding;
- minimize on-chain data and contract complexity;
- use established standards and carefully reviewed libraries;
- apply least privilege, multisignature administration, and timelocked governance where appropriate;
- test adversarially with unit, integration, invariant, fuzz, and staging tests;
- verify deployment artifacts and maintain reproducible release records;
- monitor events, privileged actions, oracle quality, and abnormal behavior;
- design clear pause, migration, communication, and incident-response procedures;
- disclose limitations and distinguish blockchain records from real-world truth.
Chapter SummarySmart contracts are deterministic programs that manage persistent blockchain state, while dApps combine contracts with wallets, interfaces, providers, off-chain services, oracles, and governance. Their lifecycle includes specification, threat modelling, architecture, implementation, testing, deployment, monitoring, and response. Token standards improve interoperability but do not guarantee security or legal validity. Oracles introduce external-world trust assumptions, and wallets make key management a central security concern. Immutability improves predictability; upgradeability improves adaptability but creates administrative risk. Secure professional practice depends on explicit invariants, least privilege, adversarial testing, transparent governance, data minimization, and realistic treatment of economic, ethical, and regulatory issues. Key TermsSmart contract: A blockchain-resident program that executes defined logic and manages persistent state. Decentralized application (dApp): An application that uses blockchain contracts as a significant part of its logic or settlement. EVM: A deterministic virtual machine that executes compatible blockchain contract bytecode. Gas: A measure of computational work used to price and limit transaction execution. Transaction: A signed request that may change blockchain state or deploy code. Call: A read-only execution request that does not normally alter blockchain state. Event: An emitted, indexed log used to communicate significant contract activity. Wallet: Software or hardware that manages keys and authorizes transactions. Multisignature wallet: A wallet requiring approval from multiple authorized keys. Oracle: A mechanism that supplies external information to a smart contract. Fungible token: Interchangeable digital units represented through a common token interface. Non-fungible token: A uniquely identifiable token representing a distinct asset or record. Allowance: Permission for a designated spender to transfer tokens on an owner’s behalf. Invariant: A property that should remain true throughout contract execution. Reentrancy: An exploit in which an external call re-enters a contract before an operation is safely completed. Proxy: A contract pattern that delegates execution to another implementation contract. Upgradeability: The ability to change contract logic after deployment through an authorized mechanism. Replay attack: Reuse of a valid message or authorization in an unintended context or more than once. Gas griefing: Deliberate exploitation of computation or transaction costs to disrupt an operation. Account abstraction: An approach that enables programmable transaction authorization and smart-contract wallet features. Review QuestionsShort Answer Questions1. Distinguish a state-changing transaction from a read-only call. 2. Why are events not a replacement for contract storage? 3. What security problem does an oracle introduce? 4. Explain the purpose of a multisignature wallet. 5. Define a contract invariant and give one example. Long Answer Questions1. Explain the architecture of a dApp and discuss the trust assumptions at each layer. 2. Describe a secure smart-contract lifecycle from requirements through post-deployment monitoring. 3. Compare fungible, non-fungible, and multi-token standards and identify design risks for each. 4. Analyse the advantages and risks of immutable and upgradeable contract architectures. 5. Discuss how wallet security, access control, and governance jointly affect dApp security. Analytical / Application Questions1. A lending dApp uses a single price feed that has not updated for six hours. Identify the risks and propose controls. 2. A token contract gives one externally owned account unlimited minting authority. Evaluate the design and recommend a governance model. 3. Design a testing and monitoring plan for the renewable-energy certificate dApp described in this chapter, including at least three invariants and three operational alerts. 22. Multiple Choice Questions with AnswersQuestion 1Which operation normally requires a signed blockchain transaction and gas? A. Reading a stored balance through a view call B. Transferring tokens and changing contract state C. Displaying an event already indexed by a provider D. Calculating a value locally in a browser Correct Answer: B. Transferring tokens and changing contract state Question 2Why is an oracle a security boundary in a smart-contract system? A. It determines the blockchain consensus algorithm B. It supplies external facts that the blockchain cannot independently verify C. It permanently encrypts all contract storage D. It prevents users from signing transactions Correct Answer: B. It supplies external facts that the blockchain cannot independently verify Question 3Which design most directly reduces reentrancy risk in a withdrawal function? A. Making the balance update after the external call B. Updating internal accounting before making the external call C. Removing all events from the contract D. Allowing unlimited recursive calls Correct Answer: B. Updating internal accounting before making the external call Question 4What is the principal risk of granting a token spender an unnecessarily large allowance? A. The token becomes non-fungible B. The spender may transfer the approved tokens if compromised or malicious C. The blockchain stops recording events D. The owner’s private key is automatically revealed Correct Answer: B. The spender may transfer the approved tokens if compromised or malicious Question 5Which property is an invariant for an escrow contract? A. Every transaction has the same gas price B. A user cannot withdraw more than the amount recorded for that user C. All users must use hardware wallets D. Every event must contain personal data Correct Answer: B. A user cannot withdraw more than the amount recorded for that user Question 6What additional trust boundary is introduced by a proxy-based upgrade pattern? A. The ability of an authorized party to change the implementation logic B. The elimination of all administrative roles C. The guarantee that storage layouts never change D. The removal of deployment records Correct Answer: A. The ability of an authorized party to change the implementation logic Question 7In the renewable-energy case, what best prevents replay of the same verified production record? A. Using a unique production-period identifier or nonce B. Increasing the web page refresh rate C. Storing all producer data publicly without identifiers D. Allowing the administrator to mint repeatedly Correct Answer: A. Using a unique production-period identifier or nonce Question 8Which statement best describes a wallet? A. A physical vault where blockchain balances are stored B. A system for managing keys and authorizing transactions C. A replacement for the blockchain validator set D. An oracle that verifies real-world events Correct Answer: B. A system for managing keys and authorizing transactions Question 9Why should sensitive personal data generally not be written directly to a public blockchain? A. Public blockchains cannot record any data B. Permanent visibility can conflict with privacy and data-governance requirements C. Events cannot be indexed D. Wallets cannot sign transactions containing data Correct Answer: B. Permanent visibility can conflict with privacy and data-governance requirements Question 10Which testing approach is especially suited to exploring many generated inputs and checking persistent properties? A. Property-based or invariant testing B. Changing the contract title C. Viewing only the deployment transaction D. Disabling failure-path tests Correct Answer: A. Property-based or invariant testing
|