// SPDX-License-Identifier: MIT pragma solidity 0.8.35; import {console2} from "forge-std/console2.sol"; import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol"; import {BankV1} from "../src/BankV1.sol"; import {MockUSDC} from "../src/MockUSDC.sol"; import {DemoScript} from "./lib/DemoScript.sol"; contract CheckState is DemoScript { error Insolvent(uint256 reserves, uint256 liabilities); error UnknownStage(string stage); function run() external view { _run(_manifestPath(ACTIVE_MANIFEST_PATH), vm.envOr("DEMO_EXPECTED_STAGE", string("v1"))); } function _run(string memory manifestPath, string memory stage) internal view { _requireSupportedChain(block.chainid); _printEducationalWarning(); bool deployedStage = keccak256(bytes(stage)) == keccak256("deployed"); Manifest memory manifest = _readManifest(manifestPath, !deployedStage); BankV1 bank = BankV1(manifest.proxy); MockUSDC token = MockUSDC(manifest.token); address actualImplementation = Upgrades.getImplementationAddress(manifest.proxy); _assertAddress("implementation", manifest.implementation, actualImplementation); _assertAddress("owner", manifest.owner, bank.owner()); _assertAddress("asset", manifest.token, address(bank.asset())); uint256 reserves = token.balanceOf(manifest.proxy); uint256 liabilities = bank.totalLiabilities(); if (reserves < liabilities) revert Insolvent(reserves, liabilities); uint256 surplus = reserves - liabilities; console2.log("network", manifest.network); console2.log("block", block.number); console2.log("token", manifest.token); console2.log("proxy", manifest.proxy); console2.log("implementation", actualImplementation); console2.log("owner", bank.owner()); console2.log("paused", bank.paused()); console2.log("version", bank.contractVersion()); for (uint256 i; i < manifest.actors.length; ++i) { console2.log(manifest.actors[i].label, manifest.actors[i].address_); console2.log(" bank balance", bank.balanceOf(manifest.actors[i].address_)); console2.log(" token balance", token.balanceOf(manifest.actors[i].address_)); } console2.log("reserves", reserves); console2.log("liabilities", liabilities); console2.log("surplus", surplus); bytes32 stageHash = keccak256(bytes(stage)); if (deployedStage) { _assertDeployedState(manifest); } else if (stageHash == keccak256("v1")) { _assertV1State(manifest); _assertUint("surplus", 0, surplus); } else if (stageHash == keccak256("upgraded")) { _assertUint("Alice internal balance", 900e6, bank.balanceOf(manifest.actors[1].address_)); _assertUint("Bob internal balance", 500e6, bank.balanceOf(manifest.actors[2].address_)); _assertUint("liabilities", 1_400e6, liabilities); _assertUint("reserves", 1_400e6, reserves); _assertUint("surplus", 0, surplus); _assertUint("version", 2, bank.contractVersion()); } else if (stageHash == keccak256("v2")) { _assertUint("Alice internal balance", 650e6, bank.balanceOf(manifest.actors[1].address_)); _assertUint("Bob internal balance", 750e6, bank.balanceOf(manifest.actors[2].address_)); _assertUint("liabilities", 1_400e6, liabilities); _assertUint("reserves", 1_400e6, reserves); _assertUint("surplus", 0, surplus); _assertUint("version", 2, bank.contractVersion()); } else if (stageHash != keccak256("invariants")) { revert UnknownStage(stage); } } }