Chapter 7
Smart Contracts and Decentralized Applications
Diploma in Blockchain
Blockchain Architecture
•
Diploma
Smart Contracts and Decentralized Applications
Introduction and Context
A blockchain becomes useful to organisations and users when it can do more than record transfers of digital currency. Smart contracts provide programmable rules that execute on a blockchain’s execution environment. Decentralized applications (dApps) combine these contracts with user interfaces, wallets, off-chain services, indexing systems, and sometimes external data providers called oracles.
A smart contract is a program deployed at a blockchain address. It can hold assets, validate transactions, update persistent state, emit events, and call other contracts. Unlike a conventional server application, its critical state transitions are replicated and verified by many nodes. This provides transparency and tamper resistance, but execution is constrained by deterministic computation, transaction fees, limited storage, and irreversible deployment decisions.
The central architectural challenge is therefore not simply writing code. It is designing a system whose rules are deterministic, economically viable, secure, observable, upgradeable when justified, and understandable to users and regulators.
Learning Objectives
By the end of this chapter, a learner should be able to:
Explain the role and lifecycle of smart contracts.
Describe blockchain execution environments and virtual machines.
Analyse gas, transaction costs, storage, and computational limits.
Distinguish contract state, function calls, events, and logs.
Select appropriate token standards and explain their interfaces.
Compare immutable, proxy-based, and modular upgradeability designs.
Design a basic dApp architecture involving contracts, wallets, front ends, indexers, and oracles.
Apply testing, auditing, and deployment practices to smart-contract projects.
Identify oracle, governance, legal, privacy, and operational risks.
1. Smart Contracts as Blockchain Programs
A smart contract normally contains four related elements:
Code: instructions defining valid operations.
Storage: persistent key–value data maintained by the contract.
Address: an identifier through which users and other contracts interact with it.
Balance and permissions: assets held by the contract and rules determining who may perform actions.
A contract function may be called in two broad ways. A read-only call is executed locally by a node and does not normally create a transaction or consume user-paid gas. A state-changing call is submitted as a transaction, included in a block, executed by validators, and recorded if successful. A failed transaction generally reverts its state changes, although the computation already performed may still consume fees.
Smart contracts are deterministic: given the same prior blockchain state, transaction input, and execution rules, all honest nodes must reach the same result. This rules out uncontrolled access to local files, arbitrary network requests, current wall-clock time, or random values unless these are represented through approved blockchain mechanisms.
A contract is not inherently intelligent, legally autonomous, or free from human control. Its behaviour is limited by its code, dependencies, administrative keys, governance, and the consensus rules of its blockchain.
2. Execution Environments and Virtual Machines
The execution environment is the subsystem that interprets or runs transaction code. In Ethereum-compatible systems, the Ethereum Virtual Machine (EVM) uses bytecode and a stack-based instruction set. Contracts are commonly written in Solidity or Vyper and compiled into bytecode. The EVM provides memory, persistent storage, a stack, account access, cryptographic operations, and execution context such as caller and transaction data.
Other platforms use different environments. Solana programs execute within a runtime based on accounts and commonly use Rust or C/C++; WebAssembly-based chains may execute WebAssembly modules; permissioned platforms may use containerized chaincode. These environments differ in programming languages, data models, parallelism, fee mechanisms, and trust assumptions.
A useful abstraction is:
St+1 = F(St, Tt, Et)
where St is the prior global state, Tt is a valid transaction, Et is the execution environment and protocol context, and F is the deterministic state-transition function. The equation applies only when all nodes use compatible protocol rules and deterministic inputs. If execution fails, the intended state transition is rejected or reverted according to the platform’s rules.
Contract lifecycle
Specification: business rules, roles, assets, assumptions, and failure conditions are defined.
Implementation: source code is written using a suitable language and libraries.
Compilation: source code becomes executable bytecode and an application binary interface (ABI).
Testing: unit, integration, property-based, and adversarial tests are performed.
Deployment: initialization data and bytecode are submitted in a transaction.
Verification: source code and compiler settings may be published for reproducibility.
Operation: users and other contracts invoke functions.
Maintenance: monitoring, incident response, governance, and—if designed—upgrades are performed.
The ABI specifies callable functions, parameter types, return values, events, and errors. A front end uses the ABI to encode transactions and decode responses, but the blockchain validates the transaction independently of the interface.
3. Gas, Resources, and Economic Execution
Blockchain computation must be priced because validators have finite CPU, memory, storage, and bandwidth. Gas is a unit of computational resource consumption. A transaction specifies a gas limit, while the protocol determines a gas price or fee mechanism.
For a simple fee model:
Transaction fee = Gas used × Gas price
Gas used is measured in gas units, and gas price is commonly denominated in the blockchain’s smallest currency unit per gas unit. Thus the result is denominated in that currency’s smallest unit. Under a base-fee and priority-fee model, a useful representation is:
Effective gas price = Base fee + Priority fee
The exact fee paid may also depend on protocol rules, fee caps, refunds, or transaction type. These formulas are conceptual and should be checked against the target network’s current specification.
Worked example. Suppose a transaction uses 80,000 gas, the base fee is 25 gwei, and the priority fee is 2 gwei. The effective price is 27 gwei per gas. The fee is:
80,000 × 27 = 2,160,000 gwei.
Since 1 ether equals 1,000,000,000 gwei, the fee is 0.00216 ether. This calculation assumes no additional protocol-specific adjustment.
Gas performs several architectural functions:
It limits computation and helps prevent denial-of-service attacks.
It makes persistent storage expensive relative to transient computation.
It encourages efficient data structures and batching.
It causes users to consider congestion and fee volatility.
It creates a maximum execution boundary through the gas limit.
Developers should avoid unbounded loops over user-controlled arrays, excessive storage writes, and designs that require every user to process an ever-growing history. Pagination, mappings, events, off-chain indexing, and bounded operations are common alternatives.
4. State, Transactions, Calls, Events, and Errors
A contract’s storage is persistent blockchain state. Changing storage creates a new state commitment and normally consumes significant resources. Memory is temporary during one execution. Calldata is transaction input that is generally read-only. These distinctions influence both cost and security.
A transaction is a signed request submitted to the network. A message call is an execution caused by a transaction or another contract. A contract-to-contract call may succeed, return data, or fail. Failure handling is essential because a called contract may be malicious, unavailable, incorrectly configured, or incompatible with the expected interface.
Events and logs
Events are structured records emitted during execution. They are useful for wallets, indexers, analytics systems, and user interfaces. For example, a token transfer event can allow an indexer to reconstruct activity without repeatedly scanning every storage slot.
Events are not the same as authoritative storage. Contracts generally cannot read historical event logs as ordinary state. An event may also be absent if the transaction reverts. Critical information required for future contract decisions must therefore be stored or derivable from state, not only emitted as an event.
A well-designed event should identify the action, relevant actors, asset or record identifiers, and important quantities. Events should not falsely imply that an off-chain action has completed when the contract has merely requested it.
Errors and reversion
Explicit errors communicate why an operation failed and can reduce unnecessary data compared with long textual messages. Checks should normally occur before state changes. The checks-effects-interactions pattern—validate conditions, update internal state, then call external contracts—reduces several re-entrancy risks, although it is not a complete security solution.
5. Token Standards and Digital Assets
Token standards are shared interfaces that allow wallets, exchanges, marketplaces, and applications to interoperate.
Standard or model
Typical purpose
Important design concern
Fungible-token interface
Interchangeable units such as points or stable-value tokens
Allowances, decimals, transfer restrictions
Non-fungible-token interface
Distinct items such as certificates or collectibles
Ownership, metadata, transfer rules
Multi-token interface
Fungible and non-fungible assets in one contract
Batch operations and identifier management
Permissioned or regulated token
Assets subject to identity or compliance controls
Administrator powers and legal obligations
A fungible token commonly exposes balance queries, transfers, approvals, and allowance-based transfers. The allowance model introduces a delegated-spending relationship: an owner permits a spender to move up to a specified amount. Applications must explain approval transactions clearly because users can accidentally grant broad permissions.
Non-fungible tokens associate an identifier with an owner and often a metadata reference. Metadata may be stored on-chain, on content-addressed storage, or on conventional servers. If a valuable property is hosted on a mutable central server, ownership of the token does not guarantee permanence of the associated content.
Token architecture must address decimals, supply creation and destruction, pausing, blacklisting, recovery, royalty claims, lost keys, and compliance. These are governance choices, not merely programming details.
6. Decentralized Application Architecture
A dApp is usually a hybrid system rather than a completely on-chain system. Its layers may include:
User interface: web, mobile, or desktop application.
Wallet and signing layer: manages user consent and transaction signatures.
RPC or node access: submits transactions and reads blockchain data.
Smart-contract layer: enforces shared rules and asset custody.
Indexing layer: organizes events and historical queries.
Oracle or bridge layer: supplies external data or cross-chain messages.
Off-chain services: notifications, search, privacy-preserving computation, or file storage.
Figure: A dApp combines on-chain contracts with user, indexing, and external-data layers.
The front end must display the connected network, contract address, transaction simulation or expected effects, fees, and confirmation status. It should not assume that a transaction has succeeded merely because it was submitted. It should wait for an appropriate receipt and account for chain reorganisations or replaced transactions.
A dApp should also be usable without trusting its front end. Contract addresses, source code, deployment parameters, and privileged roles should be published where practical. Critical operations should remain enforceable by the contract rather than by hidden interface logic.
7. Oracle Dependencies
Blockchains cannot directly observe arbitrary real-world facts. An oracle is a mechanism that reports external information, such as an exchange rate, weather measurement, delivery status, or identity attestation, to a contract.
Oracle risk has several dimensions:
Correctness: Is the reported value accurate?
Availability: Will data arrive when needed?
Manipulation resistance: Can an attacker influence the source or timing?
Freshness: Is the value recent enough?
Economic security: Is the cost of corrupting the oracle greater than the possible gain?
Governance: Who selects data sources and changes parameters?
A contract should specify acceptable staleness, range checks, decimal conversion, fallback behaviour, and circuit breakers. A price-dependent lending application, for example, should not continue liquidations using an outdated or obviously abnormal price.
An oracle does not eliminate trust; it relocates and distributes it. Multiple independent sources, aggregation, signed reports, dispute mechanisms, and monitoring may reduce risk but cannot guarantee truth.
8. Upgradeability and Governance
Immutable contracts provide strong predictability: deployed code cannot normally be changed. However, immutable code may contain defects, become obsolete, or require adaptation to regulation. Upgradeability introduces flexibility but also creates administrator, key-management, storage-layout, and governance risks.
Common models include:
Redeployment and migration: deploy a new contract and migrate users or assets. This is transparent but operationally difficult.
Proxy pattern: users call a stable proxy, which delegates execution to an implementation contract. The implementation can be replaced by an authorised administrator or governance process.
Modular architecture: separate components are connected through interfaces, allowing selected modules to change.
Governance-controlled upgrade: token holders, a multisignature group, or a time-delayed controller approves changes.
A proxy design must preserve storage layout, initialise implementations safely, restrict upgrade authority, and expose upgrade events. A transparent timelock allows users and security researchers time to inspect a proposed change. Emergency powers may be necessary for pausing, but they should be narrowly scoped, documented, monitored, and subject to accountability.
The correct question is not “Should the contract be upgradeable?” but “Which risks justify change authority, who controls it, how is it constrained, and how can users exit if they disagree?”
9. Testing, Verification, and Security
Testing should proceed from requirements to adversarial behaviour.
Testing levels
Unit testing: checks individual functions and edge cases.
Integration testing: checks interactions among contracts, tokens, oracles, and wallets.
Property-based testing: generates many inputs to test invariants such as conservation of balances.
Fuzz testing: explores unexpected sequences and values.
Fork or staging testing: executes against a realistic copy of a network state.
Static analysis: detects suspicious patterns without executing every path.
Formal verification: mathematically proves selected properties under explicit assumptions.
Independent audit: provides expert review, but does not guarantee security.
Important invariants may include: total balances equal total supply, only authorised roles can mint, collateralisation remains above a threshold, and a withdrawal cannot exceed a user’s claim.
Frequent vulnerabilities include re-entrancy, access-control failure, arithmetic or precision errors, oracle manipulation, denial of service through unbounded iteration, unsafe token assumptions, signature replay, front-running, improper randomness, and proxy initialisation errors.
Security is also operational. Private keys should use multisignature control or secure modules; deployment scripts should be reproducible; compiler versions should be pinned; dependencies should be reviewed; and alerts should monitor privileged actions, abnormal transfers, oracle deviations, and contract pauses.
Consider an illustrative dApp that allows users to deposit a collateral token and borrow a stable-value token. The system uses a price oracle and a liquidation mechanism.
Problem
The designers must ensure that a borrower cannot withdraw excessive collateral, that the system remains solvent when prices change, and that stale oracle data does not create unfair liquidations.
Analysis
The protocol records collateral balances, debt balances, interest parameters, and last-used oracle data. A risk engine calculates a collateral value from the oracle price. In simplified form:
Collateral ratio = Collateral value ÷ Debt value
Both values must use compatible units and decimal conventions. If collateral is worth 150 units and debt is 100 units, the ratio is 1.5, or 150%. If the liquidation threshold is 120%, the position is initially above the threshold. This simplified calculation ignores interest, fees, liquidation penalties, and price impact.
Approach and solution
The architecture uses separate contracts for collateral custody, debt accounting, liquidation, and oracle integration. Deposits and withdrawals emit events. The oracle adapter rejects stale reports and checks that prices lie within configured bounds. Liquidations are permitted only when the ratio is below the threshold. Administrative upgrades are controlled by a multisignature wallet and delayed governance process.
Testing includes price shocks, zero values, repeated deposits, malicious token callbacks, stale reports, failed transfers, and liquidation races. A pause function stops new borrowing during an oracle incident while preserving a documented withdrawal policy.
Outcome
The design reduces the impact of a single defective component, but it does not remove economic risk. Extreme market movement, oracle failure, blockchain congestion, or governance compromise can still cause losses. Users must understand that a displayed borrowing limit is conditional on prices, fees, and protocol rules.
Learning points
Financial dApps are systems of interacting contracts, not isolated functions.
Units, decimals, freshness, and failure behaviour must be explicit.
Oracle and upgrade authorities are part of the trust model.
Solvency properties require both code tests and economic analysis.
11. Governance, Ethics, and Regulation
Smart-contract developers exercise governance power when they define minting, freezing, upgrade, liquidation, or emergency functions. Users may not understand these powers from a token name or front-end design. Interfaces should disclose administrator privileges, risks, fees, and irreversible actions in clear language.
Privacy is another concern. Public transactions can reveal financial relationships, trading patterns, and organisational activity. Personal data should generally not be placed directly on an immutable public ledger. Systems may use commitments, selective disclosure, zero-knowledge methods, or off-chain storage, while recognising that metadata and transaction graphs may remain revealing.
Legal classification varies by jurisdiction. A token may involve securities, payment services, commodities, consumer protection, sanctions, taxation, custody, or data-protection obligations. Technical decentralisation does not automatically remove legal responsibility. Professional deployments require legal review, risk assessment, incident procedures, and records of governance decisions.
12. Contemporary Developments and Best Practices
Current dApp architecture increasingly uses layer-two networks, account abstraction, modular rollups, cross-chain messaging, zero-knowledge proofs, and automated security tooling. These developments can reduce fees or improve usability, but they introduce new assumptions about sequencers, bridges, proving systems, relayers, and withdrawal periods.
Recommended practice is to:
begin with a threat model and explicit trust assumptions;
keep contract responsibilities small and interfaces stable;
minimise privileged authority and use multisignature controls;
use established libraries while reviewing their versions and configuration;
separate critical state from analytics data;
bound loops and design for congestion;
validate token, oracle, and cross-chain assumptions;
test failures, not only successful paths;
publish source code, deployment details, and upgrade procedures;
monitor events and privileged actions continuously;
communicate uncertainty and user risks honestly.
Chapter Summary
Smart contracts are deterministic blockchain programs that manage state, assets, permissions, and interactions. Their execution occurs within a virtual machine or other blockchain runtime, where gas prices computation and storage. A dApp combines contracts with wallets, interfaces, node access, indexers, oracles, and off-chain services.
Events improve observability but do not replace authoritative state. Token standards promote interoperability while introducing allowance, metadata, supply, and compliance decisions. Upgradeability offers adaptability at the cost of additional trust and governance risk. Testing must include unit, integration, fuzz, invariant, security, and operational evaluation. Oracles are essential whenever contracts depend on external facts, but they create correctness, availability, freshness, and manipulation risks.
Professional dApp design therefore requires technical architecture, economic reasoning, security engineering, transparent governance, privacy awareness, and regulatory consideration.
Key Terms
Smart contract: Deterministic program deployed at a blockchain address.
Decentralized application: Application combining blockchain contracts with user and supporting services.
Virtual machine: Runtime that executes contract bytecode according to protocol rules.
ABI: Interface description used to encode calls and decode contract responses.
State: Persistent data representing the blockchain’s current condition.
Transaction: Signed request that may change blockchain state.
Gas: Unit used to measure and price computational execution.
Event: Structured execution log intended for external observers and indexers.
Oracle: Mechanism that supplies external information to a blockchain contract.
Token standard: Shared interface enabling compatible token behaviour and integration.
Fungible token: Interchangeable digital unit represented by balances.
Non-fungible token: Distinct token identified separately from other tokens.
Allowance: Permission for a delegated account to spend or transfer tokens.
Proxy: Contract that forwards calls to an implementation contract.
Upgradeability: Ability to change selected contract logic after deployment.
Invariant: Property that should remain true across valid executions.
Re-entrancy: Vulnerability in which external control returns to a function before its operation is safely completed.
Multisignature wallet: Account requiring approval from multiple authorised keys.
Indexer: Service that organises blockchain data for efficient application queries.
Circuit breaker: Protective mechanism that pauses or restricts operations during abnormal conditions.
Review Questions
Short Answer Questions
What distinguishes a read-only contract call from a state-changing transaction?
Why is gas required in a blockchain execution environment?
What is the difference between persistent storage, memory, and calldata?
Why can events not replace all contract state?
Identify two risks introduced by upgradeable contracts.
Long Answer Questions
Explain the lifecycle of a smart contract from specification through operation and maintenance.
Describe the layers of a decentralized application and the responsibilities of each layer.
Compare immutable, proxy-based, and modular upgradeability designs.
Explain how oracle correctness, freshness, availability, and governance affect a dApp.
Discuss a comprehensive testing and security strategy for a token-based application.
Analytical / Application Questions
Design a basic architecture for a decentralised marketplace. Identify its contracts, events, wallet interactions, indexing requirements, and off-chain dependencies.
A lending position has collateral worth 240 units and debt worth 180 units. Calculate its collateral ratio and determine whether it is above a 125% liquidation threshold. State the assumptions in your calculation.
A protocol administrator can instantly replace its implementation contract and pause all withdrawals. Analyse the security, governance, user-protection, and operational implications, and propose controls.
Multiple Choice Questions with Answers
Question 1
What is the primary purpose of gas in a blockchain execution environment?
A. To encrypt all contract source code
B. To price computational and storage resources
C. To guarantee that oracle data is accurate
D. To replace digital signatures
Correct Answer: B. To price computational and storage resources
Question 2
Which data type is intended primarily for external observers and indexers rather than as contract-readable persistent state?
A. Event log
B. Storage variable
C. Calldata parameter
D. Account balance
Correct Answer: A. Event log
Question 3
A transaction uses 50,000 gas at 20 gwei per gas. What is the fee, assuming no protocol-specific adjustment?
A. 0.0001 ether
B. 0.001 ether
C. 0.01 ether
D. 1 ether
Correct Answer: B. 0.001 ether
Question 4
Which property is essential for smart-contract execution across honest nodes?
A. Dependence on each node’s local clock
B. Deterministic results from the same state and inputs
C. Access to arbitrary web APIs
D. Random execution order chosen by the user
Correct Answer: B. Deterministic results from the same state and inputs
Question 5
What is a major risk of a token allowance mechanism?
A. The token cannot emit events
B. A spender may use an unnecessarily broad permission
C. The owner cannot query a balance
D. The token becomes automatically non-fungible
Correct Answer: B. A spender may use an unnecessarily broad permission
Question 6
Which practice most directly reduces the risk of unbounded-loop denial of service?
A. Iterating over an ever-growing array in one transaction
B. Using bounded operations and pagination
C. Removing all access control
D. Storing every historical event in contract storage
Correct Answer: B. Using bounded operations and pagination
Question 7
What does an oracle provide to a smart contract?
A. External information such as an exchange rate
B. A replacement for consensus
C. Automatic source-code verification
D. A private key for every user
Correct Answer: A. External information such as an exchange rate
Question 8
In a proxy upgrade design, what is especially important to preserve?
A. The user’s browser cache
B. Storage-layout compatibility
C. The colour scheme of the interface
D. The validator’s operating system
Correct Answer: B. Storage-layout compatibility
Question 9
A position has collateral value of 150 units and debt value of 100 units. What is its simplified collateral ratio?
A. 50%
B. 100%
C. 150%
D. 250%
Correct Answer: C. 150%
Question 10
Which testing method generates many inputs to search for unexpected contract behaviour?