Blockchain Technologies & Systems

Chapter 6
Smart Contracts and Decentralized Applications

Post Graduate Program in Cyber Security
Blockchain Technologies & Systems   •   Post Graduate

6. Smart Contracts and Decentralized Applications

Introduction and Context

Blockchain 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 Objectives

After 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 Model

A 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 dApp

A 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 Authorization

A 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 Consequences

Token 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 Problem

An 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 Engineering

A 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 Example

The 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 Governance

Immutability 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 dApp

Background

Assume 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 Problem

The 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.

Analysis

The 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 Solution

The 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.

Outcome

The 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 Points

The 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 Mistakes

Smart-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 Considerations

A 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 Directions

Layer-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 Practice

A 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 Summary

Smart 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 Terms

Smart 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 Questions

Short Answer Questions

1. 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 Questions

1. 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 Questions

1. 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 Answers

Question 1

Which 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 2

Why 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 3

Which 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 4

What 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 5

Which 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 6

What 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 7

In 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 8

Which 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 9

Why 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 10

Which 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

Blockchain Technologies & Systems
Chapter 6 of 14