ERC1155Burnable.spec 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. methods {
  2. balanceOf(address, uint256) returns uint256 envfree
  3. isApprovedForAll(address,address) returns bool envfree
  4. }
  5. /// If a method call reduces account balances, the caller must be either the
  6. /// holder of the account or approved to act on the holder's behalf.
  7. rule onlyHolderOrApprovedCanReduceBalance {
  8. address holder; uint256 token; uint256 amount;
  9. uint256 balanceBefore = balanceOf(holder, token);
  10. method f; env e; calldataarg args;
  11. f(e, args);
  12. uint256 balanceAfter = balanceOf(holder, token);
  13. assert balanceAfter < balanceBefore => e.msg.sender == holder || isApprovedForAll(holder, e.msg.sender),
  14. "An account balance may only be reduced by the holder or a holder-approved agent";
  15. }
  16. /// Burning a larger amount of a token must reduce that token's balance more
  17. /// than burning a smaller amount.
  18. rule burnAmountProportionalToBalanceReduction {
  19. storage beforeBurn = lastStorage;
  20. env e;
  21. address holder; uint256 token;
  22. mathint startingBalance = balanceOf(holder, token);
  23. uint256 smallBurn; uint256 largeBurn;
  24. require smallBurn < largeBurn;
  25. // smaller burn amount
  26. burn(e, holder, token, smallBurn) at beforeBurn;
  27. mathint smallBurnBalanceChange = startingBalance - balanceOf(holder, token);
  28. // larger burn amount
  29. burn(e, holder, token, largeBurn) at beforeBurn;
  30. mathint largeBurnBalanceChange = startingBalance - balanceOf(holder, token);
  31. assert smallBurnBalanceChange < largeBurnBalanceChange,
  32. "A larger burn must lead to a larger decrease in balance";
  33. }
  34. /// Unimplemented rule to verify monotonicity of burnBatch.
  35. rule burnBatchAmountProportionalToBalanceReduction { // TODO implement rule or remove
  36. assert true,
  37. "just a placeholder that should never show up";
  38. }
  39. /// Two sequential burns must be equivalent to a single burn of the sum of their
  40. /// amounts.
  41. rule sequentialBurnsEquivalentToSingleBurnOfSum {
  42. storage beforeBurns = lastStorage;
  43. env e;
  44. address holder; uint256 token;
  45. mathint startingBalance = balanceOf(holder, token);
  46. uint256 firstBurn; uint256 secondBurn; uint256 sumBurn;
  47. require sumBurn == firstBurn + secondBurn;
  48. // sequential burns
  49. burn(e, holder, token, firstBurn) at beforeBurns;
  50. burn(e, holder, token, secondBurn);
  51. mathint sequentialBurnsBalanceChange = startingBalance - balanceOf(holder, token);
  52. // burn of sum of sequential burns
  53. burn(e, holder, token, sumBurn) at beforeBurns;
  54. mathint sumBurnBalanceChange = startingBalance - balanceOf(holder, token);
  55. assert sequentialBurnsBalanceChange == sumBurnBalanceChange,
  56. "Sequential burns must be equivalent to a burn of their sum";
  57. }
  58. /// Unimplemented rule to verify additivty of burnBatch.
  59. rule sequentialBatchBurnsEquivalentToSingleBurnBatchOfSum { // TODO implement rule or remove
  60. assert true,
  61. "just a placeholder that should never show up";
  62. }
  63. /// This rule should always fail.
  64. rule sanity {
  65. method f; env e; calldataarg args;
  66. f(e, args);
  67. assert false,
  68. "This rule should always fail";
  69. }