ERC1155.spec 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. methods {
  2. isApprovedForAll(address, address) returns(bool) envfree
  3. balanceOf(address, uint256) returns(uint256) envfree
  4. balanceOfBatch(address[], uint256[]) returns(uint256[]) envfree
  5. _doSafeBatchTransferAcceptanceCheck(address, address, address, uint256[], uint256[], bytes) envfree
  6. _doSafeTransferAcceptanceCheck(address, address, address, uint256, uint256, bytes) envfree
  7. setApprovalForAll(address, bool)
  8. safeTransferFrom(address, address, uint256, uint256, bytes)
  9. safeBatchTransferFrom(address, address, uint256[], uint256[], bytes)
  10. _mint(address, uint256, uint256, bytes)
  11. _mintBatch(address, uint256[], uint256[], bytes)
  12. _burn(address, uint256, uint256)
  13. _burnBatch(address, uint256[], uint256[])
  14. }
  15. /////////////////////////////////////////////////
  16. // Approval (4/4)
  17. /////////////////////////////////////////////////
  18. // STATUS - verified
  19. // Function $f, which is not setApprovalForAll, should not change approval
  20. rule unexpectedAllowanceChange(method f, env e) filtered { f -> f.selector != setApprovalForAll(address, bool).selector } {
  21. address account; address operator;
  22. bool approveBefore = isApprovedForAll(account, operator);
  23. calldataarg args;
  24. f(e, args);
  25. bool approveAfter = isApprovedForAll(account, operator);
  26. assert approveBefore == approveAfter, "You couldn't get king's approval this way!";
  27. }
  28. // STATUS - verified
  29. // approval can be changed only by owner
  30. rule onlyOwnerCanApprove(env e){
  31. address owner; address operator; bool approved;
  32. bool aprovalBefore = isApprovedForAll(owner, operator);
  33. setApprovalForAll(e, operator, approved);
  34. bool aprovalAfter = isApprovedForAll(owner, operator);
  35. assert aprovalBefore != aprovalAfter => owner == e.msg.sender, "There should be only one owner";
  36. }
  37. // STATUS - verified
  38. // chech in which scenarios (if any) isApprovedForAll() revertes
  39. rule approvalRevertCases(env e){
  40. address account; address operator;
  41. isApprovedForAll@withrevert(account, operator);
  42. assert !lastReverted, "Houston, we have a problem";
  43. }
  44. // STATUS - verified
  45. // setApproval changes only one approval
  46. rule onlyOneAllowanceChange(method f, env e) {
  47. address owner; address operator; address user;
  48. bool approved;
  49. bool userApproveBefore = isApprovedForAll(owner, user);
  50. setApprovalForAll(e, operator, approved);
  51. bool userApproveAfter = isApprovedForAll(owner, user);
  52. assert userApproveBefore != userApproveAfter => (e.msg.sender == owner && operator == user), "Imposter!";
  53. }
  54. /////////////////////////////////////////////////
  55. // Balance (3/3)
  56. /////////////////////////////////////////////////
  57. // STATUS - verified
  58. // Function $f, which is not one of transfers, mints and burns, should not change balanceOf of a user
  59. rule unexpectedBalanceChange(method f, env e)
  60. filtered { f -> f.selector != safeTransferFrom(address, address, uint256, uint256, bytes).selector
  61. && f.selector != safeBatchTransferFrom(address, address, uint256[], uint256[], bytes).selector
  62. && f.selector != _mint(address, uint256, uint256, bytes).selector
  63. && f.selector != _mintBatch(address, uint256[], uint256[], bytes).selector
  64. && f.selector != _burn(address, uint256, uint256).selector
  65. && f.selector != _burnBatch(address, uint256[], uint256[]).selector } {
  66. address from; uint256 id;
  67. uint256 balanceBefore = balanceOf(from, id);
  68. calldataarg args;
  69. f(e, args);
  70. uint256 balanceAfter = balanceOf(from, id);
  71. assert balanceBefore == balanceAfter, "How you dare to take my money?";
  72. }
  73. // STATUS - verified
  74. // chech in which scenarios balanceOf() revertes
  75. rule balanceOfRevertCases(env e){
  76. address account; uint256 id;
  77. balanceOf@withrevert(account, id);
  78. assert lastReverted => account == 0, "Houston, we have a problem";
  79. }
  80. // STATUS - verified
  81. // chech in which scenarios balanceOfBatch() revertes
  82. rule balanceOfBatchRevertCases(env e){
  83. address[] accounts; uint256[] ids;
  84. address account1; address account2; address account3;
  85. uint256 id1; uint256 id2; uint256 id3;
  86. require accounts.length == 3;
  87. require ids.length == 3;
  88. require accounts[0] == account1; require accounts[1] == account2; require accounts[2] == account3;
  89. balanceOfBatch@withrevert(accounts, ids);
  90. assert lastReverted => (account1 == 0 || account2 == 0 || account3 == 0), "Houston, we have a problem";
  91. }
  92. /////////////////////////////////////////////////
  93. // Transfer (14/14)
  94. /////////////////////////////////////////////////
  95. // STATUS - verified
  96. // transfer additivity
  97. rule transferAdditivity(env e){
  98. address from; address to; uint256 id; bytes data;
  99. uint256 amount; uint256 amount1; uint256 amount2;
  100. require amount == amount1 + amount2;
  101. storage initialStorage = lastStorage;
  102. safeTransferFrom(e, from, to, id, amount, data);
  103. uint256 balanceAfterSingleTransaction = balanceOf(to, id);
  104. safeTransferFrom(e, from, to, id, amount1, data) at initialStorage;
  105. safeTransferFrom(e, from, to, id, amount2, data);
  106. uint256 balanceAfterDoubleTransaction = balanceOf(to, id);
  107. assert balanceAfterSingleTransaction == balanceAfterDoubleTransaction, "Not additive";
  108. }
  109. // STATUS - verified
  110. // safeTransferFrom updates `from` and `to` balances
  111. rule transferCorrectness(env e){
  112. address from; address to; uint256 id; uint256 amount; bytes data;
  113. require to != from;
  114. uint256 fromBalanceBefore = balanceOf(from, id);
  115. uint256 toBalanceBefore = balanceOf(to, id);
  116. safeTransferFrom(e, from, to, id, amount, data);
  117. uint256 fromBalanceAfter = balanceOf(from, id);
  118. uint256 toBalanceAfter = balanceOf(to, id);
  119. assert fromBalanceBefore == fromBalanceAfter + amount, "Something wet wrong";
  120. assert toBalanceBefore == toBalanceAfter - amount, "Something wet wrong";
  121. }
  122. // STATUS - verified
  123. // cannot transfer more than allowed (safeBatchTransferFrom version)
  124. rule transferBatchCorrectness(env e){
  125. address from; address to; uint256[] ids; uint256[] amounts; bytes data;
  126. uint256 idToCheck1; uint256 amountToCheck1;
  127. uint256 idToCheck2; uint256 amountToCheck2;
  128. uint256 idToCheck3; uint256 amountToCheck3;
  129. require to != from;
  130. require idToCheck1 != idToCheck2 && idToCheck3 != idToCheck2 && idToCheck1 != idToCheck3;
  131. require ids.length == 3;
  132. require amounts.length == 3;
  133. require ids[0] == idToCheck1; require amounts[0] == amountToCheck1;
  134. require ids[1] == idToCheck2; require amounts[1] == amountToCheck2;
  135. require ids[2] == idToCheck3; require amounts[2] == amountToCheck3;
  136. uint256 fromBalanceBefore1 = balanceOf(from, idToCheck1);
  137. uint256 fromBalanceBefore2 = balanceOf(from, idToCheck2);
  138. uint256 fromBalanceBefore3 = balanceOf(from, idToCheck3);
  139. uint256 toBalanceBefore1 = balanceOf(to, idToCheck1);
  140. uint256 toBalanceBefore2 = balanceOf(to, idToCheck2);
  141. uint256 toBalanceBefore3 = balanceOf(to, idToCheck3);
  142. safeBatchTransferFrom(e, from, to, ids, amounts, data);
  143. uint256 fromBalanceAfter1 = balanceOf(from, idToCheck1);
  144. uint256 fromBalanceAfter2 = balanceOf(from, idToCheck2);
  145. uint256 fromBalanceAfter3 = balanceOf(from, idToCheck3);
  146. uint256 toBalanceAfter1 = balanceOf(to, idToCheck1);
  147. uint256 toBalanceAfter2 = balanceOf(to, idToCheck2);
  148. uint256 toBalanceAfter3 = balanceOf(to, idToCheck3);
  149. assert (fromBalanceBefore1 == fromBalanceAfter1 + amountToCheck1)
  150. && (fromBalanceBefore2 == fromBalanceAfter2 + amountToCheck2)
  151. && (fromBalanceBefore3 == fromBalanceAfter3 + amountToCheck3), "Something wet wrong";
  152. assert (toBalanceBefore1 == toBalanceAfter1 - amountToCheck1)
  153. && (toBalanceBefore2 == toBalanceAfter2 - amountToCheck2)
  154. && (toBalanceBefore3 == toBalanceAfter3 - amountToCheck3), "Something wet wrong";
  155. }
  156. // STATUS - verified
  157. // cannot transfer more than `from` balance (safeTransferFrom version)
  158. rule cannotTransferMoreSingle(env e){
  159. address from; address to; uint256 id; uint256 amount; bytes data;
  160. uint256 balanceBefore = balanceOf(from, id);
  161. safeTransferFrom@withrevert(e, from, to, id, amount, data);
  162. assert amount > balanceBefore => lastReverted, "Achtung! Scammer!";
  163. assert to == 0 => lastReverted, "Achtung! Scammer!";
  164. }
  165. // STATUS - verified
  166. // cannot transfer more than allowed (safeBatchTransferFrom version)
  167. rule cannotTransferMoreBatch(env e){
  168. address from; address to; uint256[] ids; uint256[] amounts; bytes data;
  169. uint256 idToCheck1; uint256 amountToCheck1;
  170. uint256 idToCheck2; uint256 amountToCheck2;
  171. uint256 idToCheck3; uint256 amountToCheck3;
  172. uint256 balanceBefore1 = balanceOf(from, idToCheck1);
  173. uint256 balanceBefore2 = balanceOf(from, idToCheck2);
  174. uint256 balanceBefore3 = balanceOf(from, idToCheck3);
  175. require ids.length == 3;
  176. require amounts.length == 3;
  177. require ids[0] == idToCheck1; require amounts[0] == amountToCheck1;
  178. require ids[1] == idToCheck2; require amounts[1] == amountToCheck2;
  179. // require ids[2] == idToCheck3; require amounts[2] == amountToCheck3;
  180. safeBatchTransferFrom@withrevert(e, from, to, ids, amounts, data);
  181. assert (amountToCheck1 > balanceBefore1 || amountToCheck2 > balanceBefore2 || amountToCheck2 > balanceBefore2) => lastReverted, "Achtung! Scammer!";
  182. }
  183. // STATUS - verified
  184. // safeBatchTransferFrom should revert if `to` is 0 address or if arrays length is different
  185. rule revertOfTransferBatch(env e){
  186. address from; address to; uint256[] ids; uint256[] amounts; bytes data;
  187. require ids.length < 100000000;
  188. require amounts.length < 100000000;
  189. uint256 idTMP = ids.length;
  190. uint256 amountsTMP = amounts.length;
  191. safeBatchTransferFrom@withrevert(e, from, to, ids, amounts, data);
  192. assert ids.length != amounts.length => lastReverted, "Achtung! Scammer!";
  193. assert to == 0 => lastReverted, "Achtung! Scammer!";
  194. }
  195. // STATUS - verified
  196. // Sender calling safeTransferFrom should only reduce 'from' balance and not other's if sending amount is greater than 0
  197. rule transferBalanceReduceEffect(env e){
  198. address from; address to; address other;
  199. uint256 id; uint256 amount;
  200. bytes data;
  201. require other != to;
  202. uint256 otherBalanceBefore = balanceOf(other, id);
  203. safeTransferFrom(e, from, to, id, amount, data);
  204. uint256 otherBalanceAfter = balanceOf(other, id);
  205. assert from != other => otherBalanceBefore == otherBalanceAfter, "Don't touch my money!";
  206. }
  207. // STATUS - verified
  208. // Sender calling safeTransferFrom should only reduce 'to' balance and not other's if sending amount is greater than 0
  209. rule transferBalanceIncreaseEffect(env e){
  210. address from; address to; address other;
  211. uint256 id; uint256 amount;
  212. bytes data;
  213. require from != other;
  214. uint256 otherBalanceBefore = balanceOf(other, id);
  215. safeTransferFrom(e, from, to, id, amount, data);
  216. uint256 otherBalanceAfter = balanceOf(other, id);
  217. assert other != to => otherBalanceBefore == otherBalanceAfter, "Don't touch my money!";
  218. }
  219. // STATUS - verified
  220. // Sender calling safeTransferFrom should only reduce 'from' balance and not other's if sending amount is greater than 0
  221. rule transferBatchBalanceFromEffect(env e){
  222. address from; address to; address other;
  223. uint256[] ids; uint256[] amounts;
  224. uint256 id1; uint256 amount1; uint256 id2; uint256 amount2; uint256 id3; uint256 amount3;
  225. bytes data;
  226. require other != to;
  227. // require ids.length == 3;
  228. // require amounts.length == 3;
  229. // require ids[0] == id1; require ids[1] == id2; require ids[2] == id3;
  230. // require amounts[0] == amount1; require amounts[1] == amount2; require amounts[2] == amount3;
  231. // require amount1 > 0; require amount2 > 0; require amount3 > 0;
  232. uint256 otherBalanceBefore1 = balanceOf(other, id1);
  233. uint256 otherBalanceBefore2 = balanceOf(other, id2);
  234. uint256 otherBalanceBefore3 = balanceOf(other, id3);
  235. safeBatchTransferFrom(e, from, to, ids, amounts, data);
  236. uint256 otherBalanceAfter1 = balanceOf(other, id1);
  237. uint256 otherBalanceAfter2 = balanceOf(other, id2);
  238. uint256 otherBalanceAfter3 = balanceOf(other, id3);
  239. assert from != other => (otherBalanceBefore1 == otherBalanceAfter1
  240. && otherBalanceBefore2 == otherBalanceAfter2
  241. && otherBalanceBefore3 == otherBalanceAfter3), "Don't touch my money!";
  242. }
  243. // STATUS - verified
  244. // Sender calling safeBatchTransferFrom should only reduce 'to' balance and not other's if sending amount is greater than 0
  245. rule transferBatchBalanceToEffect(env e){
  246. address from; address to; address other;
  247. uint256[] ids; uint256[] amounts;
  248. uint256 id1; uint256 amount1; uint256 id2; uint256 amount2; uint256 id3; uint256 amount3;
  249. bytes data;
  250. require other != from;
  251. // require ids.length == 3;
  252. // require amounts.length == 3;
  253. // require ids[0] == id1; require ids[1] == id2; require ids[2] == id3;
  254. // require amounts[0] == amount1; require amounts[1] == amount2; require amounts[2] == amount3;
  255. // require amount1 > 0; require amount2 > 0; require amount3 > 0;
  256. uint256 otherBalanceBefore1 = balanceOf(other, id1);
  257. uint256 otherBalanceBefore2 = balanceOf(other, id2);
  258. uint256 otherBalanceBefore3 = balanceOf(other, id3);
  259. safeBatchTransferFrom(e, from, to, ids, amounts, data);
  260. uint256 otherBalanceAfter1 = balanceOf(other, id1);
  261. uint256 otherBalanceAfter2 = balanceOf(other, id2);
  262. uint256 otherBalanceAfter3 = balanceOf(other, id3);
  263. assert other != to => (otherBalanceBefore1 == otherBalanceAfter1
  264. && otherBalanceBefore2 == otherBalanceAfter2
  265. && otherBalanceBefore3 == otherBalanceAfter3), "Don't touch my money!";
  266. }
  267. // STATUS - verified
  268. // cannot transfer without approval (safeTransferFrom version)
  269. rule noTransferForNotApproved(env e) {
  270. address from; address operator;
  271. address to; uint256 id; uint256 amount; bytes data;
  272. require from != e.msg.sender;
  273. bool approve = isApprovedForAll(from, e.msg.sender);
  274. safeTransferFrom@withrevert(e, from, to, id, amount, data);
  275. assert !approve => lastReverted, "You don't have king's approval!";
  276. }
  277. // STATUS - verified
  278. // cannot transfer without approval (safeBatchTransferFrom version)
  279. rule noTransferBatchForNotApproved(env e) {
  280. address from; address operator; address to;
  281. bytes data;
  282. uint256[] ids; uint256[] amounts;
  283. require from != e.msg.sender;
  284. bool approve = isApprovedForAll(from, e.msg.sender);
  285. safeBatchTransferFrom@withrevert(e, from, to, ids, amounts, data);
  286. assert !approve => lastReverted, "You don't have king's approval!";
  287. }
  288. // STATUS - verified
  289. // safeTransferFrom doesn't affect any approval
  290. rule noTransferEffectOnApproval(env e){
  291. address from; address to;
  292. address owner; address operator;
  293. uint256 id; uint256 amount;
  294. bytes data;
  295. bool approveBefore = isApprovedForAll(owner, operator);
  296. safeTransferFrom(e, from, to, id, amount, data);
  297. bool approveAfter = isApprovedForAll(owner, operator);
  298. assert approveBefore == approveAfter, "Something was effected";
  299. }
  300. // STATUS - verified
  301. // safeTransferFrom doesn't affect any approval
  302. rule noTransferBatchEffectOnApproval(env e){
  303. address from; address to;
  304. address owner; address operator;
  305. uint256[] ids; uint256[] amounts;
  306. bytes data;
  307. bool approveBefore = isApprovedForAll(owner, operator);
  308. safeBatchTransferFrom(e, from, to, ids, amounts, data);
  309. bool approveAfter = isApprovedForAll(owner, operator);
  310. assert approveBefore == approveAfter, "Something was effected";
  311. }
  312. /////////////////////////////////////////////////
  313. // Mint (9/9)
  314. /////////////////////////////////////////////////
  315. // STATUS - verified
  316. // mint additivity
  317. rule mintAdditivity(env e){
  318. address to; uint256 id; uint256 amount; uint256 amount1; uint256 amount2; bytes data;
  319. require amount == amount1 + amount2;
  320. storage initialStorage = lastStorage;
  321. _mint(e, to, id, amount, data);
  322. uint256 balanceAfterSingleTransaction = balanceOf(to, id);
  323. _mint(e, to, id, amount1, data) at initialStorage;
  324. _mint(e, to, id, amount2, data);
  325. uint256 balanceAfterDoubleTransaction = balanceOf(to, id);
  326. assert balanceAfterSingleTransaction == balanceAfterDoubleTransaction, "Not additive";
  327. }
  328. // STATUS - verified
  329. // mint should revert if `from` is 0
  330. rule mintRevertCases(env e){
  331. address to; uint256 id; uint256 amount; bytes data;
  332. _mint@withrevert(e, to, id, amount, data);
  333. assert to == 0 => lastReverted, "Should revert";
  334. }
  335. // STATUS - verified
  336. // mintBatch should revert if `from` is 0 or arrays have different length
  337. rule mintBatchRevertCases(env e){
  338. address to; uint256[] ids; uint256[] amounts; bytes data;
  339. require ids.length < 100000000;
  340. require amounts.length < 100000000;
  341. _mintBatch@withrevert(e, to, ids, amounts, data);
  342. assert to == 0 => lastReverted, "Should revert";
  343. assert ids.length != amounts.length => lastReverted, "Should revert";
  344. }
  345. // STATUS - verified
  346. // check that mint updates `to` balance correctly
  347. rule mintCorrectWork(env e){
  348. address to; uint256 id; uint256 amount; bytes data;
  349. uint256 otherBalanceBefore = balanceOf(to, id);
  350. _mint(e, to, id, amount, data);
  351. uint256 otherBalanceAfter = balanceOf(to, id);
  352. assert otherBalanceBefore == otherBalanceAfter - amount, "Something is wrong";
  353. }
  354. // STATUS - verified
  355. // check that mintBatch updates `bootcamp participantsfrom` balance correctly
  356. rule mintBatchCorrectWork(env e){
  357. address to;
  358. uint256 id1; uint256 id2; uint256 id3;
  359. uint256 amount1; uint256 amount2; uint256 amount3;
  360. uint256[] ids; uint256[] amounts;
  361. bytes data;
  362. require ids.length == 3;
  363. require amounts.length == 3;
  364. require id1 != id2 && id2 != id3 && id3 != id1;
  365. require ids[0] == id1; require ids[1] == id2; require ids[2] == id3;
  366. require amounts[0] == amount1; require amounts[1] == amount2; require amounts[2] == amount3;
  367. uint256 otherBalanceBefore1 = balanceOf(to, id1);
  368. uint256 otherBalanceBefore2 = balanceOf(to, id2);
  369. uint256 otherBalanceBefore3 = balanceOf(to, id3);
  370. _mintBatch(e, to, ids, amounts, data);
  371. uint256 otherBalanceAfter1 = balanceOf(to, id1);
  372. uint256 otherBalanceAfter2 = balanceOf(to, id2);
  373. uint256 otherBalanceAfter3 = balanceOf(to, id3);
  374. assert otherBalanceBefore1 == otherBalanceAfter1 - amount1
  375. && otherBalanceBefore2 == otherBalanceAfter2 - amount2
  376. && otherBalanceBefore3 == otherBalanceAfter3 - amount3
  377. , "Something is wrong";
  378. }
  379. // STATUS - verified
  380. // the user cannot mint more than max_uint256
  381. rule cantMintMoreSingle(env e){
  382. address to; uint256 id; uint256 amount; bytes data;
  383. require to_mathint(balanceOf(to, id) + amount) > max_uint256;
  384. _mint@withrevert(e, to, id, amount, data);
  385. assert lastReverted, "Don't be too greedy!";
  386. }
  387. // STATUS - verified
  388. // the user cannot mint more than max_uint256 (batch version)
  389. rule cantMintMoreBatch(env e){
  390. address to; bytes data;
  391. uint256 id1; uint256 id2; uint256 id3;
  392. uint256 amount1; uint256 amount2; uint256 amount3;
  393. uint256[] ids; uint256[] amounts;
  394. require ids.length == 3;
  395. require amounts.length == 3;
  396. require ids[0] == id1; require ids[1] == id2; require ids[2] == id3;
  397. require amounts[0] == amount1; require amounts[1] == amount2; require amounts[2] == amount3;
  398. require to_mathint(balanceOf(to, id1) + amount1) > max_uint256
  399. || to_mathint(balanceOf(to, id2) + amount2) > max_uint256
  400. || to_mathint(balanceOf(to, id3) + amount3) > max_uint256;
  401. _mintBatch@withrevert(e, to, ids, amounts, data);
  402. assert lastReverted, "Don't be too greedy!";
  403. }
  404. // STATUS - verified
  405. // mint changes only `to` balance
  406. rule cantMintOtherBalances(env e){
  407. address to; uint256 id; uint256 amount; bytes data;
  408. address other;
  409. uint256 otherBalanceBefore = balanceOf(other, id);
  410. _mint(e, to, id, amount, data);
  411. uint256 otherBalanceAfter = balanceOf(other, id);
  412. assert other != to => otherBalanceBefore == otherBalanceAfter, "I like to see your money disappearing";
  413. }
  414. // STATUS - verified
  415. // mintBatch changes only `to` balance
  416. rule cantMintBatchOtherBalances(env e){
  417. address to;
  418. uint256 id1; uint256 id2; uint256 id3;
  419. uint256[] ids; uint256[] amounts;
  420. address other;
  421. bytes data;
  422. uint256 otherBalanceBefore1 = balanceOf(other, id1);
  423. uint256 otherBalanceBefore2 = balanceOf(other, id2);
  424. uint256 otherBalanceBefore3 = balanceOf(other, id3);
  425. _mintBatch(e, to, ids, amounts, data);
  426. uint256 otherBalanceAfter1 = balanceOf(other, id1);
  427. uint256 otherBalanceAfter2 = balanceOf(other, id2);
  428. uint256 otherBalanceAfter3 = balanceOf(other, id3);
  429. assert other != to => (otherBalanceBefore1 == otherBalanceAfter1
  430. || otherBalanceBefore2 == otherBalanceAfter2
  431. || otherBalanceBefore3 == otherBalanceAfter3)
  432. , "I like to see your money disappearing";
  433. }
  434. // rule mintRevert(env e){
  435. // address operator;
  436. // address from;
  437. // address to;
  438. // uint256 id;
  439. // uint256 amount;
  440. // bytes data;
  441. //
  442. // require operator == e.msg.sender;
  443. // require from == 0;
  444. //
  445. // _doSafeTransferAcceptanceCheck@withrevert(operator, from, to, id, amount, data);
  446. //
  447. // bool acceptanceCheck = lastReverted;
  448. //
  449. // _mint@withrevert(e, to, id, amount, data);
  450. //
  451. // bool mintRevert = lastReverted;
  452. //
  453. // assert acceptanceCheck => mintRevert, "reverts are wrong";
  454. // }
  455. /////////////////////////////////////////////////
  456. // Burn (9/9)
  457. /////////////////////////////////////////////////
  458. // STATUS - verified
  459. // burn additivity
  460. rule burnAdditivity(env e){
  461. address from; uint256 id; uint256 amount; uint256 amount1; uint256 amount2;
  462. require amount == amount1 + amount2;
  463. storage initialStorage = lastStorage;
  464. _burn(e, from, id, amount);
  465. uint256 balanceAfterSingleTransaction = balanceOf(from, id);
  466. _burn(e, from, id, amount1) at initialStorage;
  467. _burn(e, from, id, amount2);
  468. uint256 balanceAfterDoubleTransaction = balanceOf(from, id);
  469. assert balanceAfterSingleTransaction == balanceAfterDoubleTransaction, "Not additive";
  470. }
  471. // STATUS - verified
  472. // burn should revert if `from` is 0
  473. rule burnRevertCases(env e){
  474. address from; uint256 id; uint256 amount;
  475. _burn@withrevert(e, from, id, amount);
  476. assert from == 0 => lastReverted, "Should revert";
  477. }
  478. // STATUS - verified
  479. // burnBatch should revert if `from` is 0 or arrays have different length
  480. rule burnBatchRevertCases(env e){
  481. address from; uint256[] ids; uint256[] amounts;
  482. require ids.length < 100000000;
  483. _burnBatch@withrevert(e, from, ids, amounts);
  484. assert from == 0 => lastReverted, "Should revert";
  485. assert ids.length != amounts.length => lastReverted, "Should revert";
  486. }
  487. // STATUS - verified
  488. // check that burn updates `from` balance correctly
  489. rule burnCorrectWork(env e){
  490. address from; uint256 id; uint256 amount;
  491. uint256 otherBalanceBefore = balanceOf(from, id);
  492. _burn(e, from, id, amount);
  493. uint256 otherBalanceAfter = balanceOf(from, id);
  494. assert otherBalanceBefore == otherBalanceAfter + amount, "Something is wrong";
  495. }
  496. // STATUS - verified
  497. // check that burnBatch updates `from` balance correctly
  498. rule burnBatchCorrectWork(env e){
  499. address from;
  500. uint256 id1; uint256 id2; uint256 id3;
  501. uint256 amount1; uint256 amount2; uint256 amount3;
  502. uint256[] ids; uint256[] amounts;
  503. require ids.length == 3;
  504. require id1 != id2 && id2 != id3 && id3 != id1;
  505. require ids[0] == id1; require ids[1] == id2; require ids[2] == id3;
  506. require amounts[0] == amount1; require amounts[1] == amount2; require amounts[2] == amount3;
  507. uint256 otherBalanceBefore1 = balanceOf(from, id1);
  508. uint256 otherBalanceBefore2 = balanceOf(from, id2);
  509. uint256 otherBalanceBefore3 = balanceOf(from, id3);
  510. _burnBatch(e, from, ids, amounts);
  511. uint256 otherBalanceAfter1 = balanceOf(from, id1);
  512. uint256 otherBalanceAfter2 = balanceOf(from, id2);
  513. uint256 otherBalanceAfter3 = balanceOf(from, id3);
  514. assert otherBalanceBefore1 == otherBalanceAfter1 + amount1
  515. && otherBalanceBefore2 == otherBalanceAfter2 + amount2
  516. && otherBalanceBefore3 == otherBalanceAfter3 + amount3
  517. , "Something is wrong";
  518. }
  519. // STATUS - verified
  520. // the user cannot burn more than they have
  521. rule cantBurnMoreSingle(env e){
  522. address from; uint256 id; uint256 amount;
  523. require to_mathint(balanceOf(from, id) - amount) < 0;
  524. _burn@withrevert(e, from, id, amount);
  525. assert lastReverted, "Don't be too greedy!";
  526. }
  527. // STATUS - verified
  528. // the user cannot burn more than they have (batch version)
  529. rule cantBurnMoreBatch(env e){
  530. address from;
  531. uint256 id1; uint256 id2; uint256 id3;
  532. uint256 amount1; uint256 amount2; uint256 amount3;
  533. uint256[] ids; uint256[] amounts;
  534. require ids.length == 3;
  535. require ids[0] == id1; require ids[1] == id2; require ids[2] == id3;
  536. require amounts[0] == amount1; require amounts[1] == amount2; require amounts[2] == amount3;
  537. require to_mathint(balanceOf(from, id1) - amount1) < 0
  538. || to_mathint(balanceOf(from, id2) - amount2) < 0
  539. || to_mathint(balanceOf(from, id3) - amount3) < 0 ;
  540. _burnBatch@withrevert(e, from, ids, amounts);
  541. assert lastReverted, "Don't be too greedy!";
  542. }
  543. // STATUS - verified
  544. // burn changes only `from` balance
  545. rule cantBurnOtherBalances(env e){
  546. address from; uint256 id; uint256 amount;
  547. address other;
  548. uint256 otherBalanceBefore = balanceOf(other, id);
  549. _burn(e, from, id, amount);
  550. uint256 otherBalanceAfter = balanceOf(other, id);
  551. assert other != from => otherBalanceBefore == otherBalanceAfter, "I like to see your money disappearing";
  552. }
  553. // STATUS - verified
  554. // burnBatch changes only `from` balance
  555. rule cantBurnBatchOtherBalances(env e){
  556. address from;
  557. uint256 id1; uint256 id2; uint256 id3;
  558. uint256 amount1; uint256 amount2; uint256 amount3;
  559. uint256[] ids; uint256[] amounts;
  560. address other;
  561. // require ids.length == 3;
  562. // require amounts.length == 3;
  563. // require ids[0] == id1; require ids[1] == id2; require ids[2] == id3;
  564. // require amounts[0] == amount1; require amounts[1] == amount2; require amounts[2] == amount3;
  565. uint256 otherBalanceBefore1 = balanceOf(other, id1);
  566. uint256 otherBalanceBefore2 = balanceOf(other, id2);
  567. uint256 otherBalanceBefore3 = balanceOf(other, id3);
  568. _burnBatch(e, from, ids, amounts);
  569. uint256 otherBalanceAfter1 = balanceOf(other, id1);
  570. uint256 otherBalanceAfter2 = balanceOf(other, id2);
  571. uint256 otherBalanceAfter3 = balanceOf(other, id3);
  572. assert other != from => (otherBalanceBefore1 == otherBalanceAfter1
  573. || otherBalanceBefore2 == otherBalanceAfter2
  574. || otherBalanceBefore3 == otherBalanceAfter3)
  575. , "I like to see your money disappearing";
  576. }