aere-contracts/contracts/mocks/CoverageProbes.sol
Aere Network a13a649b77
Some checks are pending
contracts-ci / Install (lockfile) → compile → full test suite (push) Waiting to run
contracts-ci / PQC known-answer tests (NIST vectors) (push) Waiting to run
contracts-ci / Coverage (scoped, with artifacts) (push) Waiting to run
Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:02:37 +03:00

237 lines
8.1 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
/**
* @title CoverageProbes
* @notice TEST-ONLY helpers for the round-2 branch-coverage suite. None of these
* is deployed to any network; they exist purely so that failure branches
* which cannot be driven by an EOA become reachable from Hardhat.
*
* They are excluded from coverage instrumentation (see .solcover.js) so
* the measured per-file table stays apples-to-apples with the baseline.
*/
/// @notice Refuses every plain AERE transfer (no receive, no fallback), but can
/// still ORIGINATE calls via `exec`. This is what makes the
/// `(bool ok, ) = x.call{value: v}(""); require(ok)` FALSE branches
/// reachable: an EOA recipient always accepts value, a contract with no
/// receive() does not.
contract EtherRejector {
/// Forward an arbitrary call so this contract can be the msg.sender that
/// triggers a payout back to itself (which then fails).
function exec(address target, bytes calldata data) external returns (bytes memory) {
(bool ok, bytes memory ret) = target.call(data);
if (!ok) {
assembly {
revert(add(ret, 0x20), mload(ret))
}
}
return ret;
}
/// Same, with value attached (used to register/delegate from a contract).
function execValue(address target, bytes calldata data, uint256 value) external payable returns (bytes memory) {
(bool ok, bytes memory ret) = target.call{ value: value }(data);
if (!ok) {
assembly {
revert(add(ret, 0x20), mload(ret))
}
}
return ret;
}
/// Accept an ERC-721 so this contract can hold a fee-stream NFT.
function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
return this.onERC721Received.selector;
}
// Deliberately NO receive() and NO fallback(): plain value transfers revert.
}
/// @notice `owner()` returns the zero address, exercising the
/// `o != address(0)` FALSE side of AereFeeMonetizationV2.controlsContract
/// (a target with an owner() that answers, but answers zero).
contract ZeroOwnerProbe {
function owner() external pure returns (address) {
return address(0);
}
}
/// @notice Has code but no `owner()` at all, so the staticcall hits the fallback
/// and the try/catch CATCH arm in controlsContract is taken.
contract NoOwnerProbe {
uint256 public marker = 1;
}
/// @notice Accepts AERE and, on the FIRST value transfer after being armed,
/// re-enters a target with stored calldata. The re-entry is made with a
/// low-level call so the ReentrancyGuard's revert is CAUGHT here and the
/// outer, legitimate call still completes — the same shape as
/// MockReentrantBountyToken, which is what lets the blocked branch be
/// observed instead of unwinding the whole transaction.
contract ReentrantEtherProbe {
address public target;
bytes public payload;
bool public armed;
bool public reentryAttempted;
bool public reentryBlocked;
function arm(address _target, bytes calldata _payload) external {
target = _target;
payload = _payload;
armed = true;
reentryAttempted = false;
reentryBlocked = false;
}
/// Originate a call (so this contract can be the delegator / NFT holder).
function exec(address to, bytes calldata data) external returns (bytes memory) {
(bool ok, bytes memory ret) = to.call(data);
if (!ok) {
assembly {
revert(add(ret, 0x20), mload(ret))
}
}
return ret;
}
function execValue(address to, bytes calldata data, uint256 value) external payable returns (bytes memory) {
(bool ok, bytes memory ret) = to.call{ value: value }(data);
if (!ok) {
assembly {
revert(add(ret, 0x20), mload(ret))
}
}
return ret;
}
function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
return this.onERC721Received.selector;
}
function _tryReenter() internal {
if (!armed || target == address(0)) return;
armed = false; // one-shot, or the guard would be re-tested forever
reentryAttempted = true;
(bool ok, ) = target.call(payload);
reentryBlocked = !ok;
}
receive() external payable {
_tryReenter();
}
}
/// @notice ERC20 whose transferFrom re-enters a target once. AereSink.flush pulls
/// with transferFrom BEFORE it does anything else, so this is the hook
/// that reaches flush's own ReentrancyGuard.
contract ReentrantFlushToken {
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
address public target;
bytes public payload;
bool public armed;
bool public reentryAttempted;
bool public reentryBlocked;
function mint(address to, uint256 amt) external {
balanceOf[to] += amt;
}
function arm(address _target, bytes calldata _payload) external {
target = _target;
payload = _payload;
armed = true;
}
function approve(address spender, uint256 amt) external returns (bool) {
allowance[msg.sender][spender] = amt;
return true;
}
function _tryReenter() internal {
if (!armed || target == address(0)) return;
armed = false;
reentryAttempted = true;
(bool ok, ) = target.call(payload);
reentryBlocked = !ok;
}
function transfer(address to, uint256 amt) external returns (bool) {
balanceOf[msg.sender] -= amt;
balanceOf[to] += amt;
return true;
}
function transferFrom(address from, address to, uint256 amt) external returns (bool) {
_tryReenter();
balanceOf[from] -= amt;
balanceOf[to] += amt;
return true;
}
}
/// @notice ERC20 whose transfer REVERTS outright (rather than returning false).
/// AereSink._safeTransfer checks `!ok || (ret.length > 0 && !decode)`;
/// the return-false token drives the SECOND leg, and only a token that
/// actually reverts drives the FIRST (`!ok`).
contract RevertingTransferToken {
mapping(address => uint256) public balanceOf;
function mint(address to, uint256 amt) external {
balanceOf[to] += amt;
}
function transfer(address, uint256) external pure returns (bool) {
revert("token: transfer disabled");
}
function transferFrom(address, address, uint256) external pure returns (bool) {
revert("token: transferFrom disabled");
}
function approve(address, uint256) external pure returns (bool) {
return true;
}
}
/// @notice V2-style router whose swap reverts with EMPTY revert data.
/// AereSink's catch block does `err.length > 0 ? string(err) : "swap-failed"`.
/// A router that reverts with a reason string drives the TRUE side; only
/// a bare `revert()` (zero-length returndata) drives the FALSE side.
contract EmptyRevertRouter {
function swapExactTokensForTokens(
uint256,
uint256,
address[] calldata,
address,
uint256
) external pure returns (uint256[] memory) {
revert();
}
}
/// @notice Price oracle that reverts for ONE designated asset only.
/// AereSink._computeOracleFloor has TWO nested try/catch arms; the shared
/// MockPriceOracle can only revert globally, which reaches the OUTER
/// catch. Reverting for the AERE leg alone is the only way to reach the
/// INNER catch.
contract SelectiveRevertOracle {
mapping(address => uint256) public prices;
mapping(address => bool) public revertsFor;
function setPrice(address asset, uint256 price) external {
prices[asset] = price;
}
function setRevertFor(address asset, bool b) external {
revertsFor[asset] = b;
}
function getPrice(address asset) external view returns (uint256) {
require(!revertsFor[asset], "oracle: asset paused");
return prices[asset];
}
}