packages/contracts-core/test/utils/SynapseTest.t.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {AgentFlag, BondingManager} from "../../contracts/manager/BondingManager.sol";
import {AgentStatus, LightManager} from "../../contracts/manager/LightManager.sol";
import {IAgentSecured} from "../../contracts/interfaces/IAgentSecured.sol";
import {Destination} from "../../contracts/Destination.sol";
import {GasOracle} from "../../contracts/GasOracle.sol";
import {Origin} from "../../contracts/Origin.sol";
import {Summit} from "../../contracts/Summit.sol";
import {Inbox} from "../../contracts/inbox/Inbox.sol";
import {LightInbox} from "../../contracts/inbox/LightInbox.sol";
import {BondingManagerHarness} from "../harnesses/manager/BondingManagerHarness.t.sol";
import {LightManagerHarness} from "../harnesses/manager/LightManagerHarness.t.sol";
import {DestinationMock} from "../mocks/DestinationMock.t.sol";
import {GasOracleMock} from "../mocks/GasOracleMock.t.sol";
import {OriginMock} from "../mocks/OriginMock.t.sol";
import {SummitMock} from "../mocks/SummitMock.t.sol";
import {ProductionEvents} from "./events/ProductionEvents.t.sol";
import {SuiteEvents} from "./events/SuiteEvents.t.sol";
import {SynapseAgents} from "./SynapseAgents.t.sol";
import {SynapseProofs} from "./SynapseProofs.t.sol";
// solhint-disable no-empty-blocks
// solhint-disable ordering
abstract contract SynapseTest is ProductionEvents, SuiteEvents, SynapseAgents, SynapseProofs {
uint256 private immutable deployMask;
address internal gasOracleSynapse;
address internal originSynapse;
address internal destinationSynapse;
address internal summit;
Inbox internal inbox;
BondingManagerHarness internal bondingManager;
address internal gasOracle;
address internal destination;
address internal origin;
LightInbox internal lightInbox;
LightManagerHarness internal lightManager;
constructor(uint256 deployMask_) {
deployMask = deployMask_;
}
/// @notice Prevents this contract from being included in the coverage report
function testSynapseTest() external {}
function setUp() public virtual override {
// Setup domains and create agents for them
super.setUp();
// Deploy a single set of messaging contracts for synapse chain
deployBondingManager();
deployInbox();
deploySummit();
deployDestinationSynapse();
deployGasOracleSynapse();
deployOriginSynapse();
// Setup agents in BondingManager
initBondingManager();
initInbox();
setupAgentsBM();
// Deploy a single set of messaging contracts for local chain
deployLightManager();
deployLightInbox();
deployDestination();
deployGasOracle();
deployOrigin();
// Setup agents in LightManager
initLightManager();
initLightInbox();
setupAgentsLM();
// Skip block
skipBlock();
// cleanup the env.
vm.chainId(DOMAIN_LOCAL);
}
function setupAgentsBM() public virtual {
for (uint256 d = 0; d < allDomains.length; ++d) {
uint32 domain = allDomains[d];
for (uint256 i = 0; i < DOMAIN_AGENTS; ++i) {
address agent = domains[domain].agents[i];
addAgentBM(domain, agent);
}
}
}
function setupAgentsLM() public virtual {
if (deployMask & DEPLOY_MASK_DESTINATION == DEPLOY_PROD_DESTINATION) {
// Set initial agent merkle root via production Destination
Destination(destination).initialize(getAgentRoot());
} else {
// Mock a call from destination instead
bytes32 root = getAgentRoot();
vm.prank(destination);
lightManager.setAgentRoot(root);
}
for (uint256 d = 0; d < allDomains.length; ++d) {
uint32 domain = allDomains[d];
for (uint256 i = 0; i < DOMAIN_AGENTS; ++i) {
address agent = domains[domain].agents[i];
updateAgentLM(agent);
}
}
}
// ═════════════════════════════════════════════ DEPLOY CONTRACTS ══════════════════════════════════════════════════
function deployLightManager() public virtual {
vm.chainId(DOMAIN_LOCAL);
lightManager = new LightManagerHarness(DOMAIN_SYNAPSE);
vm.label(address(lightManager), "LightManager");
}
function initLightManager() public virtual {
lightManager.initialize(origin, destination, address(lightInbox));
}
function deployBondingManager() public virtual {
vm.chainId(DOMAIN_SYNAPSE);
bondingManager = new BondingManagerHarness(DOMAIN_SYNAPSE);
vm.label(address(bondingManager), "BondingManager");
}
function initBondingManager() public virtual {
bondingManager.initialize(originSynapse, destinationSynapse, address(inbox), summit);
}
function deployLightInbox() public virtual {
vm.chainId(DOMAIN_LOCAL);
lightInbox = new LightInbox(DOMAIN_SYNAPSE);
}
function initLightInbox() public virtual {
LightInbox(lightInbox).initialize(address(lightManager), origin, destination);
}
function deployInbox() public virtual {
vm.chainId(DOMAIN_SYNAPSE);
inbox = new Inbox(DOMAIN_SYNAPSE);
}
function initInbox() public virtual {
Inbox(inbox).initialize(address(bondingManager), originSynapse, destinationSynapse, summit);
}
function deployGasOracle() public virtual {
uint256 option = deployMask & DEPLOY_MASK_GAS_ORACLE;
if (option == DEPLOY_MOCK_GAS_ORACLE) {
gasOracle = address(new GasOracleMock());
} else if (option == DEPLOY_PROD_GAS_ORACLE) {
gasOracle = address(new GasOracle(DOMAIN_SYNAPSE, destination));
GasOracle(gasOracle).initialize();
} else {
revert("Unknown option: GasOracle");
}
vm.label(gasOracle, "GasOracle Local");
}
function deployDestination() public virtual {
uint256 option = deployMask & DEPLOY_MASK_DESTINATION;
if (option == DEPLOY_MOCK_DESTINATION) {
destination = address(new DestinationMock());
} else if (option == DEPLOY_PROD_DESTINATION) {
destination = address(new Destination(DOMAIN_SYNAPSE, address(lightManager), address(lightInbox)));
// Destination will be initialized once agents are setup
} else {
revert("Unknown option: Destination");
}
vm.label(destination, "Destination Local");
}
function deployOrigin() public virtual {
uint256 option = deployMask & DEPLOY_MASK_ORIGIN;
if (option == DEPLOY_MOCK_ORIGIN) {
origin = address(new OriginMock());
} else if (option == DEPLOY_PROD_ORIGIN) {
origin = address(new Origin(DOMAIN_SYNAPSE, address(lightManager), address(lightInbox), gasOracle));
Origin(origin).initialize();
} else {
revert("Unknown option: Origin");
}
vm.label(origin, "Origin Local");
}
function deployGasOracleSynapse() public virtual {
uint256 option = deployMask & DEPLOY_MASK_GAS_ORACLE_SYNAPSE;
if (option == DEPLOY_MOCK_GAS_ORACLE_SYNAPSE) {
gasOracleSynapse = address(new GasOracleMock());
} else if (option == DEPLOY_PROD_GAS_ORACLE_SYNAPSE) {
gasOracleSynapse = address(new GasOracle(DOMAIN_SYNAPSE, destinationSynapse));
GasOracle(gasOracleSynapse).initialize();
} else {
revert("Unknown option: GasOracle");
}
vm.label(gasOracleSynapse, "GasOracle Synapse");
}
function deployDestinationSynapse() public virtual {
uint256 option = deployMask & DEPLOY_MASK_DESTINATION_SYNAPSE;
if (option == DEPLOY_MOCK_DESTINATION_SYNAPSE) {
destinationSynapse = address(new DestinationMock());
} else if (option == DEPLOY_PROD_DESTINATION_SYNAPSE) {
destinationSynapse = address(new Destination(DOMAIN_SYNAPSE, address(bondingManager), address(inbox)));
Destination(destinationSynapse).initialize(0);
} else {
revert("Unknown option: Destination");
}
vm.label(destinationSynapse, "Destination Synapse");
}
function deployOriginSynapse() public virtual {
uint256 option = deployMask & DEPLOY_MASK_ORIGIN_SYNAPSE;
if (option == DEPLOY_MOCK_ORIGIN_SYNAPSE) {
originSynapse = address(new OriginMock());
} else if (option == DEPLOY_PROD_ORIGIN_SYNAPSE) {
originSynapse =
address(new Origin(DOMAIN_SYNAPSE, address(bondingManager), address(inbox), gasOracleSynapse));
Origin(originSynapse).initialize();
} else {
revert("Unknown option: Origin");
}
vm.label(originSynapse, "Origin Synapse");
}
function deploySummit() public virtual {
vm.chainId(DOMAIN_SYNAPSE);
uint256 option = deployMask & DEPLOY_MASK_SUMMIT;
if (option == DEPLOY_MOCK_SUMMIT) {
summit = address(new SummitMock());
} else if (option == DEPLOY_PROD_SUMMIT) {
summit = address(new Summit(DOMAIN_SYNAPSE, address(bondingManager), address(inbox)));
Summit(summit).initialize();
} else {
revert("Unknown option: Summit");
}
vm.label(summit, "Summit");
}
// ═══════════════════════════════════════════════ ADDING AGENTS ═══════════════════════════════════════════════════
function addAgentBM(uint32 domain, address agent) public {
bytes32[] memory proof = getZeroProof();
bondingManager.addAgent(domain, agent, proof);
addNewAgent(domain, agent);
}
function updateAgentLM(address agent) public {
bytes32[] memory proof = getAgentProof(agent);
lightManager.updateAgentStatus(agent, getAgentStatus(agent), proof);
}
function checkAgentStatus(address agent, AgentStatus memory status, AgentFlag flag) public virtual {
assertEq(uint8(status.flag), uint8(flag), "!flag");
assertEq(status.domain, agentDomain[agent], "!domain");
assertEq(status.index, agentIndex[agent], "!index");
}
}