12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- import "helpers/helpers.spec";
- import "methods/IERC20.spec";
- import "methods/IERC3156FlashLender.spec";
- import "methods/IERC3156FlashBorrower.spec";
- methods {
- // non standard ERC-3156 functions
- function flashFeeReceiver() external returns (address) envfree;
- // function summaries below
- function _._update(address from, address to, uint256 amount) internal => specUpdate(from, to, amount) expect void ALL;
- }
- /*
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ Ghost: track mint and burns in the CVL โ
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- */
- ghost mapping(address => mathint) trackedMintAmount;
- ghost mapping(address => mathint) trackedBurnAmount;
- ghost mapping(address => mapping(address => mathint)) trackedTransferedAmount;
- function specUpdate(address from, address to, uint256 amount) {
- if (from == 0 && to == 0) { assert(false); } // defensive
- if (from == 0) {
- trackedMintAmount[to] = amount;
- } else if (to == 0) {
- trackedBurnAmount[from] = amount;
- } else {
- trackedTransferedAmount[from][to] = amount;
- }
- }
- /*
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- โ Rule: When doing a flashLoan, "amount" is minted and burnt, additionally, the fee is either burnt โ
- โ (if the fee recipient is 0) or transferred (if the fee recipient is not 0) โ
- โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- */
- rule checkMintAndBurn(env e) {
- address receiver;
- address token;
- uint256 amount;
- bytes data;
- uint256 fees = flashFee(token, amount);
- address recipient = flashFeeReceiver();
- flashLoan(e, receiver, token, amount, data);
- assert trackedMintAmount[receiver] == to_mathint(amount);
- assert trackedBurnAmount[receiver] == amount + to_mathint(recipient == 0 ? fees : 0);
- assert (fees > 0 && recipient != 0) => trackedTransferedAmount[receiver][recipient] == to_mathint(fees);
- }
|