// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {IPluginFeed} from "../../src/interfaces/IPluginFeed.sol"; import {ITwapSource} from "../../src/TwapFallback.sol"; /// @notice Mock Plugin aggregator (also used for Apothem, where Plugin feeds are unlisted and can stall). contract MockPluginFeed is IPluginFeed { uint8 internal _decimals; int256 public answer; uint256 public updatedAt; uint80 public roundId = 1; uint80 public answeredInRound = 1; bool public noAccess; bool public customRevert; error Boom(); constructor(uint8 d) { _decimals = d; } function set(int256 a, uint256 t) external { answer = a; updatedAt = t; } function setRounds(uint80 r, uint80 air) external { roundId = r; answeredInRound = air; } function setNoAccess(bool v) external { noAccess = v; } function setCustomRevert(bool v) external { customRevert = v; } function description() external pure returns (string memory) { return "MOCK/USD"; } function _gate() internal view { require(!noAccess, "No access"); if (customRevert) revert Boom(); } function decimals() external view returns (uint8) { _gate(); return _decimals; } function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80) { _gate(); return (roundId, answer, updatedAt, updatedAt, answeredInRound); } } contract MockVault { uint8 public decimals = 18; uint256 public rate; // assets per 1e18 shares constructor(uint256 r) { rate = r; } function setRate(uint256 r) external { rate = r; } function convertToAssets(uint256 shares) external view returns (uint256) { return shares * rate / 1e18; } } /// @notice Cumulative mock in output units (quote = identity). contract MockTwap is ITwapSource { uint256 public cumulative; uint256 public lastTs; uint256 public price; constructor(uint256 p) { price = p; lastTs = block.timestamp; } function _acc() internal view returns (uint256) { return cumulative + price * (block.timestamp - lastTs); } function setPrice(uint256 p) external { cumulative = _acc(); lastTs = block.timestamp; price = p; } function priceCumulative() external view returns (uint256, uint256) { return (_acc(), block.timestamp); } function quote(uint256 avgRaw) external pure returns (uint256) { return avgRaw; } } contract MockToken { uint8 public decimals; constructor(uint8 d) { decimals = d; } } /// @notice UniswapV2-style pair: accumulates UQ112x112 prices on every reserve update. contract MockV2Pair { address public token0; address public token1; uint112 internal r0; uint112 internal r1; uint32 internal ts; uint256 public price0CumulativeLast; uint256 public price1CumulativeLast; constructor(address a, address b) { token0 = a; token1 = b; ts = uint32(block.timestamp); } function getReserves() external view returns (uint112, uint112, uint32) { return (r0, r1, ts); } function sync(uint112 n0, uint112 n1) external { uint32 nowTs = uint32(block.timestamp); unchecked { uint32 el = nowTs - ts; if (el > 0 && r0 != 0 && r1 != 0) { price0CumulativeLast += ((uint256(r1) << 112) / r0) * el; price1CumulativeLast += ((uint256(r0) << 112) / r1) * el; } } (r0, r1, ts) = (n0, n1, nowTs); } } contract MockVRFCoordinator { uint256 public nextId = 1; function requestRandomWords(bytes32, uint64, uint16, uint32, uint32) external returns (uint256) { return nextId++; } function fulfill(address consumer, uint256 id, uint256[] calldata words) external { (bool ok, bytes memory ret) = consumer.call(abi.encodeWithSignature("rawFulfillRandomWords(uint256,uint256[])", id, words)); if (!ok) assembly { revert(add(ret, 32), mload(ret)) } } }