123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- import "helpers.spec"
- import "methods/IERC20.spec"
- import "methods/IERC5805.spec"
- import "methods/IERC6372.spec"
- import "ERC20.spec"
- methods {
- numCheckpoints(address) returns (uint32) envfree
- ckptFromBlock(address, uint32) returns (uint32) envfree
- ckptVotes(address, uint32) returns (uint224) envfree
- maxSupply() returns (uint224) envfree
- }
- use invariant totalSupplyIsSumOfBalances
- /*
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ Helpers โ
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- */
- definition max_uint224() returns uint224 = 0xffffffffffffffffffffffffffff;
- /*
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ Ghost & hooks โ
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- */
- ghost totalVotes() returns uint224 {
- init_state axiom totalVotes() == 0;
- }
- ghost mapping(address => uint224) userVotes {
- init_state axiom forall address a. userVotes[a] == 0;
- }
- ghost mapping(address => uint32) userClock {
- init_state axiom forall address a. userClock[a] == 0;
- }
- ghost mapping(address => uint32) userCkpts {
- init_state axiom forall address a. userCkpts[a] == 0;
- }
- hook Sstore currentContract._checkpoints[KEY address account][INDEX uint32 index].votes uint224 newVotes (uint224 oldVotes) STORAGE {
- havoc totalVotes assuming totalVotes@new() == totalVotes@old() + newVotes - userVotes[account];
- userVotes[account] = newVotes;
- userCkpts[account] = index;
- }
- hook Sstore currentContract._checkpoints[KEY address account][INDEX uint32 index].fromBlock uint32 newTimepoint (uint32 oldTimepoint) STORAGE {
- userClock[account] = newTimepoint;
- userCkpts[account] = index;
- }
- /*
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ Invariant: clock โ
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- */
- invariant clockMode(env e)
- clock(e) == e.block.number || clock(e) == e.block.timestamp
- /*
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ Invariant: hook correctly track latest checkpoint โ
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- */
- invariant hooksAreCorrect(address a)
- numCheckpoints(a) > 0 => (
- userVotes[a] == getVotes(a) &&
- userVotes[a] == ckptVotes(a, numCheckpoints(a) - 1) &&
- userClock[a] == ckptFromBlock(a, numCheckpoints(a) - 1) &&
- userCkpts[a] == numCheckpoints(a) - 1
- )
- /*
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ Invariant: checkpoint is not in the future โ
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- */
- invariant userClockInThePast(env e, address a)
- numCheckpoints(a) > 0 => ckptFromBlock(a, numCheckpoints(a) - 1) <= clock(e)
- {
- preserved with (env e2) {
- require clock(e2) <= clock(e);
- }
- }
- /*
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ Invariant: checkpoint clock is strictly increassing (implies no duplicate) โ
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- */
- invariant checkpointClockIncreassing(address a)
- numCheckpoints(a) > 1 => ckptFromBlock(a, numCheckpoints(a) - 2) < ckptFromBlock(a, numCheckpoints(a) - 1)
- {
- preserved with (env e) {
- requireInvariant userClockInThePast(e, a);
- }
- }
- /// For some reason "sumOfBalances" is not tracking correctly ...
- /// ... and we get counter example where totalSupply is more than the sum of involved balances
- // invariant totalVotesLessTotalSupply()
- // totalVotes() <= totalSupply()
- // {
- // preserved {
- // requireInvariant totalSupplyIsSumOfBalances;
- // }
- // }
- /// For some reason "sumOfBalances" is not tracking correctly ...
- /// ... and we get counter example where totalSupply is more than the sum of involved balances
- // invariant userVotesLessTotalVotes(address a)
- // numCheckpoints(a) > 0 => getVotes(a) <= totalVotes()
- // {
- // preserved {
- // requireInvariant totalSupplyIsSumOfBalances;
- // }
- // }
|