Blockchain and Trust Infrastructure Engineer · Focus area 3: Smart contracts

BC8: Testing and securing smart contracts

Goal: test contracts thoroughly with Hardhat, recognise and fix reentrancy, access-control and other common attacks, check invariants and know what fuzzing, static analysis and audits add, and write an honest security review with an incident plan.

You'll need: BC7, Module 26 (Debugging and Testing), Module 46 (Backend Testing), Module 75 (Web App Security), Module 80 (Security Assessment), and the SakhiKosh practice kit (contracts/SakhiFund.sol, contracts/test/, test/contract.test.js).

Where this is used: every serious contract team tests and reviews before deployment; audit firms, bug bounty platforms and security researchers do this work full time.

How it differs: a web app bug might leak data or crash a page, and is patched the same day. A contract bug can let anyone take the money it holds, in one transaction, permanently, while the whole world can read the code looking for it.

Time: reading about 3 hours · practice (the Try it tasks) about 3 hours · assignment about 5 hours.

Lessons

  1. 1Testing contracts with HardhatReading 15–25 minutes, plus practice✓
  2. 2ReentrancyReading 15–25 minutes, plus practice✓
  3. 3Other common attacksReading 15–25 minutes, plus practice✓
  4. 4Invariants, fuzzing and analysis toolsReading 15–25 minutes, plus practice✓
  5. 5Security reviews and incident plansReading 15–25 minutes, plus practice✓

🛠️Assignment: Secure SakhiFund

  1. Fix every finding in the starter's SakhiFund: reentrancy, tx.origin, unchecked return values, missing access controls and safeguards, plain ether and events.
  2. Run npm run test:contract until all 10 tests pass.
  3. Write docs/security-review.md with scope, findings with severities, fixes, tests and not verified.
  4. Write a half-page incident plan for SakhiKosh: who pauses, who tells members, and how funds move to a fixed contract.

Self-check before you finish:

✅Module check

Explain in a few sentences, in your own words:

How do you make a smart contract safe enough to deploy?

Show a good answer

A good answer mentions: tests on fresh fixtures for success, refusals, events, balances and every role; reentrancy fixed with checks, effects, interactions and a guard on every external call; access control, msg.sender, checked returns, pull payments, front-running and oracle risks; invariant tests, with fuzzing, static analysis and formal verification where the value justifies it; and an honest review with severities, fixes, tests and what wasn't verified, plus audits, bounties and an incident plan.

📚Official references

Official documentation and guidance for this module's topics, chosen on 2 November 2026. Tools, laws and standards change, so check the current version before you rely on a detail. If a link has moved, search the same site.

📝Module quiz

10 questions · 10 marks each · 100 marks in all · pass mark 70% · retry as often as you like ·

1. A team's tests only run as the admin account. What kind of bug are they most likely to miss?

Why each option is right or wrong

  • “Arithmetic overflow in a deposit that's larger than any member's real savings would ever be” (Incorrect): Solidity 0.8 reverts on overflow.
  • “Gas costs that vary by account” (Incorrect): Gas doesn't depend on who calls.
  • “Events that are emitted twice” (Incorrect): Event tests would catch that.
  • “Functions that anyone can call because they lack an access check” is correct.

    Test each function as an outsider too.

    • Pattern: admin, member and outsider per test.

📖 Revise: Lesson 1: Testing contracts with Hardhat

Question ID sp-blockchain-08-q1 · Report a mistake in this question
2. Why does each kit test start from loadFixture?

Why each option is right or wrong

  • “To make the tests run on a public test network instead of on the local practice network” (Incorrect): It stays local.
  • “To skip compiling the contracts again” (Incorrect): Compiling is separate.
  • “To give each test a different version of the contract” (Incorrect): It's the same contract.
  • “So every test begins from the same fresh state and can't affect another” is correct.

    Order of tests doesn't matter then.

    • Hardhat: resets to a snapshot.

📖 Revise: Lesson 1: Testing contracts with Hardhat

Question ID sp-blockchain-08-q2 · Report a mistake in this question
3. A contract sends ether and then updates the balance. The receiver's receive() calls withdraw again. What is this?

Why each option is right or wrong

  • “A front-running attack, as the receiver acts before others” (Incorrect): Front-running is about transaction order.
  • “A denial of service attack on the fund that stops it working” (Incorrect): The fund keeps paying, which is worse.
  • “An oracle attack, as the price of ether changes in between the two calls” (Incorrect): No price is involved.
  • “A reentrancy attack: each call sees the old balance and pays again” is correct.

    Update first, and add a guard.

    • History: The DAO in 2016.

📖 Revise: Lesson 2: Reentrancy

Question ID sp-blockchain-08-q3 · Report a mistake in this question
4. A learner fixes withdraw but another function, transferBalance, still sends before updating. What's the risk?

Why each option is right or wrong

  • “None, since reentrancy can only happen through a function called withdraw” (Incorrect): Any function that calls out can be re-entered.
  • “transferBalance will fail to compile” (Incorrect): It compiles.
  • “The guard on withdraw protects every function” (Incorrect): Only if it's on them too.
  • “The attacker re-enters through transferBalance instead” is correct.

    Apply the pattern and guard to every external call.

    • Name: cross-function reentrancy.

📖 Revise: Lesson 2: Reentrancy

Question ID sp-blockchain-08-q4 · Report a mistake in this question
5. A game pays all winners in one loop. One winner is a contract that reverts on receiving ether. What happens?

Why each option is right or wrong

  • “Only that winner misses out; the rest are paid” (Incorrect): The whole transaction reverts.
  • “The prize is sent to the next winner instead” (Incorrect): Nothing reassigns it.
  • “The network skips the reverting winner automatically” (Incorrect): It doesn't.
  • “The whole payout reverts, and nobody gets paid” is correct.

    One bad recipient blocks everyone.

    • Fix: let each winner withdraw.

📖 Revise: Lesson 3: Other common attacks

Question ID sp-blockchain-08-q5 · Report a mistake in this question
6. A lending contract reads a token's price from a single trading pool. An attacker borrows a huge amount for one transaction. What can they do?

Why each option is right or wrong

  • “Nothing, since loans must be repaid in a later block, after the price is read” (Incorrect): Flash loans are repaid in the same transaction.
  • “Only pay a higher fee than other users” (Incorrect): The risk is the price.
  • “Change the token's contract code” (Incorrect): They can't change code.
  • “Move the pool's price within the transaction and borrow against the false price” is correct.

    Use robust oracles and time-averaged prices.

    • Name: price manipulation with a flash loan.

📖 Revise: Lesson 3: Other common attacks

Question ID sp-blockchain-08-q6 · Report a mistake in this question
7. A fund passes its example tests but fails an invariant test after action 23 of 60 random actions. What does that tell you?

Why each option is right or wrong

  • “The invariant test itself is wrong, since all of the example tests already pass” (Incorrect): Example tests miss sequences.
  • “The random numbers were unlucky, and a rerun will pass” (Incorrect): The seed is fixed; it's a real bug.
  • “The contract needs a bigger gas limit” (Incorrect): Gas isn't involved.
  • “Some sequence breaks the rule that the ether matches the records” is correct.

    Look at action 23 to find the branch that's wrong.

    • Kit: Project 1's test 9.

📖 Revise: Lesson 4: Invariants, fuzzing and analysis tools

Question ID sp-blockchain-08-q7 · Report a mistake in this question
8. A review says "audited with Slither", but nobody ran it. What should it say instead?

Why each option is right or wrong

  • “Keep the claim, since Slither would probably have passed it” (Incorrect): Claims must match what was done.
  • “Say "fully secure" instead, which sounds more convincing” (Incorrect): That's a bigger false claim.
  • “Remove the security review entirely” (Incorrect): The review is still needed.
  • “List static analysis under "Not verified"” is correct.

    Honesty makes the review useful.

    • Or: run it and record the output.

📖 Revise: Lesson 4: Invariants, fuzzing and analysis tools

Question ID sp-blockchain-08-q8 · Report a mistake in this question
9. What should each finding in a security review include?

Why each option is right or wrong

  • “Only the line number of the problem, so that the reader can work out everything else” (Incorrect): Readers need the risk and the fix.
  • “The name of the developer who wrote the bug” (Incorrect): Blame doesn't help.
  • “A rating out of ten for the contract's style” (Incorrect): Style isn't the point.
  • “A title, a severity, where it is, why it matters, and how it was fixed” is correct.

    Then tests show each fix.

    • Severities: high, medium or low.

📖 Revise: Lesson 5: Security reviews and incident plans

Question ID sp-blockchain-08-q9 · Report a mistake in this question
10. A shared library used by many wallets is taken over and destroyed, freezing their funds. What would a review have looked for?

Why each option is right or wrong

  • “Whether the library's code was formatted to the team's style guide” (Incorrect): Style didn't freeze funds.
  • “Whether the wallets' owners used strong passwords” (Incorrect): Passwords weren't involved.
  • “Whether the library emitted enough events” (Incorrect): Events wouldn't stop it.
  • “Who could initialise and destroy the library, and what depended on it” is correct.

    Dependencies are part of the scope.

    • Plan: what to do if a dependency fails.

📖 Revise: Lesson 5: Security reviews and incident plans

Question ID sp-blockchain-08-q10 · Report a mistake in this question

ProLearners Assist