You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
13 KiB
414 lines
13 KiB
3 years ago
|
import { ethers, abacus } from 'hardhat';
|
||
3 years ago
|
import { expect } from 'chai';
|
||
|
|
||
3 years ago
|
import { updateReplica, formatCall, formatAbacusMessage } from './utils';
|
||
3 years ago
|
import { increaseTimestampBy, UpgradeTestHelpers } from '../utils';
|
||
3 years ago
|
import { Updater } from '../lib/core';
|
||
|
import { Address, Signer } from '../lib/types';
|
||
|
import { AbacusDeployment } from '../lib/AbacusDeployment';
|
||
|
import { GovernanceDeployment } from '../lib/GovernanceDeployment';
|
||
3 years ago
|
import {
|
||
3 years ago
|
MysteryMathV2__factory,
|
||
|
TestReplica,
|
||
|
TestReplica__factory,
|
||
|
TestRecipient__factory,
|
||
|
TestGovernanceRouter,
|
||
|
Replica,
|
||
|
Home,
|
||
|
} from '../../typechain';
|
||
3 years ago
|
|
||
|
const helpers = require('../../../../vectors/proof.json');
|
||
|
|
||
|
const governorDomain = 1000;
|
||
|
const nonGovernorDomain = 2000;
|
||
|
const thirdDomain = 3000;
|
||
3 years ago
|
const domains = [governorDomain, nonGovernorDomain, thirdDomain];
|
||
|
const processGas = 850000;
|
||
|
const reserveGas = 15000;
|
||
4 years ago
|
|
||
|
/*
|
||
3 years ago
|
* Deploy the full Abacus suite on two chains
|
||
4 years ago
|
*/
|
||
|
describe('GovernanceRouter', async () => {
|
||
3 years ago
|
let abacusDeployment: AbacusDeployment;
|
||
|
let governanceDeployment: GovernanceDeployment;
|
||
3 years ago
|
let signer: Signer,
|
||
3 years ago
|
secondSigner: Signer,
|
||
3 years ago
|
thirdRouter: Signer,
|
||
|
firstGovernor: Address,
|
||
|
secondGovernor: Address,
|
||
3 years ago
|
governorRouter: TestGovernanceRouter,
|
||
|
nonGovernorRouter: TestGovernanceRouter,
|
||
|
governorHome: Home,
|
||
|
governorReplicaOnNonGovernorChain: TestReplica,
|
||
|
nonGovernorReplicaOnGovernorChain: TestReplica,
|
||
3 years ago
|
updater: Updater;
|
||
4 years ago
|
|
||
|
async function expectGovernor(
|
||
3 years ago
|
governanceRouter: TestGovernanceRouter,
|
||
3 years ago
|
expectedGovernorDomain: number,
|
||
|
expectedGovernor: Address,
|
||
4 years ago
|
) {
|
||
|
expect(await governanceRouter.governorDomain()).to.equal(
|
||
|
expectedGovernorDomain,
|
||
|
);
|
||
|
expect(await governanceRouter.governor()).to.equal(expectedGovernor);
|
||
|
}
|
||
|
|
||
3 years ago
|
before(async () => {
|
||
3 years ago
|
[thirdRouter, signer, secondSigner] = await ethers.getSigners();
|
||
3 years ago
|
updater = await Updater.fromSigner(signer, governorDomain);
|
||
|
});
|
||
4 years ago
|
|
||
3 years ago
|
beforeEach(async () => {
|
||
3 years ago
|
abacusDeployment = await abacus.deployment.fromDomains(domains, signer);
|
||
|
governanceDeployment = await GovernanceDeployment.fromAbacusDeployment(
|
||
|
abacusDeployment,
|
||
|
signer,
|
||
|
);
|
||
|
|
||
|
firstGovernor = await signer.getAddress();
|
||
|
secondGovernor = await secondSigner.getAddress();
|
||
|
|
||
|
governorRouter = governanceDeployment.router(governorDomain);
|
||
|
nonGovernorRouter = governanceDeployment.router(nonGovernorDomain);
|
||
|
|
||
|
governorReplicaOnNonGovernorChain = abacusDeployment.replica(
|
||
|
nonGovernorDomain,
|
||
|
governorDomain,
|
||
|
);
|
||
|
nonGovernorReplicaOnGovernorChain = abacusDeployment.replica(
|
||
|
governorDomain,
|
||
|
nonGovernorDomain,
|
||
|
);
|
||
|
|
||
|
governorHome = abacusDeployment.home(governorDomain);
|
||
3 years ago
|
});
|
||
|
|
||
|
// NB: must be first test for message proof
|
||
|
it('Sends cross-chain message to upgrade contract', async () => {
|
||
|
const upgradeUtils = new UpgradeTestHelpers();
|
||
|
|
||
|
// get upgradeBeaconController
|
||
3 years ago
|
const ubc = abacusDeployment.ubc(nonGovernorDomain);
|
||
|
// Transfer ownership of the UBC to governance.
|
||
|
await ubc.transferOwnership(nonGovernorRouter.address);
|
||
3 years ago
|
const mysteryMath = await upgradeUtils.deployMysteryMathUpgradeSetup(
|
||
|
signer,
|
||
3 years ago
|
ubc,
|
||
3 years ago
|
);
|
||
|
|
||
|
// expect results before upgrade
|
||
|
await upgradeUtils.expectMysteryMathV1(mysteryMath.proxy);
|
||
|
|
||
|
// Deploy Implementation 2
|
||
3 years ago
|
const factory2 = new MysteryMathV2__factory(signer);
|
||
3 years ago
|
const implementation2 = await factory2.deploy();
|
||
|
|
||
3 years ago
|
// Format abacus call message
|
||
3 years ago
|
const call = await formatCall(ubc, 'upgrade', [
|
||
3 years ago
|
mysteryMath.beacon.address,
|
||
|
implementation2.address,
|
||
|
]);
|
||
|
|
||
|
// dispatch call on local governorRouter
|
||
|
let tx = await governorRouter.callRemote(nonGovernorDomain, [call]);
|
||
|
|
||
3 years ago
|
await abacusDeployment.processMessages();
|
||
3 years ago
|
// test implementation was upgraded
|
||
|
await upgradeUtils.expectMysteryMathV2(mysteryMath.proxy);
|
||
4 years ago
|
});
|
||
|
|
||
|
it('Rejects message from unenrolled replica', async () => {
|
||
3 years ago
|
const replicaFactory = new TestReplica__factory(signer);
|
||
|
const unenrolledReplica = await replicaFactory.deploy(
|
||
|
nonGovernorDomain,
|
||
|
processGas,
|
||
|
reserveGas,
|
||
|
);
|
||
|
await unenrolledReplica.initialize(
|
||
|
thirdDomain,
|
||
|
await signer.getAddress(),
|
||
|
ethers.constants.HashZero,
|
||
|
0,
|
||
|
);
|
||
4 years ago
|
|
||
|
// Create TransferGovernor message
|
||
3 years ago
|
const transferGovernorMessage = abacus.governance.formatTransferGovernor(
|
||
3 years ago
|
thirdDomain,
|
||
3 years ago
|
abacus.ethersAddressToBytes32(secondGovernor),
|
||
3 years ago
|
);
|
||
4 years ago
|
|
||
3 years ago
|
const abacusMessage = await formatAbacusMessage(
|
||
4 years ago
|
unenrolledReplica,
|
||
|
governorRouter,
|
||
|
nonGovernorRouter,
|
||
|
transferGovernorMessage,
|
||
|
);
|
||
|
|
||
3 years ago
|
// Expect replica processing to fail when nonGovernorRouter reverts in handle
|
||
3 years ago
|
let success = await unenrolledReplica.callStatic.testProcess(abacusMessage);
|
||
4 years ago
|
expect(success).to.be.false;
|
||
|
});
|
||
|
|
||
|
it('Rejects message not from governor router', async () => {
|
||
|
// Create TransferGovernor message
|
||
3 years ago
|
const transferGovernorMessage = abacus.governance.formatTransferGovernor(
|
||
3 years ago
|
nonGovernorDomain,
|
||
3 years ago
|
abacus.ethersAddressToBytes32(nonGovernorRouter.address),
|
||
3 years ago
|
);
|
||
4 years ago
|
|
||
3 years ago
|
const abacusMessage = await formatAbacusMessage(
|
||
4 years ago
|
governorReplicaOnNonGovernorChain,
|
||
|
nonGovernorRouter,
|
||
|
governorRouter,
|
||
|
transferGovernorMessage,
|
||
|
);
|
||
|
|
||
3 years ago
|
// Set message status to MessageStatus.Proven
|
||
|
await nonGovernorReplicaOnGovernorChain.setMessageProven(abacusMessage);
|
||
4 years ago
|
|
||
3 years ago
|
// Expect replica processing to fail when nonGovernorRouter reverts in handle
|
||
3 years ago
|
let success =
|
||
|
await nonGovernorReplicaOnGovernorChain.callStatic.testProcess(
|
||
3 years ago
|
abacusMessage,
|
||
3 years ago
|
);
|
||
4 years ago
|
expect(success).to.be.false;
|
||
|
});
|
||
|
|
||
|
it('Accepts a valid transfer governor message', async () => {
|
||
|
// Enroll router for new domain (in real setting this would
|
||
3 years ago
|
// be executed with an Abacus message sent to the nonGovernorRouter)
|
||
4 years ago
|
await nonGovernorRouter.testSetRouter(
|
||
|
thirdDomain,
|
||
3 years ago
|
abacus.ethersAddressToBytes32(thirdRouter.address),
|
||
4 years ago
|
);
|
||
|
|
||
|
// Create TransferGovernor message
|
||
3 years ago
|
const transferGovernorMessage = abacus.governance.formatTransferGovernor(
|
||
3 years ago
|
thirdDomain,
|
||
3 years ago
|
abacus.ethersAddressToBytes32(thirdRouter.address),
|
||
3 years ago
|
);
|
||
4 years ago
|
|
||
3 years ago
|
const abacusMessage = await formatAbacusMessage(
|
||
4 years ago
|
governorReplicaOnNonGovernorChain,
|
||
|
governorRouter,
|
||
|
nonGovernorRouter,
|
||
|
transferGovernorMessage,
|
||
|
);
|
||
|
|
||
|
// Expect successful tx on static call
|
||
4 years ago
|
let success = await governorReplicaOnNonGovernorChain.callStatic.process(
|
||
3 years ago
|
abacusMessage,
|
||
4 years ago
|
);
|
||
|
expect(success).to.be.true;
|
||
|
|
||
3 years ago
|
await governorReplicaOnNonGovernorChain.process(abacusMessage);
|
||
4 years ago
|
await expectGovernor(
|
||
|
nonGovernorRouter,
|
||
|
thirdDomain,
|
||
|
ethers.constants.AddressZero,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('Accepts valid set router message', async () => {
|
||
|
// Create address for router to enroll and domain for router
|
||
3 years ago
|
const [router] = await ethers.getSigners();
|
||
4 years ago
|
|
||
|
// Create SetRouter message
|
||
3 years ago
|
const setRouterMessage = abacus.governance.formatSetRouter(
|
||
4 years ago
|
thirdDomain,
|
||
3 years ago
|
abacus.ethersAddressToBytes32(router.address),
|
||
4 years ago
|
);
|
||
|
|
||
3 years ago
|
const abacusMessage = await formatAbacusMessage(
|
||
4 years ago
|
governorReplicaOnNonGovernorChain,
|
||
|
governorRouter,
|
||
|
nonGovernorRouter,
|
||
|
setRouterMessage,
|
||
|
);
|
||
|
|
||
|
// Expect successful tx
|
||
4 years ago
|
let success = await governorReplicaOnNonGovernorChain.callStatic.process(
|
||
3 years ago
|
abacusMessage,
|
||
4 years ago
|
);
|
||
|
expect(success).to.be.true;
|
||
|
|
||
|
// Expect new router to be registered for domain and for new domain to be
|
||
|
// in domains array
|
||
3 years ago
|
await governorReplicaOnNonGovernorChain.process(abacusMessage);
|
||
4 years ago
|
expect(await nonGovernorRouter.routers(thirdDomain)).to.equal(
|
||
3 years ago
|
abacus.ethersAddressToBytes32(router.address),
|
||
4 years ago
|
);
|
||
|
expect(await nonGovernorRouter.containsDomain(thirdDomain)).to.be.true;
|
||
|
});
|
||
|
|
||
|
it('Accepts valid call messages', async () => {
|
||
3 years ago
|
// const TestRecipient = await abacus.deployImplementation('TestRecipient');
|
||
3 years ago
|
const testRecipientFactory = new TestRecipient__factory(signer);
|
||
|
const testRecipient = await testRecipientFactory.deploy();
|
||
4 years ago
|
|
||
3 years ago
|
// Format abacus call message
|
||
4 years ago
|
const arg = 'String!';
|
||
3 years ago
|
const call = await formatCall(testRecipient, 'receiveString', [arg]);
|
||
4 years ago
|
|
||
4 years ago
|
// Create Call message to test recipient that calls receiveString
|
||
3 years ago
|
const callMessage = abacus.governance.formatCalls([call, call]);
|
||
4 years ago
|
|
||
3 years ago
|
const abacusMessage = await formatAbacusMessage(
|
||
4 years ago
|
governorReplicaOnNonGovernorChain,
|
||
|
governorRouter,
|
||
|
nonGovernorRouter,
|
||
|
callMessage,
|
||
|
);
|
||
|
|
||
|
// Expect successful tx
|
||
3 years ago
|
let success =
|
||
|
await governorReplicaOnNonGovernorChain.callStatic.testProcess(
|
||
3 years ago
|
abacusMessage,
|
||
3 years ago
|
);
|
||
4 years ago
|
|
||
4 years ago
|
expect(success).to.be.true;
|
||
|
});
|
||
|
|
||
|
it('Transfers governorship', async () => {
|
||
|
// Transfer governor on current governor chain
|
||
|
// get root on governor chain before transferring governor
|
||
3 years ago
|
const committedRoot = await governorHome.committedRoot();
|
||
4 years ago
|
|
||
|
// Governor HAS NOT been transferred on original governor domain
|
||
|
await expectGovernor(governorRouter, governorDomain, firstGovernor);
|
||
|
// Governor HAS NOT been transferred on original non-governor domain
|
||
|
await expectGovernor(
|
||
|
nonGovernorRouter,
|
||
|
governorDomain,
|
||
|
ethers.constants.AddressZero,
|
||
|
);
|
||
|
|
||
|
// transfer governorship to nonGovernorRouter
|
||
|
await governorRouter.transferGovernor(nonGovernorDomain, secondGovernor);
|
||
|
|
||
|
// Governor HAS been transferred on original governor domain
|
||
|
await expectGovernor(
|
||
|
governorRouter,
|
||
|
nonGovernorDomain,
|
||
|
ethers.constants.AddressZero,
|
||
|
);
|
||
|
// Governor HAS NOT been transferred on original non-governor domain
|
||
|
await expectGovernor(
|
||
|
nonGovernorRouter,
|
||
|
governorDomain,
|
||
|
ethers.constants.AddressZero,
|
||
|
);
|
||
|
|
||
|
// get new root and signed update
|
||
|
const newRoot = await governorHome.queueEnd();
|
||
3 years ago
|
|
||
3 years ago
|
const { signature } = await updater.signUpdate(committedRoot, newRoot);
|
||
4 years ago
|
|
||
|
// update governor chain home
|
||
3 years ago
|
await governorHome.update(committedRoot, newRoot, signature);
|
||
4 years ago
|
|
||
3 years ago
|
const transferGovernorMessage = abacus.governance.formatTransferGovernor(
|
||
3 years ago
|
nonGovernorDomain,
|
||
3 years ago
|
abacus.ethersAddressToBytes32(secondGovernor),
|
||
3 years ago
|
);
|
||
4 years ago
|
|
||
3 years ago
|
const abacusMessage = await formatAbacusMessage(
|
||
4 years ago
|
governorReplicaOnNonGovernorChain,
|
||
|
governorRouter,
|
||
|
nonGovernorRouter,
|
||
|
transferGovernorMessage,
|
||
|
);
|
||
|
|
||
|
// Set current root on replica
|
||
3 years ago
|
await governorReplicaOnNonGovernorChain.setCommittedRoot(newRoot);
|
||
4 years ago
|
|
||
|
// Governor HAS been transferred on original governor domain
|
||
|
await expectGovernor(
|
||
|
governorRouter,
|
||
|
nonGovernorDomain,
|
||
|
ethers.constants.AddressZero,
|
||
|
);
|
||
|
// Governor HAS NOT been transferred on original non-governor domain
|
||
|
await expectGovernor(
|
||
|
nonGovernorRouter,
|
||
|
governorDomain,
|
||
|
ethers.constants.AddressZero,
|
||
|
);
|
||
|
|
||
|
// Process transfer governor message on Replica
|
||
3 years ago
|
await governorReplicaOnNonGovernorChain.process(abacusMessage);
|
||
4 years ago
|
|
||
|
// Governor HAS been transferred on original governor domain
|
||
|
await expectGovernor(
|
||
|
governorRouter,
|
||
|
nonGovernorDomain,
|
||
|
ethers.constants.AddressZero,
|
||
|
);
|
||
|
// Governor HAS been transferred on original non-governor domain
|
||
|
await expectGovernor(nonGovernorRouter, nonGovernorDomain, secondGovernor);
|
||
|
});
|
||
4 years ago
|
|
||
|
it('Upgrades using GovernanceRouter call', async () => {
|
||
3 years ago
|
const upgradeUtils = new UpgradeTestHelpers();
|
||
4 years ago
|
|
||
3 years ago
|
// get upgradeBeaconController
|
||
|
const ubc = abacusDeployment.ubc(governorDomain);
|
||
|
// Transfer ownership of the UBC to governance.
|
||
|
await ubc.transferOwnership(governorRouter.address);
|
||
3 years ago
|
const mysteryMath = await upgradeUtils.deployMysteryMathUpgradeSetup(
|
||
|
signer,
|
||
3 years ago
|
ubc,
|
||
4 years ago
|
);
|
||
|
|
||
|
// expect results before upgrade
|
||
3 years ago
|
await upgradeUtils.expectMysteryMathV1(mysteryMath.proxy);
|
||
4 years ago
|
|
||
|
// Deploy Implementation 2
|
||
3 years ago
|
const v2Factory = new MysteryMathV2__factory(signer);
|
||
3 years ago
|
const implementation = await v2Factory.deploy();
|
||
4 years ago
|
|
||
3 years ago
|
// Format abacus call message
|
||
3 years ago
|
const call = await formatCall(ubc, 'upgrade', [
|
||
3 years ago
|
mysteryMath.beacon.address,
|
||
4 years ago
|
implementation.address,
|
||
|
]);
|
||
|
|
||
|
// dispatch call on local governorRouter
|
||
|
await expect(governorRouter.callLocal([call])).to.emit(
|
||
3 years ago
|
ubc,
|
||
4 years ago
|
'BeaconUpgraded',
|
||
|
);
|
||
|
|
||
|
// test implementation was upgraded
|
||
3 years ago
|
await upgradeUtils.expectMysteryMathV2(mysteryMath.proxy);
|
||
4 years ago
|
});
|
||
|
|
||
|
it('Calls UpdaterManager to change the Updater on Home', async () => {
|
||
3 years ago
|
const [newUpdater] = await ethers.getSigners();
|
||
3 years ago
|
const updaterManager = abacusDeployment.updaterManager(governorDomain);
|
||
|
await updaterManager.transferOwnership(governorRouter.address);
|
||
4 years ago
|
|
||
|
// check current Updater address on Home
|
||
|
let currentUpdaterAddr = await governorHome.updater();
|
||
3 years ago
|
expect(currentUpdaterAddr).to.equal(
|
||
|
await abacusDeployment.updater(governorDomain).signer.getAddress(),
|
||
|
);
|
||
4 years ago
|
|
||
3 years ago
|
// format abacus call message
|
||
4 years ago
|
const call = await formatCall(updaterManager, 'setUpdater', [
|
||
|
newUpdater.address,
|
||
|
]);
|
||
|
|
||
|
await expect(governorRouter.callLocal([call])).to.emit(
|
||
|
governorHome,
|
||
|
'NewUpdater',
|
||
|
);
|
||
|
|
||
|
// check for new updater
|
||
|
currentUpdaterAddr = await governorHome.updater();
|
||
|
expect(currentUpdaterAddr).to.equal(newUpdater.address);
|
||
|
});
|
||
4 years ago
|
});
|