Chapter 27 — Web3, blockchain and cryptoasset security: control design
Lesson map
Lesson 27 published. Map, example, EX079.
flowchart TD
N0["Learning outcomes"]
N1["27.1 Role policy"]
N2["27.2 Checking configuration"]
N3["Lab — Role policy check"]
N4["27.3 Closing gaps"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Worked example"]
EX --> Q["Exercise EX079"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["27.1 Role policy"]
N2["27.2 Checking configuration"]
N3["Lab — Role policy check"]
N4["27.3 Closing gaps"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX079"]
[Learning outcomes]
|
v
[27.1 Role policy]
|
v
[27.2 Checking configuration]
|
v
[Lab — Role policy check]
|
v
[27.3 Closing gaps]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX079]
Learning outcomes
You will (1) design privileged-role controls; (2) check role configuration against policy; (3) close gaps before deployment.
27.1 Role policy
Jonas writes a role policy: any function that mints, upgrades, moves reserves or changes data sources or fees must require at least two signers and a timelock of at least 48 hours, except pause, which needs two signers but no timelock because its purpose is fast protection. The policy reflects EthTrust guidance on timelocks for sensitive operations and ConsenSys advice on restricting administrative power. Writing the policy as rules allows automatic checking of configurations against it. The board approves the policy as a formal document.
27.2 Checking configuration
Jonas writes a standard-library script that reads a synthetic inventory of privileged functions across four contracts, with controller type, signers required and timelock hours, and reports any function that breaks the policy. It only reads the inventory and prints findings for review. Configuration drift is common in practice: a function may be deployed with a temporary single key during testing and never moved to the multi-signature wallet. Jonas tests the script on a small inventory with known breaches first, then runs it against the full synthetic inventory and records the date of each run so later runs can show drift.
Lab — Role policy check
"""Privileged-role inventory check for synthetic contracts (read-only)."""
# contract, function, controller, signers needed, timelock hours
ROLES = [
("Credit", "mint", "multisig", 3, 48), ("Credit", "pause", "multisig", 2, 0),
("Credit", "upgrade", "multisig", 3, 48), ("Market", "setFee", "single", 1, 0),
("Market", "upgrade", "multisig", 3, 24), ("Oracle", "setSource", "single", 1, 0),
("Vault", "withdrawReserve", "multisig", 3, 72),
]
FUND_OR_CODE = {"mint", "upgrade", "withdrawReserve", "setSource", "setFee"}
MIN_TIMELOCK = 48
def main():
for c, f, ctl, n, t in ROLES:
notes = []
if f in FUND_OR_CODE and n < 2:
notes.append("single signer")
if f in FUND_OR_CODE and t < MIN_TIMELOCK:
notes.append(f"timelock {t}h < {MIN_TIMELOCK}h")
if notes:
print(f"{c}.{f}: {'; '.join(notes)}")
print(f"privileged functions {len(ROLES)}; pause is exempt from timelock by design")
if __name__ == "__main__":
main()
Run with python3 lab_roles.py. Verified output:
Market.setFee: single signer; timelock 0h < 48h
Market.upgrade: timelock 24h < 48h
Oracle.setSource: single signer; timelock 0h < 48h
privileged functions 7; pause is exempt from timelock by design
27.3 Closing gaps
The check reports three issues among seven privileged functions: Market.setFee has a single signer and no timelock; Market.upgrade has a 24-hour timelock, below the 48-hour policy; and Oracle.setSource has a single signer and no timelock. Pause is correctly exempt from the timelock. Jonas notes that setSource is the most serious because a changed data source could affect credit prices. The team moves both single-signer functions to the multi-signature wallet and sets timelocks to 48 hours before deployment, then reruns the check.
Worked example
The check finds three policy breaches among seven privileged functions, including single-signer control of Oracle.setSource; all are fixed and rechecked.
Synthetic case. Contracts and inventory are synthetic; EEA EthTrust and ConsenSys best practices are real sources.
Errors and limits
Leaving test-time single-key control on production functions is a common, avoidable gap.
Exercises
- EX079 — Pause exemption. Why is pause exempt from the timelock? Rubric: 3 = its purpose is fast protection;; 2 = speed;; 1 = oversight;; 0 = none.
- EX080 — Breaches found. How many breaches did the check report? Rubric: 3 = three of seven functions;; 2 = three;; 1 = vague;; 0 = none.
- EX081 — Most serious. Which finding is most serious? Rubric: 3 = Oracle.setSource single signer;; 2 = data source;; 1 = pause;; 0 = none.
Synthesis
A written role policy checked automatically against configuration closes privileged-control gaps.
Continue studying — chapter 27 of 50
← Chapter 26 (draft) · Course chapter index · Chapter 28 (draft) →