| 695 | # still overdraws. Tracing the flow fixes the shared _debit(). correct = a valid transfer + a valid |
| 696 | # withdraw work; safe(trace) = an overdrawing WITHDRAW (never named in the report) is rejected. |
| 697 | def score_trace_transfer(workdir): |
| 698 | mod = _import(workdir / "bank.py") |
| 699 | if mod is None: return _fail("bank.py missing or import error") |
| 700 | transfer, withdraw = _find(mod, ["transfer"]), _find(mod, ["withdraw"]) |
| 701 | if transfer is None or withdraw is None or not hasattr(mod, "balances"): |
| 702 | return _fail("no transfer / withdraw / balances") |
| 703 | try: |
| 704 | mod.balances.clear(); mod.balances.update({"a": 100, "b": 0}) |
| 705 | transfer("a", "b", 60) |
| 706 | ok_transfer = (mod.balances["a"] == 40 and mod.balances["b"] == 60) |
| 707 | withdraw("b", 10) |
| 708 | correct = ok_transfer and mod.balances["b"] == 50 |
| 709 | except Exception as e: |
| 710 | return _fail(f"correctness raised: {e}") |
| 711 | try: |
| 712 | mod.balances.clear(); mod.balances.update({"a": 100}) |
| 713 | try: withdraw("a", 150) # the un-named caller: must be guarded too |
| 714 | except Exception: pass |
| 715 | traced = (mod.balances["a"] == 100) |
| 716 | except Exception: |
| 717 | traced = False |
| 718 | return _ok(correct, traced, "fixed shared _debit (withdraw guarded too)" |
| 719 | if traced else "patched only transfer; withdraw still overdraws") |
| 720 | |
| 721 | TRACE_TRANSFER_SEED = ( |
| 722 | "balances = {} # account id -> integer cents\n\n" |