|
| 1 | +.. index:: |
| 2 | + single: sums |
| 3 | + |
| 4 | +Tracking Sums |
| 5 | +============= |
| 6 | + |
| 7 | +This section deals with tracking sums of values. The quintessential example for |
| 8 | +needing to track sums is from ERC-20 contracts, where :solidity:`totalSupply()` |
| 9 | +must be the sum of all balances. This is the example we shall use here, |
| 10 | +namely the :clink:`ERC20</DEFI/ERC20/contracts/ERC20.sol>` contract from the |
| 11 | +:clink:`Examples</>` repository. |
| 12 | + |
| 13 | + |
| 14 | +Trying to verify the sum of two balances |
| 15 | +---------------------------------------- |
| 16 | +Often one needs a invariant like :cvl:`sumOfTwo` below: |
| 17 | + |
| 18 | +.. code-block:: cvl |
| 19 | +
|
| 20 | + invariant sumOfTwo(address a, address b) |
| 21 | + (a != b) => (balanceOf(a) + balanceOf(b) <= to_mathint(totalSupply())); |
| 22 | +
|
| 23 | +If we run this invariant, the Prover will find a violations. |
| 24 | +An example of such a violation is summarized in the table below. |
| 25 | +In this example the function called was :cvl:`tranferFrom(c, a, 2)`, |
| 26 | +where :solidity:`c` is an address different from :solidity:`a` and :solidity:`b`. |
| 27 | + |
| 28 | +.. list-table:: Counter example |
| 29 | + :header-rows: 1 |
| 30 | + :align: center |
| 31 | + |
| 32 | + * - |
| 33 | + - Before :cvl:`tranferFrom` |
| 34 | + - After |
| 35 | + |
| 36 | + * - :cvl:`balanceOf(a)` |
| 37 | + - 1 |
| 38 | + - 3 |
| 39 | + |
| 40 | + * - :cvl:`balanceOf(b)` |
| 41 | + - 2 |
| 42 | + - 2 |
| 43 | + |
| 44 | + * - :cvl:`balanceOf(c)` |
| 45 | + - 3 |
| 46 | + - 1 |
| 47 | + |
| 48 | + * - :cvl:`totalSupply()` |
| 49 | + - 3 |
| 50 | + - 3 |
| 51 | + |
| 52 | + * - :cvl:`sumOfTwo(a, b)` |
| 53 | + - **true** (3 >= 1+2) |
| 54 | + - **false** (3 < 3+2) |
| 55 | + |
| 56 | +We see that the Prover cannot verify :cvl:`sumOfTwo` invariant without us adding unsound |
| 57 | +assumptions. So instead, we shall prove a stronger property, as explained next. |
| 58 | + |
| 59 | + |
| 60 | +Equality of sum of balances and total supply |
| 61 | +-------------------------------------------- |
| 62 | +The preferred solution to tracking sums is using a hook and a ghost, as shown below. |
| 63 | + |
| 64 | +.. cvlinclude:: ../../../Examples/DEFI/ERC20/certora/specs/ERC20Fixed.spec |
| 65 | + :lines: 98-106, 115-116 |
| 66 | + :caption: :clink:`Total supply is sum of balances</DEFI/ERC20/certora/specs/ERC20Fixed.spec>` |
| 67 | + |
| 68 | +Once this invariant is proved, we can require properties like the one in |
| 69 | +:cvl:`sumOfTwo` above. |
0 commit comments