M05-L02 · Solidity Fundamentals

Mapping, structs and ledger accounting

Mapping, structs and ledger accounting

01 — Bài toán

Thiết kế một Smart Contract có thể được nhiều địa chỉ gọi mà không cần tin cậy một backend quản lý state.

02 — Vấn đề

Code chạy trong EVM, mỗi state write tiêu tốn gas và giao dịch có thể bị gọi từ bất kỳ địa chỉ nào. Java private không tương đương với bí mật on-chain.

03 — Giải pháp

Áp dụng các primitive Solidity đúng ngữ cảnh, xác minh preconditions, cập nhật state nhất quán và kiểm thử trường hợp thất bại.

04 — Lý thuyết

Mappings default to zero values and are not enumerable; struct groups account fields. A Solidity mapping is unlike an iterable Java Map.

So sánh Java: contract giống một stateful service được nhân bản theo đồng thuận; msg.sender tương tự authenticated caller nhưng không tự đảm bảo user identity; storage tồn tại trên chain, không giống Java heap.

Dependency: M04 EVM; M05 bài trước nếu có.

05 — Hands-on lab: Mapping, structs and ledger accounting

Chuẩn bị

Thực hiện

  1. Đọc theory.md và solution/src/Lab.sol, xác định state, invariants và external calls.
  2. Tự triển khai starter/src/Lab.sol trước khi xem solution.
  3. Viết các test trong starter/test/Lab.t.sol.
  4. cd solution && forge build && forge test -vvv
  5. forge test --gas-report để quan sát chi phí.
  6. forge test -vvvv nếu test fail, đọc call trace và revert reason.

Các test trong reference

Expected output

forge build thành công, tất cả các test trên PASS. Đây là kết quả dự kiến, chưa được xác minh trong môi trường đóng gói vì không có forge/solc.

Troubleshooting

07 — Exercises

  1. Implement contract và test từ đầu trong starter/, không copy solution.
  2. Implement debit and enforce totalCredit equals the sum of known accounts in tests.
  3. Bổ sung ít nhất một negative test (revert) và một edge case.
  4. Viết giải thích vì sao state thay đổi hoặc revert; so sánh với Java service.

Acceptance criteria: forge build pass; toàn bộ test pass; không sử dụng tài sản mainnet; README ghi các invariants và assumptions.

08 — Interview

Q1: Vì sao contract cần kiểm tra msg.sender? Bởi mọi địa chỉ đều có thể gửi transaction; quyền phải được enforce on-chain, không thể chỉ dựa vào API gateway.

Q2: view và pure khác nhau thế nào? view có thể đọc state nhưng không sửa state; pure không đọc hoặc sửa state contract.

Q3: Revert ảnh hưởng gì? State updates trong phạm vi bị revert được rollback, nhưng gas đã tiêu thụ không được hoàn lại hoàn toàn.

Q4: Mapping, structs and ledger accounting có rủi ro gì? Kiểm tra access control, arithmetic bounds, external calls, assumptions về người gọi và accounting invariants.