// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Test} from "forge-std/Test.sol"; import {ObseroWatchBoard} from "../../src/ObseroWatchBoard.sol"; interface IERC20Meta { function symbol() external view returns (string memory); function decimals() external view returns (uint8); } /// Fork test against Robinhood Chain mainnet: /// forge test --match-path 'test/fork/*' --fork-url https://rpc.mainnet.chain.robinhood.com --evm-version cancun contract ObseroForkTest is Test { address constant USDG = 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168; address constant WETH = 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73; function setUp() public { vm.skip(block.chainid != 4663); } function test_fork_publishPresetForRealToken() public { // The preset target is a real token on the chain: its code exists and it answers like USDG. assertGt(USDG.code.length, 0); assertEq(IERC20Meta(USDG).symbol(), "USDG"); assertEq(IERC20Meta(USDG).decimals(), 6); ObseroWatchBoard board = new ObseroWatchBoard(); uint64 nowBlock = board.chainBlock(); bytes memory rules = bytes('{"v":1,"events":["Transfer"],"alerts":[]}'); uint256 id = board.publish(USDG, "USDG transfers", rules); ObseroWatchBoard.Preset memory p = board.preset(id); assertEq(p.publishedBlock, nowBlock); assertEq(p.rulesHash, keccak256(rules)); assertEq(board.targetPresetCount(USDG), 1); assertEq(board.targetPresetCount(WETH), 0); } function test_fork_chainBlockIsTheChainsOwnBlock() public { ObseroWatchBoard board = new ObseroWatchBoard(); // On a fork ArbSys is not emulated; the contract falls back to the forked block number, which is the // chain's own block (tens of millions), not the parent-chain block. assertEq(board.chainBlock(), uint64(block.number)); assertGt(block.number, 90_000_000); } }