methods { balanceOf(address, uint256) returns uint256 envfree isApprovedForAll(address,address) returns bool envfree } /// If a method call reduces account balances, the caller must be either the /// holder of the account or approved to act on the holder's behalf. /// n.b. This rule was passing for all methods except `_burn` and `_burnBatch`, /// ordinarily internal methods that are callable by our tool only because they /// were changed to public for the purposes of prior verification. Filtered here /// since they are not generally callable. rule onlyHolderOrApprovedCanReduceBalance(method f) filtered { f -> f.selector != _burn(address,uint256,uint256).selector && f.selector != _burnBatch(address,uint256[],uint256[]).selector } { address holder; uint256 token; uint256 amount; uint256 balanceBefore = balanceOf(holder, token); env e; calldataarg args; f(e, args); uint256 balanceAfter = balanceOf(holder, token); assert balanceAfter < balanceBefore => e.msg.sender == holder || isApprovedForAll(holder, e.msg.sender), "An account balance may only be reduced by the holder or a holder-approved agent"; } /// Burning a larger amount of a token must reduce that token's balance more /// than burning a smaller amount. /// n.b. This rule holds for `burnBatch` as well due to rules establishing /// appropriate equivance between `burn` and `burnBatch` methods. rule burnAmountProportionalToBalanceReduction { storage beforeBurn = lastStorage; env e; address holder; uint256 token; mathint startingBalance = balanceOf(holder, token); uint256 smallBurn; uint256 largeBurn; require smallBurn < largeBurn; // smaller burn amount burn(e, holder, token, smallBurn) at beforeBurn; mathint smallBurnBalanceChange = startingBalance - balanceOf(holder, token); // larger burn amount burn(e, holder, token, largeBurn) at beforeBurn; mathint largeBurnBalanceChange = startingBalance - balanceOf(holder, token); assert smallBurnBalanceChange < largeBurnBalanceChange, "A larger burn must lead to a larger decrease in balance"; } /// @decription Two sequential burns must be equivalent to a single burn of the sum of their /// amounts. /// @formula