Rename Governance to Controller (#426)

* Rename Governance to Controller

* prettier
pull/434/head
Nam Chu Hoai 3 years ago committed by GitHub
parent 0ac724aa7b
commit c7038ab42a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      solidity/apps/contracts/controller/ControllerMessage.sol
  2. 116
      solidity/apps/contracts/controller/ControllerRouter.sol
  3. 0
      solidity/apps/contracts/controller/test/TestSet.sol
  4. 179
      solidity/apps/test/controller/controller.test.ts
  5. 26
      solidity/apps/test/controller/lib/ControllerDeploy.ts
  6. 14
      solidity/apps/test/controller/lib/utils.ts
  7. 20
      typescript/infra/config/environments/dev/controller.ts
  8. 20
      typescript/infra/config/environments/dev/governance.ts
  9. 4
      typescript/infra/config/environments/dev/index.ts
  10. 21
      typescript/infra/config/environments/test/controller.ts
  11. 21
      typescript/infra/config/environments/test/governance.ts
  12. 4
      typescript/infra/config/environments/test/index.ts
  13. 24
      typescript/infra/config/environments/testnet/controller.ts
  14. 24
      typescript/infra/config/environments/testnet/governance.ts
  15. 4
      typescript/infra/config/environments/testnet/index.ts
  16. 23
      typescript/infra/scripts/check-deploy.ts
  17. 14
      typescript/infra/scripts/deploy-controller.ts
  18. 22
      typescript/infra/scripts/set-validator.ts
  19. 12
      typescript/infra/scripts/utils.ts
  20. 4
      typescript/infra/src/config/environment.ts
  21. 20
      typescript/infra/src/controller/check.ts
  22. 28
      typescript/infra/src/controller/deploy.ts
  23. 3
      typescript/infra/src/controller/index.ts
  24. 10
      typescript/infra/src/controller/types.ts
  25. 16
      typescript/infra/src/core/control.ts
  26. 2
      typescript/infra/src/core/index.ts
  27. 3
      typescript/infra/src/governance/index.ts
  28. 10
      typescript/infra/src/governance/types.ts
  29. 38
      typescript/infra/test/controller.test.ts
  30. 48
      typescript/sdk/src/controller/app.ts
  31. 20
      typescript/sdk/src/controller/contracts.ts
  32. 0
      typescript/sdk/src/controller/environments/index.ts
  33. 0
      typescript/sdk/src/controller/environments/test.ts
  34. 4
      typescript/sdk/src/controller/index.ts
  35. 2
      typescript/sdk/src/controller/utils.ts
  36. 4
      typescript/sdk/src/governance/index.ts
  37. 10
      typescript/sdk/src/index.ts

@ -5,7 +5,7 @@ pragma experimental ABIEncoderV2;
// ============ External Imports ============
import {TypedMemView} from "@summa-tx/memview-sol/contracts/TypedMemView.sol";
library GovernanceMessage {
library ControllerMessage {
using TypedMemView for bytes;
using TypedMemView for bytes29;
@ -18,7 +18,7 @@ library GovernanceMessage {
enum Types {
Invalid, // 0
Call, // 1
SetGovernor, // 2
SetController, // 2
EnrollRemoteRouter, // 3
Data, // 4
SetAbacusConnectionManager // 5
@ -68,14 +68,14 @@ library GovernanceMessage {
_msg = TypedMemView.join(_encodedCalls);
}
function formatSetGovernor(bytes32 _governor)
function formatSetController(bytes32 _controller)
internal
view
returns (bytes memory _msg)
{
_msg = TypedMemView.clone(
mustBeSetGovernor(
abi.encodePacked(Types.SetGovernor, _governor).ref(0)
mustBeSetController(
abi.encodePacked(Types.SetController, _controller).ref(0)
)
);
}
@ -183,8 +183,8 @@ library GovernanceMessage {
return _view.index(5, 32);
}
// Types.SetGovernor
function governor(bytes29 _view) internal pure returns (bytes32) {
// Types.SetController
function controller(bytes29 _view) internal pure returns (bytes32) {
return _view.index(1, 32);
}
@ -232,34 +232,38 @@ library GovernanceMessage {
}
/*
Message Type: SET GOVERNOR
struct SetGovernor {
Message Type: SET CONTROLLER
struct SetController {
identifier, // message ID -- 1 byte
addr // address of new governor -- 32 bytes
addr // address of new controller -- 32 bytes
}
*/
function isValidSetGovernor(bytes29 _view) internal pure returns (bool) {
function isValidSetController(bytes29 _view) internal pure returns (bool) {
return
identifier(_view) == uint8(Types.SetGovernor) &&
identifier(_view) == uint8(Types.SetController) &&
_view.len() == SET_ADDRESS_LEN;
}
function isSetGovernor(bytes29 _view) internal pure returns (bool) {
function isSetController(bytes29 _view) internal pure returns (bool) {
return
isValidSetGovernor(_view) &&
messageType(_view) == Types.SetGovernor;
isValidSetController(_view) &&
messageType(_view) == Types.SetController;
}
function tryAsSetGovernor(bytes29 _view) internal pure returns (bytes29) {
if (isValidSetGovernor(_view)) {
return _view.castTo(uint40(Types.SetGovernor));
function tryAsSetController(bytes29 _view) internal pure returns (bytes29) {
if (isValidSetController(_view)) {
return _view.castTo(uint40(Types.SetController));
}
return TypedMemView.nullView();
}
function mustBeSetGovernor(bytes29 _view) internal pure returns (bytes29) {
return tryAsSetGovernor(_view).assertValid();
function mustBeSetController(bytes29 _view)
internal
pure
returns (bytes29)
{
return tryAsSetController(_view).assertValid();
}
/*

@ -3,7 +3,7 @@ pragma solidity >=0.6.11;
pragma experimental ABIEncoderV2;
// ============ Internal Imports ============
import {GovernanceMessage} from "./GovernanceMessage.sol";
import {ControllerMessage} from "./ControllerMessage.sol";
// ============ External Imports ============
import {Router} from "@abacus-network/app/contracts/Router.sol";
import {Version0} from "@abacus-network/core/contracts/Version0.sol";
@ -14,19 +14,19 @@ import {TypedMemView} from "@summa-tx/memview-sol/contracts/TypedMemView.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
/**
* @dev GovernanceRouter has two modes of operation, normal and recovery.
* During normal mode, `owner()` returns the `governor`, giving it permission
* @dev ControllerRouter has two modes of operation, normal and recovery.
* During normal mode, `owner()` returns the `controller`, giving it permission
* to call `onlyOwner` functions.
* During recovery mode, `owner()` returns the `_owner`, giving it permission
* to call `onlyOwner` functions.
*/
contract GovernanceRouter is Version0, Router {
contract ControllerRouter is Version0, Router {
// ============ Libraries ============
using SafeMath for uint256;
using TypedMemView for bytes;
using TypedMemView for bytes29;
using GovernanceMessage for bytes29;
using ControllerMessage for bytes29;
// ============ Immutables ============
@ -37,9 +37,9 @@ contract GovernanceRouter is Version0, Router {
// timestamp when recovery timelock expires; 0 if timelock has not been initiated
uint256 public recoveryActiveAt;
// the local entity empowered to call governance functions during normal
// the local entity empowered to call permissioned functions during normal
// operation, typically set to 0x0 on all chains but one
address public governor;
address public controller;
// ============ Upgrade Gap ============
@ -49,10 +49,10 @@ contract GovernanceRouter is Version0, Router {
// ============ Events ============
/**
* @notice Emitted when the Governor role is set
* @param governor the address of the new Governor
* @notice Emitted when the controller role is set
* @param controller the address of the new controller
*/
event SetGovernor(address indexed governor);
event SetController(address indexed controller);
/**
* @notice Emitted when recovery state is initiated by the Owner
@ -69,7 +69,7 @@ contract GovernanceRouter is Version0, Router {
// ============ Modifiers ============
modifier typeAssert(bytes29 _view, GovernanceMessage.Types _type) {
modifier typeAssert(bytes29 _view, ControllerMessage.Types _type) {
_view.assertType(uint40(_type));
_;
}
@ -84,8 +84,8 @@ contract GovernanceRouter is Version0, Router {
_;
}
modifier onlyGovernor() {
require(msg.sender == governor, "!governor");
modifier onlyController() {
require(msg.sender == controller, "!controller");
_;
}
@ -104,17 +104,17 @@ contract GovernanceRouter is Version0, Router {
function initialize(address _abacusConnectionManager) public initializer {
__Router_initialize(_abacusConnectionManager);
governor = msg.sender;
controller = msg.sender;
}
// ============ External Functions ============
/**
* @notice Handle Abacus messages
* For all non-Governor chains to handle messages
* sent from the Governor chain via Abacus.
* Governor chain should never receive messages,
* because non-Governor chains are not able to send them
* For all non-controlling chains to handle messages
* sent from the controlling chain via Abacus.
* Controlling chain should never receive messages,
* because non-controlling chains are not able to send them
* @param _message The message
*/
function _handle(
@ -125,8 +125,8 @@ contract GovernanceRouter is Version0, Router {
bytes29 _msg = _message.ref(0);
if (_msg.isValidCall()) {
_handleCall(_msg.tryAsCall());
} else if (_msg.isValidSetGovernor()) {
_handleSetGovernor(_msg.tryAsSetGovernor());
} else if (_msg.isValidSetController()) {
_handleSetController(_msg.tryAsSetController());
} else if (_msg.isValidEnrollRemoteRouter()) {
_handleEnrollRemoteRouter(_msg.tryAsEnrollRemoteRouter());
} else if (_msg.isValidSetAbacusConnectionManager()) {
@ -144,18 +144,18 @@ contract GovernanceRouter is Version0, Router {
* @notice Make local calls.
* @param _calls The calls
*/
function call(GovernanceMessage.Call[] calldata _calls) external onlyOwner {
function call(ControllerMessage.Call[] calldata _calls) external onlyOwner {
for (uint256 i = 0; i < _calls.length; i++) {
_makeCall(_calls[i]);
}
}
/**
* @notice Sets the governor of the router.
* @param _governor The address of the new governor
* @notice Sets the controller of the router.
* @param _controller The address of the new controller
*/
function setGovernor(address _governor) external onlyOwner {
_setGovernor(_governor);
function setController(address _controller) external onlyOwner {
_setController(_controller);
}
/**
@ -185,16 +185,16 @@ contract GovernanceRouter is Version0, Router {
// ============ External Remote Functions ============
/**
* @notice Dispatch calls on a remote chain via the remote GovernanceRouter.
* @notice Dispatch calls on a remote chain via the remote ControllerRouter.
* Any value paid to this function is used to pay for message processing on the remote chain.
* @param _destination The domain of the remote chain
* @param _calls The calls
*/
function callRemote(
uint32 _destination,
GovernanceMessage.Call[] calldata _calls
) external payable onlyGovernor onlyNotInRecovery {
bytes memory _msg = GovernanceMessage.formatCalls(_calls);
ControllerMessage.Call[] calldata _calls
) external payable onlyController onlyNotInRecovery {
bytes memory _msg = ControllerMessage.formatCalls(_calls);
_dispatchWithGasAndCheckpoint(_destination, _msg, msg.value);
}
@ -209,8 +209,8 @@ contract GovernanceRouter is Version0, Router {
uint32 _destination,
uint32 _domain,
bytes32 _router
) external payable onlyGovernor onlyNotInRecovery {
bytes memory _msg = GovernanceMessage.formatEnrollRemoteRouter(
) external payable onlyController onlyNotInRecovery {
bytes memory _msg = ControllerMessage.formatEnrollRemoteRouter(
_domain,
_router
);
@ -226,27 +226,27 @@ contract GovernanceRouter is Version0, Router {
function setAbacusConnectionManagerRemote(
uint32 _destination,
address _abacusConnectionManager
) external payable onlyGovernor onlyNotInRecovery {
bytes memory _msg = GovernanceMessage.formatSetAbacusConnectionManager(
) external payable onlyController onlyNotInRecovery {
bytes memory _msg = ControllerMessage.formatSetAbacusConnectionManager(
TypeCasts.addressToBytes32(_abacusConnectionManager)
);
_dispatchWithGasAndCheckpoint(_destination, _msg, msg.value);
}
/**
* @notice Sets the governor of a remote router. Any value paid to this
* @notice Sets the controller of a remote router. Any value paid to this
* function is used to pay for message processing on the remote chain.
* @param _destination The domain of router on which to set the governor
* @param _governor The address of the new governor
* @param _destination The domain of router on which to set the controller
* @param _controller The address of the new controller
*/
function setGovernorRemote(uint32 _destination, address _governor)
function setControllerRemote(uint32 _destination, address _controller)
external
payable
onlyGovernor
onlyController
onlyNotInRecovery
{
bytes memory _msg = GovernanceMessage.formatSetGovernor(
TypeCasts.addressToBytes32(_governor)
bytes memory _msg = ControllerMessage.formatSetController(
TypeCasts.addressToBytes32(_controller)
);
_dispatchWithGasAndCheckpoint(_destination, _msg, msg.value);
}
@ -255,7 +255,7 @@ contract GovernanceRouter is Version0, Router {
/**
* @notice Transfers the recovery manager to a new address.
* @dev Callable by the governor when not in recovery mode or the
* @dev Callable by the controller when not in recovery mode or the
* recoveryManager at any time.
* @param _recoveryManager The address of the new recovery manager
*/
@ -278,10 +278,10 @@ contract GovernanceRouter is Version0, Router {
/**
* @notice Returns the address of the current owner.
* @dev When not in recovery mode, the governor owns the contract.
* @dev When not in recovery mode, the controller owns the contract.
*/
function owner() public view virtual override returns (address) {
return inRecovery() ? recoveryManager() : governor;
return inRecovery() ? recoveryManager() : controller;
}
/**
@ -313,24 +313,24 @@ contract GovernanceRouter is Version0, Router {
*/
function _handleCall(bytes29 _msg)
internal
typeAssert(_msg, GovernanceMessage.Types.Call)
typeAssert(_msg, ControllerMessage.Types.Call)
{
GovernanceMessage.Call[] memory _calls = _msg.getCalls();
ControllerMessage.Call[] memory _calls = _msg.getCalls();
for (uint256 i = 0; i < _calls.length; i++) {
_makeCall(_calls[i]);
}
}
/**
* @notice Handle message transferring governorship to a new Governor
* @notice Handle message transferring control to a new Controller
* @param _msg The message
*/
function _handleSetGovernor(bytes29 _msg)
function _handleSetController(bytes29 _msg)
internal
typeAssert(_msg, GovernanceMessage.Types.SetGovernor)
typeAssert(_msg, ControllerMessage.Types.SetController)
{
address _governor = TypeCasts.bytes32ToAddress(_msg.governor());
_setGovernor(_governor);
address _controller = TypeCasts.bytes32ToAddress(_msg.controller());
_setController(_controller);
}
/**
@ -339,7 +339,7 @@ contract GovernanceRouter is Version0, Router {
*/
function _handleEnrollRemoteRouter(bytes29 _msg)
internal
typeAssert(_msg, GovernanceMessage.Types.EnrollRemoteRouter)
typeAssert(_msg, ControllerMessage.Types.EnrollRemoteRouter)
{
uint32 _domain = _msg.domain();
bytes32 _router = _msg.router();
@ -352,7 +352,7 @@ contract GovernanceRouter is Version0, Router {
*/
function _handleSetAbacusConnectionManager(bytes29 _msg)
internal
typeAssert(_msg, GovernanceMessage.Types.SetAbacusConnectionManager)
typeAssert(_msg, ControllerMessage.Types.SetAbacusConnectionManager)
{
address _abacusConnectionManager = TypeCasts.bytes32ToAddress(
_msg.abacusConnectionManager()
@ -365,7 +365,7 @@ contract GovernanceRouter is Version0, Router {
* @param _call The call
* @return _ret
*/
function _makeCall(GovernanceMessage.Call memory _call)
function _makeCall(ControllerMessage.Call memory _call)
internal
returns (bytes memory _ret)
{
@ -378,11 +378,11 @@ contract GovernanceRouter is Version0, Router {
}
/**
* @notice Set the governor.
* @param _governor The address of the new governor
* @notice Set the controller.
* @param _controller The address of the new controller
*/
function _setGovernor(address _governor) internal {
governor = _governor;
emit SetGovernor(_governor);
function _setController(address _controller) internal {
controller = _controller;
emit SetController(_controller);
}
}

@ -5,9 +5,9 @@ import { abacus, ethers } from 'hardhat';
import { InterchainGasPaymaster, Outbox } from '@abacus-network/core';
import { utils } from '@abacus-network/utils';
import { GovernanceRouter, TestSet, TestSet__factory } from '../../types';
import { ControllerRouter, TestSet, TestSet__factory } from '../../types';
import { GovernanceConfig, GovernanceDeploy } from './lib/GovernanceDeploy';
import { ControllerConfig, ControllerDeploy } from './lib/ControllerDeploy';
import { formatCall, increaseTimestampBy } from './lib/utils';
const recoveryTimelock = 60 * 60 * 24 * 7;
@ -17,39 +17,39 @@ const testDomain = 3000;
const domains = [localDomain, remoteDomain];
const ONLY_OWNER_REVERT_MESSAGE = 'Ownable: caller is not the owner';
describe('GovernanceRouter', async () => {
let governor: SignerWithAddress,
describe('ControllerRouter', async () => {
let controller: SignerWithAddress,
recoveryManager: SignerWithAddress,
router: GovernanceRouter,
remote: GovernanceRouter,
router: ControllerRouter,
remote: ControllerRouter,
testSet: TestSet,
governance: GovernanceDeploy;
controllerDeploy: ControllerDeploy;
let outbox: Outbox;
let interchainGasPaymaster: InterchainGasPaymaster;
const testInterchainGasPayment = 123456789;
before(async () => {
[governor, recoveryManager] = await ethers.getSigners();
[controller, recoveryManager] = await ethers.getSigners();
const testSetFactory = new TestSet__factory(governor);
const testSetFactory = new TestSet__factory(controller);
testSet = await testSetFactory.deploy();
});
beforeEach(async () => {
const config: GovernanceConfig = {
signer: governor,
const config: ControllerConfig = {
signer: controller,
timelock: recoveryTimelock,
recoveryManager: recoveryManager.address,
governor: {
controller: {
domain: localDomain,
address: governor.address,
address: controller.address,
},
};
await abacus.deploy(domains, governor);
governance = new GovernanceDeploy(config);
await governance.deploy(abacus);
router = governance.router(localDomain);
remote = governance.router(remoteDomain);
await abacus.deploy(domains, controller);
controllerDeploy = new ControllerDeploy(config);
await controllerDeploy.deploy(abacus);
router = controllerDeploy.router(localDomain);
remote = controllerDeploy.router(remoteDomain);
outbox = abacus.outbox(localDomain);
interchainGasPaymaster = abacus.interchainGasPaymaster(localDomain);
});
@ -61,31 +61,31 @@ describe('GovernanceRouter', async () => {
});
describe('when not in recovery mode', async () => {
it('governor is the owner', async () => {
expect(await router.owner()).to.equal(governor.address);
it('controller is the owner', async () => {
expect(await router.owner()).to.equal(controller.address);
});
it('governor can set local recovery manager', async () => {
it('controller can set local recovery manager', async () => {
expect(await router.recoveryManager()).to.equal(recoveryManager.address);
await router.transferOwnership(router.address);
expect(await router.recoveryManager()).to.equal(router.address);
expect(await router.recoveryActiveAt()).to.equal(0);
});
it('governor can make local calls', async () => {
it('controller can make local calls', async () => {
const value = 12;
const call = formatCall(testSet, 'set', [value]);
await router.call([call]);
expect(await testSet.get()).to.equal(value);
});
it('governor can set local governor', async () => {
expect(await router.governor()).to.equal(governor.address);
await router.setGovernor(ethers.constants.AddressZero);
expect(await router.governor()).to.equal(ethers.constants.AddressZero);
it('controller can set local controller', async () => {
expect(await router.controller()).to.equal(controller.address);
await router.setController(ethers.constants.AddressZero);
expect(await router.controller()).to.equal(ethers.constants.AddressZero);
});
it('governor can set local abacusConnectionManager', async () => {
it('controller can set local abacusConnectionManager', async () => {
expect(await router.abacusConnectionManager()).to.equal(
abacus.abacusConnectionManager(localDomain).address,
);
@ -95,7 +95,7 @@ describe('GovernanceRouter', async () => {
);
});
it('governor can enroll local remote router', async () => {
it('controller can enroll local remote router', async () => {
expect(await router.routers(testDomain)).to.equal(
ethers.constants.HashZero,
);
@ -104,7 +104,7 @@ describe('GovernanceRouter', async () => {
expect(await router.routers(testDomain)).to.equal(newRouter);
});
it('governor can make remote calls', async () => {
it('controller can make remote calls', async () => {
const value = 13;
const call = formatCall(testSet, 'set', [value]);
await router.callRemote(domains[1], [call]);
@ -134,19 +134,19 @@ describe('GovernanceRouter', async () => {
);
});
it('governor can set remote governor', async () => {
const newGovernor = governor.address;
expect(await remote.governor()).to.not.equal(newGovernor);
await router.setGovernorRemote(remoteDomain, newGovernor);
it('controller can set remote controller', async () => {
const newController = controller.address;
expect(await remote.controller()).to.not.equal(newController);
await router.setControllerRemote(remoteDomain, newController);
await abacus.processMessages();
expect(await remote.governor()).to.equal(newGovernor);
expect(await remote.controller()).to.equal(newController);
});
it('allows interchain gas payment when setting a remote governor', async () => {
const newGovernor = governor.address;
it('allows interchain gas payment when setting a remote controller', async () => {
const newController = controller.address;
const leafIndex = await outbox.count();
await expect(
router.setGovernorRemote(remoteDomain, newGovernor, {
router.setControllerRemote(remoteDomain, newController, {
value: testInterchainGasPayment,
}),
)
@ -154,15 +154,14 @@ describe('GovernanceRouter', async () => {
.withArgs(leafIndex, testInterchainGasPayment);
});
it('creates a checkpoint when setting a remote governor', async () => {
const newGovernor = governor.address;
await expect(router.setGovernorRemote(remoteDomain, newGovernor)).to.emit(
outbox,
'Checkpoint',
);
it('creates a checkpoint when setting a remote controller', async () => {
const newController = controller.address;
await expect(
router.setControllerRemote(remoteDomain, newController),
).to.emit(outbox, 'Checkpoint');
});
it('governor can set remote abacusConnectionManager', async () => {
it('controller can set remote abacusConnectionManager', async () => {
const newConnectionManager = ethers.constants.AddressZero;
expect(await remote.abacusConnectionManager()).to.not.equal(
newConnectionManager,
@ -199,7 +198,7 @@ describe('GovernanceRouter', async () => {
).to.emit(outbox, 'Checkpoint');
});
it('governor can enroll remote remote router', async () => {
it('controller can enroll remote remote router', async () => {
expect(await remote.routers(testDomain)).to.equal(
ethers.constants.HashZero,
);
@ -232,13 +231,13 @@ describe('GovernanceRouter', async () => {
).to.emit(outbox, 'Checkpoint');
});
it('governor cannot initiate recovery', async () => {
it('controller cannot initiate recovery', async () => {
await expect(router.initiateRecoveryTimelock()).to.be.revertedWith(
'!recoveryManager',
);
});
it('governor cannot exit recovery', async () => {
it('controller cannot exit recovery', async () => {
await expect(router.exitRecovery()).to.be.revertedWith('!recovery');
});
@ -257,11 +256,11 @@ describe('GovernanceRouter', async () => {
).to.be.revertedWith(ONLY_OWNER_REVERT_MESSAGE);
});
it('recovery manager cannot set local governor', async () => {
it('recovery manager cannot set local controller', async () => {
await expect(
router
.connect(recoveryManager)
.setGovernor(ethers.constants.AddressZero),
.setController(ethers.constants.AddressZero),
).to.be.revertedWith(ONLY_OWNER_REVERT_MESSAGE);
});
@ -289,15 +288,15 @@ describe('GovernanceRouter', async () => {
const call = formatCall(testSet, 'set', [value]);
await expect(
router.connect(recoveryManager).callRemote(domains[1], [call]),
).to.be.revertedWith('!governor');
).to.be.revertedWith('!controller');
});
it('recovery manager cannot set remote governor', async () => {
it('recovery manager cannot set remote controller', async () => {
await expect(
router
.connect(recoveryManager)
.setGovernorRemote(remoteDomain, router.address),
).to.be.revertedWith('!governor');
.setControllerRemote(remoteDomain, router.address),
).to.be.revertedWith('!controller');
});
it('recovery manager cannot set remote abacusConnectionManager', async () => {
@ -305,7 +304,7 @@ describe('GovernanceRouter', async () => {
router
.connect(recoveryManager)
.setAbacusConnectionManagerRemote(remoteDomain, router.address),
).to.be.revertedWith('!governor');
).to.be.revertedWith('!controller');
});
it('recovery manager cannot enroll remote remote router', async () => {
@ -317,7 +316,7 @@ describe('GovernanceRouter', async () => {
testDomain,
utils.addressToBytes32(router.address),
),
).to.be.revertedWith('!governor');
).to.be.revertedWith('!controller');
});
it('recovery manager can initiate recovery', async () => {
@ -361,10 +360,10 @@ describe('GovernanceRouter', async () => {
expect(await testSet.get()).to.equal(value);
});
it('recovery manager can set local governor', async () => {
expect(await router.governor()).to.equal(governor.address);
await router.setGovernor(ethers.constants.AddressZero);
expect(await router.governor()).to.equal(ethers.constants.AddressZero);
it('recovery manager can set local controller', async () => {
expect(await router.controller()).to.equal(controller.address);
await router.setController(ethers.constants.AddressZero);
expect(await router.controller()).to.equal(ethers.constants.AddressZero);
});
it('recovery manager can set local abacusConnectionManager', async () => {
@ -390,20 +389,20 @@ describe('GovernanceRouter', async () => {
const value = 13;
const call = formatCall(testSet, 'set', [value]);
await expect(router.callRemote(domains[1], [call])).to.be.revertedWith(
'!governor',
'!controller',
);
});
it('recovery manager cannot set remote governor', async () => {
it('recovery manager cannot set remote controller', async () => {
await expect(
router.setGovernorRemote(remoteDomain, router.address),
).to.be.revertedWith('!governor');
router.setControllerRemote(remoteDomain, router.address),
).to.be.revertedWith('!controller');
});
it('recovery manager cannot set remote abacusConnectionManager', async () => {
await expect(
router.setAbacusConnectionManagerRemote(remoteDomain, router.address),
).to.be.revertedWith('!governor');
).to.be.revertedWith('!controller');
});
it('recovery manager cannot enroll remote remote router', async () => {
@ -413,7 +412,7 @@ describe('GovernanceRouter', async () => {
testDomain,
utils.addressToBytes32(router.address),
),
).to.be.revertedWith('!governor');
).to.be.revertedWith('!controller');
});
it('recovery manager cannot initiate recovery', async () => {
@ -427,36 +426,36 @@ describe('GovernanceRouter', async () => {
expect(await router.inRecovery()).to.be.false;
});
it('governor cannot make local calls', async () => {
it('controller cannot make local calls', async () => {
const value = 12;
const call = formatCall(testSet, 'set', [value]);
await expect(router.connect(governor).call([call])).to.be.revertedWith(
await expect(router.connect(controller).call([call])).to.be.revertedWith(
ONLY_OWNER_REVERT_MESSAGE,
);
});
it('governor cannot set local governor', async () => {
it('controller cannot set local controller', async () => {
await expect(
router.connect(governor).setGovernor(ethers.constants.AddressZero),
router.connect(controller).setController(ethers.constants.AddressZero),
).to.be.revertedWith(ONLY_OWNER_REVERT_MESSAGE);
});
it('governor cannot set local recovery manager', async () => {
it('controller cannot set local recovery manager', async () => {
await expect(
router.connect(governor).transferOwnership(router.address),
router.connect(controller).transferOwnership(router.address),
).to.be.revertedWith(ONLY_OWNER_REVERT_MESSAGE);
});
it('governor cannot set local abacusConnectionManager', async () => {
it('controller cannot set local abacusConnectionManager', async () => {
await expect(
router.connect(governor).setAbacusConnectionManager(router.address),
router.connect(controller).setAbacusConnectionManager(router.address),
).to.be.revertedWith(ONLY_OWNER_REVERT_MESSAGE);
});
it('governor cannot enroll local remote router', async () => {
it('controller cannot enroll local remote router', async () => {
await expect(
router
.connect(governor)
.connect(controller)
.enrollRemoteRouter(
testDomain,
utils.addressToBytes32(router.address),
@ -464,34 +463,34 @@ describe('GovernanceRouter', async () => {
).to.be.revertedWith(ONLY_OWNER_REVERT_MESSAGE);
});
it('governor cannot make remote calls', async () => {
it('controller cannot make remote calls', async () => {
const value = 13;
const call = formatCall(testSet, 'set', [value]);
await expect(
router.connect(governor).callRemote(domains[1], [call]),
router.connect(controller).callRemote(domains[1], [call]),
).to.be.revertedWith('recovery');
});
it('governor cannot set remote governor', async () => {
it('controller cannot set remote controller', async () => {
await expect(
router
.connect(governor)
.setGovernorRemote(remoteDomain, router.address),
.connect(controller)
.setControllerRemote(remoteDomain, router.address),
).to.be.revertedWith('recovery');
});
it('governor cannot set remote abacusConnectionManager', async () => {
it('controller cannot set remote abacusConnectionManager', async () => {
await expect(
router
.connect(governor)
.connect(controller)
.setAbacusConnectionManagerRemote(remoteDomain, router.address),
).to.be.revertedWith('recovery');
});
it('governor cannot enroll remote remote router', async () => {
it('controller cannot enroll remote remote router', async () => {
await expect(
router
.connect(governor)
.connect(controller)
.enrollRemoteRouterRemote(
remoteDomain,
testDomain,
@ -500,16 +499,16 @@ describe('GovernanceRouter', async () => {
).to.be.revertedWith('recovery');
});
it('governor cannot initiate recovery', async () => {
it('controller cannot initiate recovery', async () => {
await expect(
router.connect(governor).initiateRecoveryTimelock(),
router.connect(controller).initiateRecoveryTimelock(),
).to.be.revertedWith('recovery');
});
it('governor cannot exit recovery', async () => {
await expect(router.connect(governor).exitRecovery()).to.be.revertedWith(
'!recoveryManager',
);
it('controller cannot exit recovery', async () => {
await expect(
router.connect(controller).exitRecovery(),
).to.be.revertedWith('!recoveryManager');
});
});
});

@ -3,31 +3,31 @@ import { ethers } from 'ethers';
import { TestAbacusDeploy, TestRouterDeploy } from '@abacus-network/hardhat';
import { types } from '@abacus-network/utils';
import { GovernanceRouter, GovernanceRouter__factory } from '../../../types';
import { ControllerRouter, ControllerRouter__factory } from '../../../types';
export type Governor = {
export type ControllingEntity = {
domain: types.Domain;
address: types.Address;
};
export type GovernanceConfig = {
export type ControllerConfig = {
signer: ethers.Signer;
timelock: number;
governor: Governor;
controller: ControllingEntity;
recoveryManager: types.Address;
};
export class GovernanceDeploy extends TestRouterDeploy<
GovernanceRouter,
GovernanceConfig
export class ControllerDeploy extends TestRouterDeploy<
ControllerRouter,
ControllerConfig
> {
async deploy(abacus: TestAbacusDeploy) {
await super.deploy(abacus);
for (const domain of this.domains) {
if (domain == this.config.governor.domain) {
await this.router(domain).setGovernor(this.config.governor.address);
if (domain == this.config.controller.domain) {
await this.router(domain).setController(this.config.controller.address);
} else {
await this.router(domain).setGovernor(ethers.constants.AddressZero);
await this.router(domain).setController(ethers.constants.AddressZero);
}
}
}
@ -35,15 +35,15 @@ export class GovernanceDeploy extends TestRouterDeploy<
async deployInstance(
domain: types.Domain,
abacus: TestAbacusDeploy,
): Promise<GovernanceRouter> {
const routerFactory = new GovernanceRouter__factory(this.config.signer);
): Promise<ControllerRouter> {
const routerFactory = new ControllerRouter__factory(this.config.signer);
const router = await routerFactory.deploy(this.config.timelock);
await router.initialize(abacus.abacusConnectionManager(domain).address);
await router.transferOwnership(this.config.recoveryManager);
return router;
}
router(domain: types.Domain): GovernanceRouter {
router(domain: types.Domain): ControllerRouter {
return this.instances[domain];
}
}

@ -2,17 +2,17 @@ import { ethers } from 'ethers';
import { types, utils } from '@abacus-network/utils';
export enum GovernanceMessage {
export enum ControllerMessage {
CALL = 1,
SETGOVERNOR = 2,
SETCONTROLLER = 2,
ENROLLREMOTEROUTER = 3,
SETXAPPCONNECTIONMANAGER = 5,
}
export function formatSetGovernor(address: types.Address): string {
export function formatSetController(address: types.Address): string {
return ethers.utils.solidityPack(
['bytes1', 'bytes32'],
[GovernanceMessage.SETGOVERNOR, utils.addressToBytes32(address)],
[ControllerMessage.SETCONTROLLER, utils.addressToBytes32(address)],
);
}
@ -22,7 +22,7 @@ export function formatSetAbacusConnectionManager(
return ethers.utils.solidityPack(
['bytes1', 'bytes32'],
[
GovernanceMessage.SETXAPPCONNECTIONMANAGER,
ControllerMessage.SETXAPPCONNECTIONMANAGER,
utils.addressToBytes32(address),
],
);
@ -35,7 +35,7 @@ export function formatEnrollRemoteRouter(
return ethers.utils.solidityPack(
['bytes1', 'uint32', 'bytes32'],
[
GovernanceMessage.ENROLLREMOTEROUTER,
ControllerMessage.ENROLLREMOTEROUTER,
domain,
utils.addressToBytes32(address),
],
@ -65,7 +65,7 @@ export function formatCalls(callsData: types.CallData[]): string {
return ethers.utils.solidityPack(
['bytes1', 'bytes1', 'bytes'],
[GovernanceMessage.CALL, numCalls, callBody],
[ControllerMessage.CALL, numCalls, callBody],
);
}

@ -0,0 +1,20 @@
import { ChainMap } from '@abacus-network/sdk';
import { ControllerConfig } from '../../../src/controller';
import { DevNetworks } from './domains';
const defaultControllerConfig = {
recoveryManager: '0x3909CFACD7a568634716CbCE635F76b9Cf37364B',
recoveryTimelock: 180,
};
const addresses = {
alfajores: {
...defaultControllerConfig,
controller: '0x3909CFACD7a568634716CbCE635F76b9Cf37364B',
},
kovan: defaultControllerConfig,
};
export const controller: ChainMap<DevNetworks, ControllerConfig> = addresses;

@ -1,20 +0,0 @@
import { ChainMap } from '@abacus-network/sdk';
import { GovernanceConfig } from '../../../src/governance';
import { DevNetworks } from './domains';
const defaultGovernanceConfig = {
recoveryManager: '0x3909CFACD7a568634716CbCE635F76b9Cf37364B',
recoveryTimelock: 180,
};
const addresses = {
alfajores: {
...defaultGovernanceConfig,
governor: '0x3909CFACD7a568634716CbCE635F76b9Cf37364B',
},
kovan: defaultGovernanceConfig,
};
export const governance: ChainMap<DevNetworks, GovernanceConfig> = addresses;

@ -2,9 +2,9 @@ import { getMultiProviderFromGCP } from '../../../scripts/utils';
import { CoreEnvironmentConfig } from '../../../src/config';
import { agent } from './agent';
import { controller } from './controller';
import { core } from './core';
import { DevNetworks, devConfigs } from './domains';
import { governance } from './governance';
import { infrastructure } from './infrastructure';
export const environment: CoreEnvironmentConfig<DevNetworks> = {
@ -12,6 +12,6 @@ export const environment: CoreEnvironmentConfig<DevNetworks> = {
getMultiProvider: () => getMultiProviderFromGCP(devConfigs, 'dev'),
agent,
core,
governance,
controller,
infra: infrastructure,
};

@ -0,0 +1,21 @@
import { ChainMap } from '@abacus-network/sdk';
import { ControllerConfig } from '../../../src/controller';
import { TestNetworks } from './domains';
const defaultControllerConfig: ControllerConfig = {
recoveryManager: '0x4FbBB2b0820CF0cF027BbB58DC7F7f760BC0c57e',
recoveryTimelock: 180,
};
const addresses = {
test1: {
...defaultControllerConfig,
controller: '0x4FbBB2b0820CF0cF027BbB58DC7F7f760BC0c57e',
},
test2: defaultControllerConfig,
test3: defaultControllerConfig,
};
export const controller: ChainMap<TestNetworks, ControllerConfig> = addresses;

@ -1,21 +0,0 @@
import { ChainMap } from '@abacus-network/sdk';
import { GovernanceConfig } from '../../../src/governance';
import { TestNetworks } from './domains';
const defaultGovernanceConfig: GovernanceConfig = {
recoveryManager: '0x4FbBB2b0820CF0cF027BbB58DC7F7f760BC0c57e',
recoveryTimelock: 180,
};
const addresses = {
test1: {
...defaultGovernanceConfig,
governor: '0x4FbBB2b0820CF0cF027BbB58DC7F7f760BC0c57e',
},
test2: defaultGovernanceConfig,
test3: defaultGovernanceConfig,
};
export const governance: ChainMap<TestNetworks, GovernanceConfig> = addresses;

@ -3,16 +3,16 @@ import { utils } from '@abacus-network/deploy';
import { CoreEnvironmentConfig } from '../../../src/config';
import { agent } from './agent';
import { controller } from './controller';
import { core } from './core';
import { TestNetworks, testConfigs } from './domains';
import { governance } from './governance';
import { infra } from './infra';
export const environment: CoreEnvironmentConfig<TestNetworks> = {
transactionConfigs: testConfigs,
agent,
core,
governance,
controller,
infra,
// NOTE: Does not work from hardhat.config.ts
getMultiProvider: async () => {

@ -0,0 +1,24 @@
import { ChainMap } from '@abacus-network/sdk';
import { ControllerConfig } from '../../../src/controller';
const defaultControllerConfig: ControllerConfig = {
recoveryManager: '0xfaD1C94469700833717Fa8a3017278BC1cA8031C',
recoveryTimelock: 180,
};
const addresses = {
alfajores: {
...defaultControllerConfig,
controller: '0xfaD1C94469700833717Fa8a3017278BC1cA8031C',
},
kovan: defaultControllerConfig,
fuji: defaultControllerConfig,
mumbai: defaultControllerConfig,
bsctestnet: defaultControllerConfig,
arbitrumrinkeby: defaultControllerConfig,
optimismkovan: defaultControllerConfig,
};
export const controller: ChainMap<keyof typeof addresses, ControllerConfig> =
addresses;

@ -1,24 +0,0 @@
import { ChainMap } from '@abacus-network/sdk';
import { GovernanceConfig } from '../../../src/governance';
const defaultGovernanceConfig: GovernanceConfig = {
recoveryManager: '0xfaD1C94469700833717Fa8a3017278BC1cA8031C',
recoveryTimelock: 180,
};
const addresses = {
alfajores: {
...defaultGovernanceConfig,
governor: '0xfaD1C94469700833717Fa8a3017278BC1cA8031C',
},
kovan: defaultGovernanceConfig,
fuji: defaultGovernanceConfig,
mumbai: defaultGovernanceConfig,
bsctestnet: defaultGovernanceConfig,
arbitrumrinkeby: defaultGovernanceConfig,
optimismkovan: defaultGovernanceConfig,
};
export const governance: ChainMap<keyof typeof addresses, GovernanceConfig> =
addresses;

@ -2,9 +2,9 @@ import { getMultiProviderFromGCP } from '../../../scripts/utils';
import { CoreEnvironmentConfig } from '../../../src/config';
import { agent } from './agent';
import { controller } from './controller';
import { core } from './core';
import { TestnetNetworks, testnetConfigs } from './domains';
import { governance } from './governance';
import { infrastructure } from './infrastructure';
export const environment: CoreEnvironmentConfig<TestnetNetworks> = {
@ -12,6 +12,6 @@ export const environment: CoreEnvironmentConfig<TestnetNetworks> = {
getMultiProvider: () => getMultiProviderFromGCP(testnetConfigs, 'testnet'),
agent,
core,
governance,
controller,
infra: infrastructure,
};

@ -1,7 +1,7 @@
import { AbacusCore, AbacusGovernance } from '@abacus-network/sdk';
import { AbacusCore, ControllerApp } from '@abacus-network/sdk';
import { ControllerChecker } from '../src/controller';
import { AbacusCoreChecker } from '../src/core';
import { AbacusGovernanceChecker } from '../src/governance';
import { getCoreEnvironmentConfig, getEnvironment } from './utils';
@ -12,25 +12,22 @@ async function check() {
if (environment !== 'test') {
throw new Error(
`Do not have governance addresses for ${environment} in SDK`,
`Do not have controller addresses for ${environment} in SDK`,
);
}
const core = AbacusCore.fromEnvironment(environment, multiProvider);
const governance = AbacusGovernance.fromEnvironment(
environment,
multiProvider,
);
const controller = ControllerApp.fromEnvironment(environment, multiProvider);
const governanceChecker = new AbacusGovernanceChecker(
const controllerChecker = new ControllerChecker(
multiProvider,
governance,
config.governance,
controller,
config.controller,
);
await governanceChecker.check();
governanceChecker.expectEmpty();
await controllerChecker.check();
controllerChecker.expectEmpty();
const owners = governance.routerAddresses();
const owners = controller.routerAddresses();
const coreChecker = new AbacusCoreChecker(multiProvider, core, {
...config.core,
owners,

@ -1,13 +1,13 @@
import { AbacusCoreDeployer } from '@abacus-network/deploy';
import { AbacusCore, objMap } from '@abacus-network/sdk';
import { AbacusGovernanceDeployer } from '../src/governance';
import { ControllerDeployer } from '../src/controller';
import {
getControllerContractsSdkFilepath,
getControllerVerificationDirectory,
getCoreEnvironmentConfig,
getEnvironment,
getGovernanceContractsSdkFilepath,
getGovernanceVerificationDirectory,
} from './utils';
async function main() {
@ -16,17 +16,17 @@ async function main() {
const multiProvider = await config.getMultiProvider();
const core = AbacusCore.fromEnvironment(environment, multiProvider);
const deployer = new AbacusGovernanceDeployer(
const deployer = new ControllerDeployer(
multiProvider,
config.governance,
config.controller,
core,
);
const addresses = await deployer.deploy();
deployer.writeContracts(
addresses,
getGovernanceContractsSdkFilepath(environment),
getControllerContractsSdkFilepath(environment),
);
deployer.writeVerification(getGovernanceVerificationDirectory(environment));
deployer.writeVerification(getControllerVerificationDirectory(environment));
const owners = objMap(addresses, (_, r) => r.router.proxy);
await AbacusCoreDeployer.transferOwnership(core, owners, multiProvider);

@ -1,6 +1,6 @@
import { AbacusCore, AbacusGovernance } from '@abacus-network/sdk';
import { AbacusCore, ControllerApp } from '@abacus-network/sdk';
import { AbacusCoreGovernor, CoreViolationType } from '../src/core';
import { AbacusCoreControllerChecker, CoreViolationType } from '../src/core';
import { getCoreEnvironmentConfig, getEnvironment } from './utils';
@ -12,34 +12,34 @@ async function main() {
if (environment !== 'test') {
throw new Error(`No governanace addresses for ${environment} in SDK`);
}
const governance = AbacusGovernance.fromEnvironment(
const controllerApp = ControllerApp.fromEnvironment(
environment,
multiProvider,
);
const governor = new AbacusCoreGovernor(
const checker = new AbacusCoreControllerChecker(
multiProvider,
core,
governance,
controllerApp,
config.core,
);
await governor.check();
await checker.check();
// Sanity check: for each domain, expect one validator violation.
governor.expectViolations(
checker.expectViolations(
[CoreViolationType.Validator],
[core.networks().length],
);
// Sanity check: for each domain, expect one call to set the validator.
governor.expectCalls(
checker.expectCalls(
core.networks(),
new Array(core.networks().length).fill(1),
);
// Change to `batch.execute` in order to run.
const governorActor = await governance.governor();
const provider = multiProvider.getDomainConnection(governorActor.network)
const controllerActor = await controllerApp.controller();
const provider = multiProvider.getDomainConnection(controllerActor.network)
.provider!;
const receipts = await governor.governance.estimateGas(provider);
const receipts = await checker.controllerApp.estimateGas(provider);
console.log(receipts);
}
main().then(console.log).catch(console.error);

@ -65,10 +65,10 @@ export function getCoreContractsSdkFilepath(environment: DeployEnvironment) {
return getContractsSdkFilepath('core', environment);
}
export function getGovernanceContractsSdkFilepath(
export function getControllerContractsSdkFilepath(
environment: DeployEnvironment,
) {
return getContractsSdkFilepath('governance', environment);
return getContractsSdkFilepath('controller', environment);
}
export function getEnvironmentDirectory(environment: DeployEnvironment) {
@ -87,14 +87,14 @@ export function getCoreRustDirectory(environment: DeployEnvironment) {
return path.join(getCoreDirectory(environment), 'rust');
}
export function getGovernanceDirectory(environment: DeployEnvironment) {
return path.join(getEnvironmentDirectory(environment), 'governance');
export function getControllerDirectory(environment: DeployEnvironment) {
return path.join(getEnvironmentDirectory(environment), 'controller');
}
export function getGovernanceVerificationDirectory(
export function getControllerVerificationDirectory(
environment: DeployEnvironment,
) {
return path.join(getGovernanceDirectory(environment), 'verification');
return path.join(getControllerDirectory(environment), 'verification');
}
export function getKeyRoleAndChainArgs() {

@ -2,7 +2,7 @@ import { CoreConfig, EnvironmentConfig } from '@abacus-network/deploy';
import { ChainMap, ChainName, MultiProvider } from '@abacus-network/sdk';
import { environments } from '../../config/environments';
import { GovernanceConfig } from '../governance';
import { ControllerConfig } from '../controller';
import { AgentConfig } from './agent';
import { InfrastructureConfig } from './infrastructure';
@ -18,7 +18,7 @@ export type CoreEnvironmentConfig<Networks extends ChainName> = {
transactionConfigs: EnvironmentConfig<Networks>;
agent: AgentConfig<Networks>;
core: ChainMap<Networks, CoreConfig>;
governance: ChainMap<Networks, GovernanceConfig>;
controller: ChainMap<Networks, ControllerConfig>;
infra: InfrastructureConfig;
getMultiProvider: () => Promise<MultiProvider<Networks>>;
};

@ -3,38 +3,38 @@ import { ethers } from 'ethers';
import { AbacusRouterChecker } from '@abacus-network/deploy';
import {
AbacusGovernance,
ChainMap,
ChainName,
ControllerApp,
MultiProvider,
objMap,
} from '@abacus-network/sdk';
import { types } from '@abacus-network/utils';
import { GovernanceConfig } from './types';
import { ControllerConfig } from './types';
export class AbacusGovernanceChecker<
export class ControllerChecker<
Networks extends ChainName,
> extends AbacusRouterChecker<
Networks,
AbacusGovernance<Networks>,
GovernanceConfig & {
ControllerApp<Networks>,
ControllerConfig & {
owner: types.Address;
}
> {
constructor(
multiProvider: MultiProvider<any>,
app: AbacusGovernance<Networks>,
configMap: ChainMap<Networks, GovernanceConfig>,
app: ControllerApp<Networks>,
configMap: ChainMap<Networks, ControllerConfig>,
) {
const joinedConfig = objMap(configMap, (_, config) => ({
...config,
owner: config.governor ?? ethers.constants.AddressZero,
owner: config.controller ?? ethers.constants.AddressZero,
}));
super(multiProvider, app, joinedConfig);
}
// GovernanceRouter's owner is 0x0 on all chains except the governing chain as setup in the constructor
// ControllerRouter's owner is 0x0 on all chains except the controlling chain as setup in the constructor
async checkOwnership(network: Networks): Promise<void> {
const contracts = this.app.getContracts(network);
@ -58,7 +58,7 @@ export class AbacusGovernanceChecker<
// Outbox upgrade setup contracts are defined
await this.checkUpgradeBeacon(
network,
'GovernanceRouter',
'ControllerRouter',
addresses.router,
);
}

@ -1,28 +1,28 @@
import { ethers } from 'ethers';
import { GovernanceRouter__factory } from '@abacus-network/apps';
import { ControllerRouter__factory } from '@abacus-network/apps';
import { UpgradeBeaconController__factory } from '@abacus-network/core';
import { AbacusRouterDeployer } from '@abacus-network/deploy';
import {
ChainName,
GovernanceAddresses,
ControllerAddresses,
objMap,
promiseObjAll,
} from '@abacus-network/sdk';
import { GovernanceConfig } from './types';
import { ControllerConfig } from './types';
export class AbacusGovernanceDeployer<
export class ControllerDeployer<
Networks extends ChainName,
> extends AbacusRouterDeployer<
Networks,
GovernanceConfig,
GovernanceAddresses
ControllerConfig,
ControllerAddresses
> {
async deployContracts(
network: Networks,
config: GovernanceConfig,
): Promise<GovernanceAddresses> {
config: ControllerConfig,
): Promise<ControllerAddresses> {
const dc = this.multiProvider.getDomainConnection(network);
const signer = dc.signer!;
@ -38,8 +38,8 @@ export class AbacusGovernanceDeployer<
const router = await this.deployProxiedContract(
network,
'GovernanceRouter',
new GovernanceRouter__factory(signer),
'ControllerRouter',
new ControllerRouter__factory(signer),
[config.recoveryTimelock],
upgradeBeaconController.address,
[abacusConnectionManager.address],
@ -73,8 +73,8 @@ export class AbacusGovernanceDeployer<
const router = this.mustGetRouter(local, addresses);
const config = this.configMap[local];
await router.transferOwnership(config.recoveryManager);
await router.setGovernor(
config.governor ?? ethers.constants.AddressZero,
await router.setController(
config.controller ?? ethers.constants.AddressZero,
);
}),
);
@ -82,8 +82,8 @@ export class AbacusGovernanceDeployer<
return deploymentOutput;
}
mustGetRouter(network: Networks, addresses: GovernanceAddresses) {
return GovernanceRouter__factory.connect(
mustGetRouter(network: Networks, addresses: ControllerAddresses) {
return ControllerRouter__factory.connect(
addresses.router.proxy,
this.multiProvider.getDomainConnection(network).signer!,
);

@ -0,0 +1,3 @@
export { ControllerDeployer } from './deploy';
export { ControllerChecker } from './check';
export { ControllerConfigAddresses, ControllerConfig } from './types';

@ -0,0 +1,10 @@
import { RouterConfig } from '@abacus-network/deploy';
import { types } from '@abacus-network/utils';
export type ControllerConfigAddresses = {
recoveryManager: types.Address;
controller?: types.Address;
};
export type ControllerConfig = RouterConfig &
ControllerConfigAddresses & { recoveryTimelock: number };

@ -10,10 +10,10 @@ import {
} from '@abacus-network/deploy';
import {
AbacusCore,
AbacusGovernance,
Call,
ChainMap,
ChainName,
ControllerApp,
MultiProvider,
objMap,
} from '@abacus-network/sdk';
@ -30,18 +30,18 @@ interface DomainedCall {
call: Call;
}
export class AbacusCoreGovernor<
export class AbacusCoreControllerChecker<
Networks extends ChainName,
> extends AbacusCoreChecker<Networks> {
readonly governance: AbacusGovernance<Networks>;
readonly controllerApp: ControllerApp<Networks>;
constructor(
multiProvider: MultiProvider<Networks>,
app: AbacusCore<Networks>,
governance: AbacusGovernance<Networks>,
controllerApp: ControllerApp<Networks>,
config: ChainMap<Networks, CoreConfig>,
) {
const owners = governance.routerAddresses();
const owners = controllerApp.routerAddresses();
const joinedConfigMap = objMap(config, (network, coreConfig) => {
return {
...coreConfig,
@ -49,7 +49,7 @@ export class AbacusCoreGovernor<
};
});
super(multiProvider, app, joinedConfigMap);
this.governance = governance;
this.controllerApp = controllerApp;
}
async check(): Promise<void[]> {
@ -58,7 +58,7 @@ export class AbacusCoreGovernor<
this.violations.map((v) => this.handleViolation(v)),
);
txs.map((call) =>
this.governance.pushCall(call.network as Networks, call.call),
this.controllerApp.pushCall(call.network as Networks, call.call),
);
return [];
}
@ -136,7 +136,7 @@ export class AbacusCoreGovernor<
expectCalls(networks: Networks[], count: number[]) {
expect(networks).to.have.lengthOf(count.length);
networks.forEach((network, i) => {
expect(this.governance.getCalls(network)).to.have.lengthOf(count[i]);
expect(this.controllerApp.getCalls(network)).to.have.lengthOf(count[i]);
});
}
}

@ -1,2 +1,2 @@
export { AbacusCoreChecker, CoreViolationType } from './check';
export { AbacusCoreGovernor } from './govern';
export { AbacusCoreControllerChecker } from './control';

@ -1,3 +0,0 @@
export { AbacusGovernanceDeployer } from './deploy';
export { AbacusGovernanceChecker } from './check';
export { GovernanceConfigAddresses, GovernanceConfig } from './types';

@ -1,10 +0,0 @@
import { RouterConfig } from '@abacus-network/deploy';
import { types } from '@abacus-network/utils';
export type GovernanceConfigAddresses = {
recoveryManager: types.Address;
governor?: types.Address;
};
export type GovernanceConfig = RouterConfig &
GovernanceConfigAddresses & { recoveryTimelock: number };

@ -3,40 +3,36 @@ import path from 'path';
import {
AbacusCore,
AbacusGovernance,
ChainMap,
GovernanceAddresses,
ControllerAddresses,
ControllerApp,
MultiProvider,
} from '@abacus-network/sdk';
import { TestNetworks } from '../config/environments/test/domains';
import { getCoreEnvironmentConfig } from '../scripts/utils';
import {
AbacusGovernanceChecker,
AbacusGovernanceDeployer,
GovernanceConfig,
} from '../src/governance';
ControllerChecker,
ControllerConfig,
ControllerDeployer,
} from '../src/controller';
describe('governance', async () => {
describe('controller', async () => {
const environment = 'test';
let multiProvider: MultiProvider<TestNetworks>;
let deployer: AbacusGovernanceDeployer<TestNetworks>;
let addresses: ChainMap<TestNetworks, GovernanceAddresses>;
let governanceConfig: ChainMap<TestNetworks, GovernanceConfig>;
let deployer: ControllerDeployer<TestNetworks>;
let addresses: ChainMap<TestNetworks, ControllerAddresses>;
let controllerConfig: ChainMap<TestNetworks, ControllerConfig>;
before(async () => {
const config = getCoreEnvironmentConfig(environment);
governanceConfig = config.governance;
controllerConfig = config.controller;
multiProvider = await config.getMultiProvider();
const core = AbacusCore.fromEnvironment(environment, multiProvider);
console.log(core);
deployer = new AbacusGovernanceDeployer(
multiProvider,
governanceConfig,
core,
);
deployer = new ControllerDeployer(multiProvider, controllerConfig, core);
});
it('deploys', async () => {
@ -44,17 +40,17 @@ describe('governance', async () => {
});
it('writes', async () => {
const base = './test/outputs/governance';
const base = './test/outputs/controller';
deployer.writeVerification(path.join(base, 'verification'));
deployer.writeContracts(addresses, path.join(base, 'contracts.ts'));
});
it('checks', async () => {
const governance = new AbacusGovernance(addresses, multiProvider);
const checker = new AbacusGovernanceChecker(
const controller = new ControllerApp(addresses, multiProvider);
const checker = new ControllerChecker(
multiProvider,
governance,
governanceConfig,
controller,
controllerConfig,
);
await checker.check();
});

@ -1,4 +1,4 @@
import { GovernanceContracts } from '.';
import { ControllerContracts } from '.';
import { Call } from '..';
import { ethers } from 'ethers';
@ -9,32 +9,32 @@ import { MultiProvider } from '../provider';
import { ChainMap, ChainName, ChainNameToDomainId } from '../types';
import { objMap, promiseObjAll } from '../utils';
import { GovernanceAddresses } from './contracts';
import { ControllerAddresses } from './contracts';
import { environments } from './environments';
type Environments = typeof environments;
type EnvironmentName = keyof Environments;
export type Governor = {
export type Controller = {
domain: number;
identifier: string;
};
export class AbacusGovernance<
export class ControllerApp<
Networks extends ChainName = ChainName,
> extends AbacusApp<GovernanceContracts, Networks> {
> extends AbacusApp<ControllerContracts, Networks> {
constructor(
networkAddresses: ChainMap<Networks, GovernanceAddresses>,
networkAddresses: ChainMap<Networks, ControllerAddresses>,
multiProvider: MultiProvider<Networks>,
) {
super(GovernanceContracts, networkAddresses, multiProvider);
super(ControllerContracts, networkAddresses, multiProvider);
}
static fromEnvironment(
name: EnvironmentName,
multiProvider: MultiProvider<any>,
) {
return new AbacusGovernance(environments[name], multiProvider);
return new ControllerApp(environments[name], multiProvider);
}
pushCall(network: Networks, call: Call) {
@ -54,32 +54,32 @@ export class AbacusGovernance<
routerAddresses = () => objMap(this.routers(), (_, r) => r.address);
governor = async (): Promise<{
controller = async (): Promise<{
network: Networks;
address: types.Address;
}> => {
const governors = await promiseObjAll(
objMap(this.routers(), (network, router) => router.governor()),
const controllers = await promiseObjAll(
objMap(this.routers(), (network, router) => router.controller()),
);
const match = Object.entries(governors).find(
([_, governor]) => governor !== ethers.constants.AddressZero,
const match = Object.entries(controllers).find(
([_, controller]) => controller !== ethers.constants.AddressZero,
) as [Networks, types.Address] | undefined;
if (match) {
return { network: match[0], address: match[1] };
}
throw new Error('No governor found');
throw new Error('No controller found');
};
build = async (): Promise<ethers.PopulatedTransaction[]> => {
const governor = await this.governor();
const governorRouter = this.routers()[governor.network];
const controller = await this.controller();
const controllerRouter = this.routers()[controller.network];
const networkTransactions = await promiseObjAll(
objMap(this.networkCalls(), (network, calls) => {
if (network === governor.network) {
return governorRouter.populateTransaction.call(calls);
if (network === controller.network) {
return controllerRouter.populateTransaction.call(calls);
} else {
return governorRouter.populateTransaction.callRemote(
return controllerRouter.populateTransaction.callRemote(
ChainNameToDomainId[network],
calls,
);
@ -90,12 +90,12 @@ export class AbacusGovernance<
};
execute = async (signer: ethers.Signer) => {
const governor = await this.governor();
const controller = await this.controller();
const signerAddress = await signer.getAddress();
if (signerAddress !== governor.address) {
if (signerAddress !== controller.address) {
throw new Error(
`Signer ${signerAddress} is not the governor ${governor.address}`,
`Signer ${signerAddress} is not the controller ${controller.address}`,
);
}
@ -113,10 +113,10 @@ export class AbacusGovernance<
provider: ethers.providers.Provider,
): Promise<ethers.BigNumber[]> => {
const transactions = await this.build();
const governor = await this.governor();
const controller = await this.controller();
return Promise.all(
transactions.map(
(tx) => provider.estimateGas({ ...tx, from: governor.address }), // Estimate gas as the governor
(tx) => provider.estimateGas({ ...tx, from: controller.address }), // Estimate gas as the controller
),
);
};

@ -1,6 +1,6 @@
import { Call } from '..';
import { GovernanceRouter__factory } from '@abacus-network/apps';
import { ControllerRouter__factory } from '@abacus-network/apps';
import { UpgradeBeaconController__factory } from '@abacus-network/core';
import { types } from '@abacus-network/utils';
@ -9,32 +9,32 @@ import { ProxiedAddress } from '../types';
import { normalizeCall } from './utils';
export type GovernanceAddresses = {
export type ControllerAddresses = {
// Basically copy RouterAddresses
abacusConnectionManager: types.Address;
router: ProxiedAddress;
upgradeBeaconController: types.Address;
};
export const governanceFactories = {
export const controllerFactories = {
...routerFactories,
upgradeBeaconController: UpgradeBeaconController__factory.connect,
router: GovernanceRouter__factory.connect,
router: ControllerRouter__factory.connect,
};
export type GovernanceFactories = typeof governanceFactories;
export type ControllerFactories = typeof controllerFactories;
export class GovernanceContracts extends AbacusContracts<
GovernanceAddresses,
GovernanceFactories
export class ControllerContracts extends AbacusContracts<
ControllerAddresses,
ControllerFactories
> {
// necessary for factories be defined in the constructor
factories() {
return governanceFactories;
return controllerFactories;
}
calls: Call[] = [];
push = (call: Call) => this.calls.push(normalizeCall(call));
router = this.contracts.router;
governor = () => this.router.governor();
controller = () => this.router.controller();
}

@ -0,0 +1,4 @@
export { ControllerApp } from './app';
export { ControllerAddresses, ControllerContracts } from './contracts';
export { environments as controllerEnvironments } from './environments';
export { Call } from './utils';

@ -15,7 +15,7 @@ export function byteLength(bytesLike: ethers.utils.BytesLike): number {
}
/**
* Serialize a call to its packed Abacus governance representation
* Serialize a call to its packed ControllerMessage representation
* @param call The function call to serialize
* @returns The serialized function call, as a '0x'-prepended hex string
*/

@ -1,4 +0,0 @@
export { AbacusGovernance } from './app';
export { GovernanceAddresses, GovernanceContracts } from './contracts';
export { environments as governanceEnvironments } from './environments';
export { Call } from './utils';

@ -39,12 +39,12 @@ export {
TokenPriceGetter,
} from './gas';
export {
AbacusGovernance,
ControllerApp,
Call,
GovernanceAddresses,
GovernanceContracts,
governanceEnvironments,
} from './governance';
ControllerAddresses,
ControllerContracts,
controllerEnvironments,
} from './controller';
export { DomainConnection, IDomainConnection, MultiProvider } from './provider';
export {
AllChains,

Loading…
Cancel
Save