synapsecns/sanguine

View on GitHub
packages/solidity-devops/src/writer/DataWriter.sol

Summary

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

import {Logger} from "../base/Logger.sol";
import {PathFinder} from "../base/PathFinder.sol";
import {StringUtils} from "../libs/StringUtils.sol";

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

abstract contract DataWriter is PathFinder, Logger {
    using stdJson for string;
    using StringUtils for *;

    /// @notice Writes a JSON data to a file, and prints a log message.
    function writeJson(string memory descriptionLog, string memory path, string memory data) internal {
        printLogWithIndent(descriptionLog);
        createDirIfRequired(path);
        data.write(path);
    }

    /// @notice Writes the deployment JSON for a contract on a given chain under the specified alias.
    /// Example: contractName = "LinkedPool", contractAlias = "LinkedPool.USDC"
    /// Note: writes the JSON file to the FRESH deployments directory. The written file needs to be moved
    /// to the correct location outside of the deployment script.
    /// Note: will not include the ABI in the output JSON.
    function writeDeploymentArtifact(
        string memory chain,
        string memory contractAlias,
        string memory artifact
    )
        internal
        returns (string memory path)
    {
        // Use contract alias to determine the deployment path
        path = getFreshDeploymentFN(chain, contractAlias);
        // First write the deployment JSON without the ABI
        writeJson(StringUtils.concat("Saving deployment for ", contractAlias, " on ", chain), path, artifact);
    }

    /// @notice Writes the deploy config for a contract on a given chain.
    function writeDeployConfig(string memory chain, string memory contractName, string memory configData) internal {
        writeJson(
            StringUtils.concat("Saving deploy config for ", contractName, " on ", chain),
            getDeployConfigFN(chain, contractName),
            configData
        );
    }

    /// @notice Writes the global deploy config that is shared across all chains for a contract.
    function writeGlobalDeployConfig(
        string memory contractName,
        string memory environment,
        string memory configData
    )
        internal
    {
        string memory environmentLabel = environment.equals(ENVIRONMENT_PROD) ? "production" : environment;
        writeJson(
            StringUtils.concat("Saving global config for ", contractName, " [", environmentLabel, "]"),
            getGlobalDeployConfigFN(contractName, environment),
            configData
        );
    }

    /// @notice Writes the global deploy production config that is shared across all chains for a contract.
    function writeGlobalDeployProdConfig(string memory contractName, string memory configData) internal {
        writeGlobalDeployConfig(contractName, ENVIRONMENT_PROD, configData);
    }

    // ═══════════════════════════════════════════════════ UTILS ═══════════════════════════════════════════════════

    /// @notice Creates a directory where the file will be saved if it doesn't exist yet.
    function createDirIfRequired(string memory filePath) internal {
        // Path to the directory is everything that comes before the last slash
        uint256 lastSlash = filePath.lastIndexOf("/");
        if (lastSlash == StringUtils.NOT_FOUND) {
            return;
        }
        string memory dirPath = filePath.prefix(lastSlash);
        if (!vm.exists(dirPath)) {
            printLog(StringUtils.concat("Creating directory: ", dirPath));
            vm.createDir({path: dirPath, recursive: true});
        }
    }
}