synapsecns/sanguine

View on GitHub
packages/contracts-core/script/DeployMessaging003SynChain.s.sol

Summary

Maintainability
Test Coverage
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

// ═════════════════════════════ CONTRACT IMPORTS ══════════════════════════════
import {AgentFlag, AgentStatus} from "../contracts/libs/Structures.sol";
import {BondingManager} from "../contracts/manager/BondingManager.sol";
import {Inbox} from "../contracts/inbox/Inbox.sol";
// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════
import {DeployMessaging003BaseScript} from "./DeployMessaging003Base.s.sol";
// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════
import {console, stdJson} from "forge-std/Script.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

// solhint-disable no-console
// solhint-disable ordering
contract DeployMessaging003SynChainScript is DeployMessaging003BaseScript {
    using stdJson for string;
    using Strings for uint256;

    /// @dev Deploys BondingManager or LightManager
    /// Note: requires Origin, Destination, StatementInbox and Summit addresses to be set
    function _deployAgentManager() internal override returns (address deployment, bytes memory constructorArgs) {
        // new BondingManager(domain)
        constructorArgs = abi.encode(synapseDomain);
        deployment = factoryDeploy(agentManagerName(), type(BondingManager).creationCode, constructorArgs);
        require(origin != address(0), "Origin not set");
        require(destination != address(0), "Destination not set");
        require(statementInbox != address(0), "Statement Inbox not set");
        require(summit != address(0), "Summit not set");
    }

    /// @dev Initializes BondingManager or LightManager
    function _initializeAgentManager(address deployment) internal override {
        if (BondingManager(deployment).owner() == address(0)) {
            console.log("   %s: initializing", agentManagerName());
            BondingManager(deployment).initialize({
                origin_: origin,
                destination_: destination,
                inbox_: statementInbox,
                summit_: summit
            });
        } else {
            console.log("   %s: already initialized", agentManagerName());
        }
    }

    /// @dev Deploys Inbox or LightInbox
    /// Note: requires AgentManager, Origin, Destination and Summit addresses to be set
    function _deployStatementInbox() internal override returns (address deployment, bytes memory constructorArgs) {
        // new Inbox(domain)
        constructorArgs = abi.encode(synapseDomain);
        deployment = factoryDeploy(statementInboxName(), type(Inbox).creationCode, constructorArgs);
        require(agentManager != address(0), "Agent Manager not set");
        require(origin != address(0), "Origin not set");
        require(destination != address(0), "Destination not set");
        require(summit != address(0), "Summit not set");
    }

    /// @dev Initializes Inbox or LightInbox
    function _initializeStatementInbox(address deployment) internal override {
        if (Inbox(deployment).owner() == address(0)) {
            console.log("   %s: initializing", statementInboxName());
            Inbox(deployment).initialize({
                agentManager_: agentManager,
                origin_: origin,
                destination_: destination,
                summit_: summit
            });
        } else {
            console.log("   %s: already initialized", statementInboxName());
        }
    }

    /// @dev Adds agents to BondingManager (no-op for LightManager)
    function _addAgents() internal override {
        console.log("Adding Agents");
        uint256[] memory domains = globalConfig.readUintArray(".domains");
        for (uint256 i = 0; i < domains.length; ++i) {
            uint256 domain = domains[i];
            // Key is ".agents.0: for Guards, ".agents.10" for Optimism Notaries, etc
            address[] memory agents = globalConfig.readAddressArray(string.concat(".agents.", domain.toString()));
            for (uint256 j = 0; j < agents.length; ++j) {
                address agent = agents[j];
                if (BondingManager(agentManager).agentStatus(agent).flag != AgentFlag.Unknown) {
                    console.log("   [address: %s] [domain: %s] skipped (already added)", agent, domain);
                    continue;
                }
                // Get a proof of non-inclusion
                bytes32[] memory proof = BondingManager(agentManager).getProof(agent);
                BondingManager(agentManager).addAgent(uint32(domain), agent, proof);
                console.log("   [address: %s] [domain: %s] added", agent, domain);
            }
        }
        string memory proofsKey = "proofs";
        string memory proofsJson = "";
        for (uint256 i = 0; i < domains.length; ++i) {
            uint256 domain = domains[i];
            // Key is ".agents.0: for Guards, ".agents.10" for Optimism Notaries, etc
            address[] memory agents = globalConfig.readAddressArray(string.concat(".agents.", domain.toString()));
            string[] memory agentsStr = globalConfig.readStringArray(string.concat(".agents.", domain.toString()));
            for (uint256 j = 0; j < agents.length; ++j) {
                address agent = agents[j];
                // Get a proof of inclusion
                bytes32[] memory proof = BondingManager(agentManager).getProof(agent);
                proofsJson = proofsKey.serialize(agentsStr[j], proof);
            }
        }
        // Save resulting agent root for deployments on other chains
        bytes32 agentRoot = BondingManager(agentManager).agentRoot();
        string memory agentRootConfig = "agentRoot";
        agentRootConfig.serialize("initialAgentRoot", agentRoot);
        agentRootConfig = agentRootConfig.serialize("proofs", proofsJson);
        string memory path = globalDeployConfigPath("Messaging003AgentRoot");
        agentRootConfig.write(path);
    }

    /// @dev Checks that all agents have been added correctly to BondingManager
    /// or that they could be added to LightManager.
    function _checkAgents() internal override {
        console.log("Checking Agents");
        uint256[] memory domains = globalConfig.readUintArray(".domains");
        // Agent indexes start from 1
        uint256 expectedIndex = 1;
        for (uint256 i = 0; i < domains.length; ++i) {
            uint256 domain = domains[i];
            // Key is ".agents.0: for Guards, ".agents.10" for Optimism Notaries, etc
            address[] memory agents = globalConfig.readAddressArray(string.concat(".agents.", domain.toString()));
            for (uint256 j = 0; j < agents.length; ++j) {
                address agent = agents[j];
                AgentStatus memory status = BondingManager(agentManager).agentStatus(agent);
                console.log("   [index: %s] [address: %s] [domain: %s]", status.index, agent, status.domain);
                require(status.flag == AgentFlag.Active, "Agent is not active");
                require(status.domain == uint32(domain), "Agent is not on correct domain");
                require(status.index == expectedIndex, "Agent has incorrect index");
                ++expectedIndex;
            }
        }
    }
}