"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("../constants");
const utils_1 = require("../../../../utils/utils");
const utils_hre_1 = require("../../../../utils/utils.hre");
const HubPool_Fixture_1 = require("../fixtures/HubPool.Fixture");
const MerkleLib_utils_1 = require("../MerkleLib.utils");
let hubPool, spokePool, dai, weth;
let owner, relayer, rando;
describe("Ethereum Spoke Pool", function () {
    beforeEach(async function () {
        [owner, relayer, rando] = await utils_1.ethers.getSigners();
        ({ weth, dai, hubPool } = await (0, HubPool_Fixture_1.hubPoolFixture)());
        spokePool = await utils_hre_1.hre.upgrades.deployProxy(await (0, utils_1.getContractFactory)("Ethereum_SpokePool", owner), [0, hubPool.address], { kind: "uups", unsafeAllow: ["delegatecall"], constructorArgs: [weth.address, 60 * 60, 9 * 60 * 60] });
        // Seed spoke pool with tokens that it should transfer to the hub pool
        // via the _bridgeTokensToHubPool() internal call.
        await (0, utils_1.seedContract)(spokePool, relayer, [dai], weth, constants_1.amountHeldByPool);
    });
    it("Only cross domain owner upgrade logic contract", async function () {
        // TODO: Could also use upgrades.prepareUpgrade but I'm unclear of differences
        const implementation = await utils_hre_1.hre.upgrades.deployImplementation(await (0, utils_1.getContractFactory)("Ethereum_SpokePool", owner), { kind: "uups", unsafeAllow: ["delegatecall"], constructorArgs: [weth.address, 60 * 60, 9 * 60 * 60] });
        // upgradeTo fails unless called by cross domain admin
        await (0, utils_1.expect)(spokePool.connect(rando).upgradeTo(implementation)).to.be.revertedWith("Ownable: caller is not the owner");
        await spokePool.connect(owner).upgradeTo(implementation);
    });
    it("Only owner can set the cross domain admin", async function () {
        await (0, utils_1.expect)(spokePool.connect(rando).setCrossDomainAdmin(rando.address)).to.be.reverted;
        await spokePool.connect(owner).setCrossDomainAdmin(rando.address);
        (0, utils_1.expect)(await spokePool.crossDomainAdmin()).to.equal(rando.address);
    });
    it("Only owner can enable a route", async function () {
        await (0, utils_1.expect)(spokePool.connect(rando).setEnableRoute(dai.address, 1, true)).to.be.reverted;
        await spokePool.connect(owner).setEnableRoute(dai.address, 1, true);
        (0, utils_1.expect)(await spokePool.enabledDepositRoutes(dai.address, 1)).to.equal(true);
    });
    it("Only owner can set the hub pool address", async function () {
        await (0, utils_1.expect)(spokePool.connect(rando).setWithdrawalRecipient(rando.address)).to.be.reverted;
        await spokePool.connect(owner).setWithdrawalRecipient(rando.address);
        (0, utils_1.expect)(await spokePool.withdrawalRecipient()).to.equal(rando.address);
    });
    it("Only owner can initialize a relayer refund", async function () {
        await (0, utils_1.expect)(spokePool.connect(rando).relayRootBundle(constants_1.mockTreeRoot, constants_1.mockTreeRoot)).to.be.reverted;
        await spokePool.connect(owner).relayRootBundle(constants_1.mockTreeRoot, constants_1.mockTreeRoot);
        (0, utils_1.expect)((await spokePool.rootBundles(0)).slowRelayRoot).to.equal(constants_1.mockTreeRoot);
        (0, utils_1.expect)((await spokePool.rootBundles(0)).relayerRefundRoot).to.equal(constants_1.mockTreeRoot);
    });
    it("Only owner can delete a relayer refund", async function () {
        await spokePool.connect(owner).relayRootBundle(constants_1.mockTreeRoot, constants_1.mockTreeRoot);
        await (0, utils_1.expect)(spokePool.connect(rando).emergencyDeleteRootBundle(0)).to.be.reverted;
        await (0, utils_1.expect)(spokePool.connect(owner).emergencyDeleteRootBundle(0)).to.not.be.reverted;
        (0, utils_1.expect)((await spokePool.rootBundles(0)).slowRelayRoot).to.equal(utils_1.ethers.utils.hexZeroPad("0x0", 32));
        (0, utils_1.expect)((await spokePool.rootBundles(0)).relayerRefundRoot).to.equal(utils_1.ethers.utils.hexZeroPad("0x0", 32));
    });
    it("Bridge tokens to hub pool correctly sends tokens to hub pool", async function () {
        const { leaves, tree } = await (0, MerkleLib_utils_1.constructSingleRelayerRefundTree)(dai.address, await spokePool.callStatic.chainId());
        await spokePool.connect(owner).relayRootBundle(tree.getHexRoot(), constants_1.mockTreeRoot);
        await (0, utils_1.expect)(() => spokePool.connect(relayer).executeRelayerRefundLeaf(0, leaves[0], tree.getHexProof(leaves[0]))).to.changeTokenBalances(dai, [spokePool, hubPool], [constants_1.amountToReturn.mul(-1), constants_1.amountToReturn]);
    });
});
