synapsecns/sanguine

View on GitHub
packages/solidity-devops/src/base/PathFinder.sol

Summary

Maintainability
Test Coverage
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.12;

import {StringUtils} from "../libs/StringUtils.sol";

import {CommonBase} from "forge-std/Base.sol";
import {stdJson} from "forge-std/StdJson.sol";

abstract contract PathFinder is CommonBase {
    using StringUtils for string;
    using stdJson for string;

    string private constant DEFAULT_DEVOPS_CONFIG = "./devops.json";
    string internal constant ENVIRONMENT_PROD = "";

    string private devopsConfig;

    modifier withDevopsConfig() {
        require(devopsConfig.length() > 0, "Devops config not loaded");
        _;
    }

    function assertFileExists(string memory filePath) internal {
        require(vm.exists(filePath), StringUtils.concat("File does not exist: ", filePath));
    }

    function loadDevopsConfig() internal {
        string memory devopsConfigPath = getDevopsConfigPath();
        assertFileExists(devopsConfigPath);
        devopsConfig = vm.readFile(devopsConfigPath);
    }

    // ═══════════════════════════════════════════════ PATH GETTERS ════════════════════════════════════════════════════

    /// @dev Path to the devops.json file. Could be overridden if the location of the file is different.
    function getDevopsConfigPath() internal pure virtual returns (string memory) {
        return DEFAULT_DEVOPS_CONFIG;
    }

    /// @notice Returns the path to the directory where the forge artifacts for the contracts are stored.
    /// @dev The path is configured in the devops.json file.
    function getForgeArtifactsPath() internal view withDevopsConfig returns (string memory) {
        return devopsConfig.readString(".forgeArtifacts").concat("/");
    }

    /// @notice Returns the path to the temp directory where the deployment artifacts are saved during a script run.
    /// Note: deployment artifacts are NOT saved to the deployments directory automatically, another script must be run
    /// to verify that the deployment was successful and save the deployment artifacts to the deployments directory.
    /// The reason for this is that the forge script is simulated before the broadcasted transactions are sent,
    /// and the artifacts are saved during the script simulation. So we can't know if the deployment was successful
    /// until the script is actually run.
    /// @dev The path is configured in the devops.json file.
    function getFreshDeploymentsPath() internal view withDevopsConfig returns (string memory) {
        return devopsConfig.readString(".freshDeployments").concat("/");
    }

    /// @notice Returns the path to the directory where the deployment artifacts are stored.
    /// Note: only verified deployments are stored in this directory.
    /// @dev The path is configured in the devops.json file.
    function getDeploymentsPath() internal view withDevopsConfig returns (string memory) {
        return devopsConfig.readString(".deployments").concat("/");
    }

    /// @notice Returns the path to the directory where the deployment configuration files are stored.
    /// @dev The path is configured in the devops.json file.
    function getDeployConfigsPath() internal view withDevopsConfig returns (string memory) {
        return devopsConfig.readString(".deployConfigs").concat("/");
    }

    /// @notice Returns the path to the global deployment configuration file for a contract.
    /// @dev Override this function to customize the path to the global deployment config file.
    function getGlobalDeployConfigPath() internal view virtual returns (string memory) {
        return getDeployConfigsPath().concat("global/");
    }

    // ═════════════════════════════════════════════ FILE NAME GETTERS ═════════════════════════════════════════════════

    /// @notice Returns the path to the contract artifact generated by forge.
    /// Example: "artifacts/SynapseRouter.sol/SynapseRouter.json"
    function getArtifactFN(string memory contractName) internal view returns (string memory) {
        return getForgeArtifactsPath().concat(contractName, ".sol/", contractName, ".json");
    }

    /// @notice Returns the path to the FRESH contract deployment JSON for a contract.
    /// Example: ".deployments/mainnet/SynapseRouter.json"
    function getFreshDeploymentFN(
        string memory chain,
        string memory contractName
    )
        internal
        view
        returns (string memory)
    {
        return getFreshDeploymentsPath().concat(chain, "/", contractName, ".json");
    }

    /// @notice Returns the path to the SAVED deployment JSON for a contract.
    /// Example: "deployments/mainnet/SynapseRouter.json"
    function getDeploymentFN(string memory chain, string memory contractName) internal view returns (string memory) {
        return getDeploymentsPath().concat(chain, "/", contractName, ".json");
    }

    /// @notice Returns the path to the generic file on a given chain.
    /// @dev Useful for the files that are not specific to a contract, but are specific to a chain.
    function getChainGenericFN(string memory chain, string memory fileName) internal view returns (string memory) {
        return getDeployConfigsPath().concat(chain, "/", fileName);
    }

    /// @notice Returns the path to the contract deployment config JSON for a contract on a given chain.
    /// Example: "script/configs/mainnet/SynapseRouter.dc.json"
    function getDeployConfigFN(string memory chain, string memory contractName) internal view returns (string memory) {
        return getChainGenericFN({chain: chain, fileName: contractName.concat(".dc.json")});
    }

    /// @notice Returns the path to the global config JSON that is shared across all chains for a contract.
    /// We expect different environments to exist, therefore the following pattern is used:
    /// - For a production environment, the environment param is empty, e.g. "script/configs/global/SynapseCCTP.json"
    /// - For a testnet, the environment param is "testnet", e.g. "script/configs/global/testnet/SynapseCCTP.json"
    function getGlobalDeployConfigFN(
        string memory contractName,
        string memory environment
    )
        internal
        view
        returns (string memory)
    {
        string memory environmentDir = environment.equals(ENVIRONMENT_PROD) ? "" : environment.concat("/");
        return getGlobalDeployConfigPath().concat(environmentDir, contractName, ".json");
    }
}