"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const hardhat_1 = require("hardhat");
const constants_1 = require("../helpers/deploy/constants");
const deploymentConfig_1 = require("../helpers/deploy/deploymentConfig");
const deploymentUtils_1 = require("../helpers/deploy/deploymentUtils");
const configureAccessControls = (methods, accessControlManagerAddress, caller, target) => __awaiter(void 0, void 0, void 0, function* () {
    const commands = yield Promise.all(methods.map((method) => __awaiter(void 0, void 0, void 0, function* () {
        const callerAddress = caller;
        const targetAddress = target;
        return [
            {
                contract: accessControlManagerAddress,
                signature: "giveCallPermission(address,string,address)",
                argTypes: ["address", "string", "address"],
                parameters: [targetAddress, method, callerAddress],
                value: 0,
            },
        ];
    })));
    return commands.flat();
});
const executeCommands = (target, hre, deployer, omnichainProposalSenderAddress, chainId, normalTimelockAddress, fastTrackTimelockAddress, criticalTimelockAddress) => __awaiter(void 0, void 0, void 0, function* () {
    const signer = yield hardhat_1.ethers.getSigner(deployer);
    const networkName = hre.network.name;
    console.log("Executing commands");
    const methods = deploymentConfig_1.config[networkName].methods;
    for (let i = 0; i < methods.length; i++) {
        const entry = methods[i];
        const { method, args } = entry;
        const data = target.interface.encodeFunctionData(method, args);
        yield signer.sendTransaction({
            to: target.address,
            data: data,
        });
    }
    let tx = yield target.connect(signer).setTrustedRemoteAddress(chainId, omnichainProposalSenderAddress);
    yield tx.wait();
    tx = yield target
        .connect(signer)
        .addTimelocks([normalTimelockAddress, fastTrackTimelockAddress, criticalTimelockAddress]);
    yield tx.wait();
});
const func = function (hre) {
    return __awaiter(this, void 0, void 0, function* () {
        const srcChainId = deploymentUtils_1.testnetNetworks.includes(hre.network.name) ? constants_1.LZ_CHAINID["bsctestnet"] : constants_1.LZ_CHAINID["bscmainnet"];
        const Guardian = yield (0, deploymentUtils_1.guardian)(hre.network.name);
        const { deployments, getNamedAccounts } = hre;
        const { deploy } = deployments;
        const { deployer } = yield getNamedAccounts();
        const networkName = hre.network.name;
        const acmAddress = (yield hardhat_1.ethers.getContract("AccessControlManager")).address;
        const normalTimelockAddress = (yield hardhat_1.ethers.getContract("NormalTimelock")).address;
        const fastTrackTimelockAddress = (yield hardhat_1.ethers.getContract("FastTrackTimelock")).address;
        const criticalTimelockAddress = (yield hardhat_1.ethers.getContract("CriticalTimelock")).address;
        const defaultProxyAdmin = yield hre.artifacts.readArtifact("hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin");
        const normalTimelock = yield hardhat_1.ethers.getContract("NormalTimelock");
        const omnichainGovernanceExecutorAddress = (yield hardhat_1.ethers.getContract("OmnichainGovernanceExecutor")).address;
        const OmnichainExecutorOwner = yield deploy("OmnichainExecutorOwner", {
            from: deployer,
            args: [omnichainGovernanceExecutorAddress],
            contract: "OmnichainExecutorOwner",
            proxy: {
                owner: hre.network.live ? normalTimelock.address : deployer,
                proxyContract: "OptimizedTransparentUpgradeableProxy",
                execute: {
                    methodName: "initialize",
                    args: [acmAddress],
                },
                viaAdminContract: {
                    name: "DefaultProxyAdmin",
                    artifact: defaultProxyAdmin,
                },
                upgradeIndex: 0,
            },
            log: true,
            autoMine: true,
            skipIfAlreadyDeployed: true,
        });
        const omnichainExecutorOwner = yield hardhat_1.ethers.getContractAt("OmnichainExecutorOwner", OmnichainExecutorOwner.address, hardhat_1.ethers.provider.getSigner(deployer));
        const omnichainGovernanceExecutor = yield hardhat_1.ethers.getContractAt("OmnichainGovernanceExecutor", omnichainGovernanceExecutorAddress, hardhat_1.ethers.provider.getSigner(deployer));
        if ((yield omnichainGovernanceExecutor.owner()) === deployer) {
            const omnichainProposalSenderAddress = yield (0, deploymentUtils_1.getOmnichainProposalSender)(networkName);
            yield executeCommands(omnichainGovernanceExecutor, hre, deployer, omnichainProposalSenderAddress, srcChainId, normalTimelockAddress, fastTrackTimelockAddress, criticalTimelockAddress);
            const tx = yield omnichainGovernanceExecutor.transferOwnership(OmnichainExecutorOwner.address);
            yield tx.wait();
        }
        if ((yield omnichainExecutorOwner.owner()) === deployer) {
            let isAdded = new Array(deploymentConfig_1.OmnichainGovernanceExecutorNormalMethods.length).fill(true);
            let tx = yield omnichainExecutorOwner.upsertSignature(deploymentConfig_1.OmnichainGovernanceExecutorNormalMethods, isAdded);
            isAdded = new Array(deploymentConfig_1.OmnichainGovernanceExecutorMethodsForGuardian.length).fill(true);
            tx = yield omnichainExecutorOwner.upsertSignature(deploymentConfig_1.OmnichainGovernanceExecutorMethodsForGuardian, isAdded);
            yield tx.wait();
            tx = yield omnichainExecutorOwner.transferOwnership(normalTimelockAddress);
            yield tx.wait();
            console.log(`Omnichain Executor Owner ${deployer} successfully changed to ${normalTimelockAddress}.`);
        }
        const commands = [
            ...(yield configureAccessControls(deploymentConfig_1.OmnichainGovernanceExecutorNormalMethods, acmAddress, normalTimelockAddress, OmnichainExecutorOwner.address)),
            ...(yield configureAccessControls(deploymentConfig_1.OmnichainGovernanceExecutorFasttrackMethods, acmAddress, fastTrackTimelockAddress, OmnichainExecutorOwner.address)),
            ...(yield configureAccessControls(deploymentConfig_1.OmnichainGovernanceExecutorCriticalMethods, acmAddress, criticalTimelockAddress, OmnichainExecutorOwner.address)),
            ...(yield configureAccessControls(deploymentConfig_1.OmnichainGovernanceExecutorMethodsForGuardian, acmAddress, Guardian, OmnichainExecutorOwner.address)),
            ...(yield configureAccessControls(deploymentConfig_1.OmnichainGovernanceExecutorOwnerMethods, acmAddress, Guardian, OmnichainExecutorOwner.address)),
            ...(yield configureAccessControls(deploymentConfig_1.OmnichainGovernanceExecutorOwnerMethods, acmAddress, normalTimelockAddress, OmnichainExecutorOwner.address)),
            {
                contract: omnichainExecutorOwner.address,
                signature: "acceptOwnership()",
                parameters: [],
                value: 0,
            },
        ];
        console.log("Please propose a VIP with the following commands:");
        console.log(JSON.stringify(commands.map(c => ({ target: c.contract, signature: c.signature, params: c.parameters, value: c.value }))));
    });
};
func.tags = ["OmnichainExecutorOwner", "Remote"];
func.id = "configure_remote_executor";
func.skip = (hre) => __awaiter(void 0, void 0, void 0, function* () { return hre.network.name === "bsctestnet" || hre.network.name === "bscmainnet"; });
exports.default = func;
//# sourceMappingURL=006-omnichain-executorOwner-remote.js.map