Chapter 5 — Web3, blockchain and cryptoasset security: tools and interpretation
Lesson map
Lesson 05 published. Map, example, EX021.
flowchart TD
N0["Learning outcomes"]
N1["5.1 Reconciling donations"]
N2["Lab — Donation reconciliation"]
N3["5.2 Interpreting discrepancies"]
N4["5.3 Proportionate response"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Worked example"]
EX --> Q["Exercise EX021"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["5.1 Reconciling donations"]
N2["Lab — Donation reconciliation"]
N3["5.2 Interpreting discrepancies"]
N4["5.3 Proportionate response"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX021"]
[Learning outcomes]
|
v
[5.1 Reconciling donations]
|
v
[Lab — Donation reconciliation]
|
v
[5.2 Interpreting discrepancies]
|
v
[5.3 Proportionate response]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX021]
Learning outcomes
You will (1) use read-only tools to reconcile donations; (2) interpret discrepancies; (3) avoid over- and under-reacting.
5.1 Reconciling donations
Each donation receipt should match an incoming transfer to the treasury address. Marcus writes a read-only script that compares the finance team's receipts, each with an amount and a ledger reference, against incoming transfers exported from a block explorer. It reports receipts with no reference, references not found, amount differences and incoming transfers with no receipt. This lab uses five synthetic receipts and five synthetic transfers. It uses only Python's standard library and touches no live systems, accounts or wallets.
Lab — Donation reconciliation
"""Reconcile synthetic donation receipts with incoming ledger transfers (read-only)."""
# receipt id, amount in units, ledger tx reference recorded by the finance team
RECEIPTS = [("R-201", 500, "tx-a1"), ("R-202", 120, "tx-a2"), ("R-203", 75, "tx-a3"),
("R-204", 300, "tx-a4"), ("R-205", 60, None)]
# incoming transfers seen on the ledger: tx reference, amount
LEDGER = {"tx-a1": 500, "tx-a2": 120, "tx-a3": 57, "tx-a4": 300, "tx-a6": 40}
def main():
used = set()
for rid, amt, tx in RECEIPTS:
if tx is None:
print(f"{rid}: no ledger reference")
elif tx not in LEDGER:
print(f"{rid}: {tx} not found on ledger")
elif LEDGER[tx] != amt:
print(f"{rid}: amount {amt} vs ledger {LEDGER[tx]}")
used.add(tx)
for tx in sorted(set(LEDGER) - used):
print(f"{tx}: incoming {LEDGER[tx]} with no receipt")
print(f"receipts {len(RECEIPTS)}; ledger transfers {len(LEDGER)}")
if __name__ == "__main__":
main()
Run with python3 lab_donations.py. Verified output:
R-203: amount 75 vs ledger 57
R-205: no ledger reference
tx-a6: incoming 40 with no receipt
receipts 5; ledger transfers 5
5.2 Interpreting discrepancies
The lab reports three issues: receipt R-203 records 75 units while the ledger shows 57; receipt R-205 has no ledger reference; and transfer tx-a6 of 40 units has no receipt. Marcus investigates each. R-203 is a typing error that swapped digits when the receipt was issued; a corrected receipt is sent. R-205 was a cash donation wrongly entered in the cryptoasset register. Tx-a6 is a genuine donation from a donor who did not request a receipt; it is recorded. Each discrepancy has an ordinary explanation, but each needed checking.
5.3 Proportionate response
Marcus notes that discrepancies are signals, not proof of wrongdoing. Over-reacting, such as freezing the treasury for a typing error, would harm the charity; under-reacting, such as ignoring an unreceipted transfer, could miss a misdirected payment or a reporting duty. He documents each explanation and evidence, and proposes that receipts be generated from the ledger reference rather than typed. Ms Holm notes that proportionate interpretation is the core professional skill: tools find differences, and practitioners decide what they mean using evidence and judgement.
Worked example
The lab reports R-203 at 75 versus 57, R-205 without a reference and tx-a6 of 40 without a receipt, each explained and corrected.
Synthetic case. The receipts, transfers and explanations are synthetic.
Errors and limits
Treating every discrepancy as wrongdoing, or ignoring it, are both disproportionate responses.
Exercises
- EX021 — Lab issue count. How many issues does the lab report? Rubric: 3 = three;; 2 = 3;; 1 = five;; 0 = none.
- EX022 — R-203 discrepancy. What is wrong with R-203? Rubric: 3 = 75 recorded versus 57 on the ledger;; 2 = swapped digits;; 1 = missing;; 0 = none.
- EX023 — R-205 explanation. What explains R-205? Rubric: 3 = a cash donation entered in the wrong register;; 2 = cash entry;; 1 = theft;; 0 = none.
- EX024 — Unreceipted transfer. What is tx-a6? Rubric: 3 = a genuine 40-unit donation without a receipt request;; 2 = genuine donation;; 1 = an error;; 0 = none.
- EX025 — Process improvement. What process change does Marcus propose? Rubric: 3 = generate receipts from the ledger reference;; 2 = automatic receipts;; 1 = stop receipts;; 0 = none.
Synthesis
Read-only reconciliation finds differences, and proportionate interpretation explains them.
Continue studying — chapter 05 of 12
← Chapter 04 (draft) · Course chapter index · Chapter 06 (draft) →