diff --git a/DESIGN.md b/DESIGN.md index befb175c..15d3519b 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -56,7 +56,7 @@ Multisig operations demand multi-signatory authorization for proposal execution. ## Axelar Service Governance -Building upon the Interchain Governance Contract, the Service Governance Contract is specifically designed to manage operations that require coordination. By incorporating `MultisigBase`, it introduces the functionality to approve, execute, and cancel multisig proposals, in addition to schedule and cancel TimeLock proposals. This is intended to be used as the owner for services such as the Interchain token service contract, allowing Axelar governance to manage it. +Building upon the Interchain Governance Contract, the Service Governance Contract is specifically designed to manage operations that require coordination. Axelar Service Governance introduces the functionality to approve, execute, and cancel operator proposals, in addition to schedule and cancel TimeLock proposals. This is intended to be used as the owner for services such as the Interchain token service contract, allowing Axelar governance to manage it. ### Service Governance Operations @@ -66,10 +66,10 @@ The contract orchestrates four governance operations: - **Cancel TimeLock Proposal**: Again, similar to Interchain Governance, it cancels an existing governance proposal. -- **Approve Multisig Proposal**: This function enables multisig proposal approval by setting the proposal's approval status to true. It resets any previous voting and signals successful approval via a MultisigApproved event. +- **Approve Operator Proposal**: This function enables operator proposal approval by setting the proposal's approval status to true. It resets any previous voting and signals successful approval via a OperatorProposalApproved event. -- **Cancel Multisig Approval**: Cancels an approved multisig proposal, setting the approval status of the proposal to false and indicating successful cancellation through a `MultisigCancelled` event. +- **Cancel Operator Approval**: Cancels an approved operator proposal, setting the approval status of the proposal to false and indicating successful cancellation through a `OperatorProposalCancelled` event. -### Secure Execution of Multisig Proposals +### Secure Execution of Operator Proposals -Each time a new multisig proposal receives approval from governance, the multisig voting count is reset to 0. This ensures that any previous votes on similar proposals will not affect the new proposal. When a multisig proposal gathers the required number of signatory approvals, it becomes ready for execution. Before execution, the contract verifies the proposal's approval status. If the status is set to false, the transaction is reverted. Once executed successfully, the approval status of the proposal is reset, and a MultisigExecuted event gets emitted. +Each time a new operator proposal receives approval from governance, the operator voting count is reset to 0. This ensures that any previous votes on similar proposals will not affect the new proposal. When a operator proposal gathers the required number of signatory approvals, it becomes ready for execution. Before execution, the contract verifies the proposal's approval status. If the status is set to false, the transaction is reverted. Once executed successfully, the approval status of the proposal is reset, and a OperatorProposalExecuted event gets emitted. diff --git a/contracts/governance/AxelarServiceGovernance.sol b/contracts/governance/AxelarServiceGovernance.sol index 158ee1bd..4b5a5cde 100644 --- a/contracts/governance/AxelarServiceGovernance.sol +++ b/contracts/governance/AxelarServiceGovernance.sol @@ -8,27 +8,27 @@ import { InterchainGovernance } from './InterchainGovernance.sol'; /** * @title AxelarServiceGovernance Contract * @dev This contract is part of the Axelar Governance system, it inherits the Interchain Governance contract - * with added functionality to approve and execute multisig proposals. + * with added functionality to approve and execute operator proposals. */ contract AxelarServiceGovernance is InterchainGovernance, IAxelarServiceGovernance { enum ServiceGovernanceCommand { ScheduleTimeLockProposal, CancelTimeLockProposal, - ApproveMultisigProposal, - CancelMultisigApproval + ApproveOperatorProposal, + CancelOperatorApproval } - address public multisig; + address public operator; - mapping(bytes32 => bool) public multisigApprovals; + mapping(bytes32 => bool) public operatorApprovals; - modifier onlyMultisig() { - if (msg.sender != multisig) revert NotAuthorized(); + modifier onlyOperator() { + if (msg.sender != operator) revert NotAuthorized(); _; } - modifier onlyMultisigOrSelf() { - if (msg.sender != multisig && msg.sender != address(this)) revert NotAuthorized(); + modifier onlyOperatorOrSelf() { + if (msg.sender != operator && msg.sender != address(this)) revert NotAuthorized(); _; } @@ -38,67 +38,67 @@ contract AxelarServiceGovernance is InterchainGovernance, IAxelarServiceGovernan * @param governanceChain_ The name of the governance chain * @param governanceAddress_ The address of the governance contract * @param minimumTimeDelay The minimum time delay for timelock operations - * @param multisig_ The multisig contract address + * @param operator_ The operator address */ constructor( address gateway_, string memory governanceChain_, string memory governanceAddress_, uint256 minimumTimeDelay, - address multisig_ + address operator_ ) InterchainGovernance(gateway_, governanceChain_, governanceAddress_, minimumTimeDelay) { - if (multisig_ == address(0)) revert InvalidMultisigAddress(); - multisig = multisig_; + if (operator_ == address(0)) revert InvalidOperator(); + operator = operator_; } /** - * @notice Returns whether a multisig proposal has been approved + * @notice Returns whether an operator proposal has been approved * @param target The address of the contract targeted by the proposal * @param callData The call data to be sent to the target contract * @param nativeValue The amount of native tokens to be sent to the target contract * @return bool True if the proposal has been approved, False otherwise */ - function isMultisigProposalApproved( + function isOperatorProposalApproved( address target, bytes calldata callData, uint256 nativeValue ) external view returns (bool) { - return multisigApprovals[_getProposalHash(target, callData, nativeValue)]; + return operatorApprovals[_getProposalHash(target, callData, nativeValue)]; } /** - * @notice Executes a multisig proposal. + * @notice Executes an operator proposal. * @param target The target address the proposal will call * @param callData The data that encodes the function and arguments to call on the target contract * @param nativeValue The value of native token to be sent to the target contract */ - function executeMultisigProposal( + function executeOperatorProposal( address target, bytes calldata callData, uint256 nativeValue - ) external payable onlyMultisig { + ) external payable onlyOperator { bytes32 proposalHash = _getProposalHash(target, callData, nativeValue); - if (!multisigApprovals[proposalHash]) revert NotApproved(); + if (!operatorApprovals[proposalHash]) revert NotApproved(); - multisigApprovals[proposalHash] = false; + operatorApprovals[proposalHash] = false; - emit MultisigExecuted(proposalHash, target, callData, nativeValue); + emit OperatorProposalExecuted(proposalHash, target, callData, nativeValue); _call(target, callData, nativeValue); } /** - * @notice Transfers the multisig address to a new address - * @dev Only the current multisig or the governance can call this function - * @param newMultisig The new multisig address + * @notice Transfers the operator address to a new address + * @dev Only the current operator or the governance can call this function + * @param newOperator The new operator address */ - function transferMultisig(address newMultisig) external onlyMultisigOrSelf { - if (newMultisig == address(0)) revert InvalidMultisigAddress(); + function transferOperatorship(address newOperator) external onlyOperatorOrSelf { + if (newOperator == address(0)) revert InvalidOperator(); - emit MultisigTransferred(multisig, newMultisig); + emit OperatorshipTransferred(operator, newOperator); - multisig = newMultisig; + operator = newOperator; } /** @@ -128,15 +128,15 @@ contract AxelarServiceGovernance is InterchainGovernance, IAxelarServiceGovernan emit ProposalCancelled(proposalHash, target, callData, nativeValue, eta); return; - } else if (commandType == uint256(ServiceGovernanceCommand.ApproveMultisigProposal)) { - multisigApprovals[proposalHash] = true; + } else if (commandType == uint256(ServiceGovernanceCommand.ApproveOperatorProposal)) { + operatorApprovals[proposalHash] = true; - emit MultisigApproved(proposalHash, target, callData, nativeValue); + emit OperatorProposalApproved(proposalHash, target, callData, nativeValue); return; - } else if (commandType == uint256(ServiceGovernanceCommand.CancelMultisigApproval)) { - multisigApprovals[proposalHash] = false; + } else if (commandType == uint256(ServiceGovernanceCommand.CancelOperatorApproval)) { + operatorApprovals[proposalHash] = false; - emit MultisigCancelled(proposalHash, target, callData, nativeValue); + emit OperatorProposalCancelled(proposalHash, target, callData, nativeValue); return; } else { revert InvalidCommand(); diff --git a/contracts/interfaces/IAxelarServiceGovernance.sol b/contracts/interfaces/IAxelarServiceGovernance.sol index 3d632a03..d658374b 100644 --- a/contracts/interfaces/IAxelarServiceGovernance.sol +++ b/contracts/interfaces/IAxelarServiceGovernance.sol @@ -6,71 +6,71 @@ import { IInterchainGovernance } from './IInterchainGovernance.sol'; /** * @title IAxelarServiceGovernance Interface - * @dev This interface extends IInterchainGovernance and IMultisigBase for multisig proposal actions + * @dev This interface extends IInterchainGovernance for operator proposal actions */ interface IAxelarServiceGovernance is IInterchainGovernance { - error InvalidMultisigAddress(); + error InvalidOperator(); error NotApproved(); error NotAuthorized(); - event MultisigApproved( + event OperatorProposalApproved( bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue ); - event MultisigCancelled( + event OperatorProposalCancelled( bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue ); - event MultisigExecuted( + event OperatorProposalExecuted( bytes32 indexed proposalHash, address indexed targetContract, bytes callData, uint256 nativeValue ); - event MultisigTransferred(address indexed oldMultisig, address indexed newMultisig); + event OperatorshipTransferred(address indexed oldOperator, address indexed newOperator); /** - * @notice Returns whether a multisig proposal has been approved + * @notice Returns whether an operator proposal has been approved * @param proposalHash The hash of the proposal * @return bool True if the proposal has been approved, False otherwise */ - function multisigApprovals(bytes32 proposalHash) external view returns (bool); + function operatorApprovals(bytes32 proposalHash) external view returns (bool); /** - * @notice Returns whether a multisig proposal has been approved + * @notice Returns whether an operator proposal has been approved * @param target The address of the contract targeted by the proposal * @param callData The call data to be sent to the target contract * @param nativeValue The amount of native tokens to be sent to the target contract * @return bool True if the proposal has been approved, False otherwise */ - function isMultisigProposalApproved( + function isOperatorProposalApproved( address target, bytes calldata callData, uint256 nativeValue ) external view returns (bool); /** - * @notice Executes a multisig proposal + * @notice Executes an operator proposal * @param targetContract The target address the proposal will call * @param callData The data that encodes the function and arguments to call on the target contract */ - function executeMultisigProposal( + function executeOperatorProposal( address targetContract, bytes calldata callData, uint256 value ) external payable; /** - * @notice Transfers the multisig address to a new address - * @dev Only the current multisig or the governance can call this function - * @param newMultisig The new multisig address + * @notice Transfers the operator address to a new address + * @dev Only the current operator or the governance can call this function + * @param newOperator The new operator address */ - function transferMultisig(address newMultisig) external; + function transferOperatorship(address newOperator) external; } diff --git a/test/governance/AxelarServiceGovernance.js b/test/governance/AxelarServiceGovernance.js index e4ddb38a..eecee8e6 100644 --- a/test/governance/AxelarServiceGovernance.js +++ b/test/governance/AxelarServiceGovernance.js @@ -13,7 +13,7 @@ describe('AxelarServiceGovernance', () => { let ownerWallet; let governanceAddress; let gateway; - let multisig; + let operator; let serviceGovernanceFactory; let serviceGovernance; @@ -31,12 +31,12 @@ describe('AxelarServiceGovernance', () => { const ScheduleTimeLockProposal = 0; const CancelTimeLockProposal = 1; - const ApproveMultisigProposal = 2; - const CancelMultisigApproval = 3; + const ApproveOperatorProposal = 2; + const CancelOperatorApproval = 3; const InvalidCommand = 4; before(async () => { - [ownerWallet, governanceAddress, multisig] = await ethers.getSigners(); + [ownerWallet, governanceAddress, operator] = await ethers.getSigners(); serviceGovernanceFactory = await ethers.getContractFactory('AxelarServiceGovernance', ownerWallet); targetFactory = await ethers.getContractFactory('Target', ownerWallet); @@ -51,7 +51,7 @@ describe('AxelarServiceGovernance', () => { calldata = targetInterface.encodeFunctionData('callTarget'); serviceGovernance = await serviceGovernanceFactory - .deploy(gateway.address, governanceChain, governanceAddress.address, minimumTimeDelay, multisig.address) + .deploy(gateway.address, governanceChain, governanceAddress.address, minimumTimeDelay, operator.address) .then((d) => d.deployed()); }); @@ -59,10 +59,10 @@ describe('AxelarServiceGovernance', () => { expect(await serviceGovernance.gateway()).to.equal(gateway.address); expect(await serviceGovernance.governanceChain()).to.equal(governanceChain); expect(await serviceGovernance.governanceAddress()).to.equal(governanceAddress.address); - expect(await serviceGovernance.multisig()).to.equal(multisig.address); + expect(await serviceGovernance.operator()).to.equal(operator.address); }); - it('should revert on invalid multisig address', async () => { + it('should revert on invalid operator address', async () => { await expectRevert( async (gasOptions) => serviceGovernanceFactory.deploy( @@ -74,15 +74,15 @@ describe('AxelarServiceGovernance', () => { gasOptions, ), serviceGovernanceFactory, - 'InvalidMultisigAddress', + 'InvalidOperator', ); }); - it('should revert on invalid multisig transfer', async () => { + it('should revert on invalid operator transfer', async () => { await expectRevert( - async (gasOptions) => serviceGovernance.connect(multisig).transferMultisig(AddressZero, gasOptions), + async (gasOptions) => serviceGovernance.connect(operator).transferOperatorship(AddressZero, gasOptions), serviceGovernance, - 'InvalidMultisigAddress', + 'InvalidOperator', ); }); @@ -149,50 +149,50 @@ describe('AxelarServiceGovernance', () => { .withArgs(proposalHash, target, calldata, nativeValue, eta); }); - it('should approve a multisig proposal', async () => { + it('should approve a operator proposal', async () => { const govCommandID = formatBytes32String('4'); const nativeValue = 400; const [payload, proposalHash] = await getPayloadAndProposalHash( - ApproveMultisigProposal, + ApproveOperatorProposal, target, nativeValue, calldata, ); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigApproved') + .to.emit(serviceGovernance, 'OperatorProposalApproved') .withArgs(proposalHash, target, calldata, nativeValue); }); - it('should return whether or not a multisig proposal is approved', async () => { + it('should return whether or not a operator proposal is approved', async () => { const govCommandID = formatBytes32String('5'); const nativeValue = 500; const [payload, proposalHash] = await getPayloadAndProposalHash( - ApproveMultisigProposal, + ApproveOperatorProposal, target, nativeValue, calldata, ); - let isApproved = await serviceGovernance.isMultisigProposalApproved(target, calldata, nativeValue); + let isApproved = await serviceGovernance.isOperatorProposalApproved(target, calldata, nativeValue); expect(isApproved).to.be.false; await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigApproved') + .to.emit(serviceGovernance, 'OperatorProposalApproved') .withArgs(proposalHash, target, calldata, nativeValue); - isApproved = await serviceGovernance.isMultisigProposalApproved(target, calldata, nativeValue); + isApproved = await serviceGovernance.isOperatorProposalApproved(target, calldata, nativeValue); expect(isApproved).to.be.true; }); - it('should re-approve a multisig proposal after cancelling it', async () => { + it('should re-approve a operator proposal after cancelling it', async () => { const govCommandID = formatBytes32String('6'); const nativeValue = 600; const [payload, proposalHash] = await getPayloadAndProposalHash( - ApproveMultisigProposal, + ApproveOperatorProposal, target, nativeValue, calldata, @@ -200,42 +200,42 @@ describe('AxelarServiceGovernance', () => { const payloadCancel = defaultAbiCoder.encode( ['uint256', 'address', 'bytes', 'uint256', 'uint256'], - [CancelMultisigApproval, target, calldata, nativeValue, 0], + [CancelOperatorApproval, target, calldata, nativeValue, 0], ); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigApproved') + .to.emit(serviceGovernance, 'OperatorProposalApproved') .withArgs(proposalHash, target, calldata, nativeValue); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payloadCancel)) - .to.emit(serviceGovernance, 'MultisigCancelled') + .to.emit(serviceGovernance, 'OperatorProposalCancelled') .withArgs(proposalHash, target, calldata, nativeValue); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigApproved') + .to.emit(serviceGovernance, 'OperatorProposalApproved') .withArgs(proposalHash, target, calldata, nativeValue); }); - it('should revert on executing a multisig proposal if called by non-multisig', async () => { + it('should revert on executing a operator proposal if called by non-operator', async () => { await expectRevert( async (gasOptions) => - serviceGovernance.connect(ownerWallet).executeMultisigProposal(target, calldata, 0, gasOptions), + serviceGovernance.connect(ownerWallet).executeOperatorProposal(target, calldata, 0, gasOptions), serviceGovernance, 'NotAuthorized', ); }); - it('should revert on executing a multisig proposal if proposal is not approved', async () => { + it('should revert on executing a operator proposal if proposal is not approved', async () => { await expectRevert( async (gasOptions) => - serviceGovernance.connect(multisig).executeMultisigProposal(target, calldata, 0, gasOptions), + serviceGovernance.connect(operator).executeOperatorProposal(target, calldata, 0, gasOptions), serviceGovernance, 'NotApproved', ); }); - it('should revert on executing a multisig proposal if call to target fails', async () => { - const ApproveMultisigProposal = 2; + it('should revert on executing a operator proposal if call to target fails', async () => { + const ApproveOperatorProposal = 2; const govCommandID = formatBytes32String('7'); const nativeValue = 700; @@ -244,19 +244,19 @@ describe('AxelarServiceGovernance', () => { const invalidCalldata = invalidTargetInterface.encodeFunctionData('set'); const [payload, proposalHash] = await getPayloadAndProposalHash( - ApproveMultisigProposal, + ApproveOperatorProposal, target, nativeValue, invalidCalldata, ); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigApproved') + .to.emit(serviceGovernance, 'OperatorProposalApproved') .withArgs(proposalHash, target, invalidCalldata, nativeValue); await expectRevert( async (gasOptions) => - serviceGovernance.connect(multisig).executeMultisigProposal(target, invalidCalldata, nativeValue, { + serviceGovernance.connect(operator).executeOperatorProposal(target, invalidCalldata, nativeValue, { value: nativeValue, ...gasOptions, }), @@ -265,71 +265,71 @@ describe('AxelarServiceGovernance', () => { ); }); - it('should execute a multisig proposal', async () => { + it('should execute a operator proposal', async () => { const govCommandID = formatBytes32String('8'); const nativeValue = 800; const [payload, proposalHash] = await getPayloadAndProposalHash( - ApproveMultisigProposal, + ApproveOperatorProposal, target, nativeValue, calldata, ); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigApproved') + .to.emit(serviceGovernance, 'OperatorProposalApproved') .withArgs(proposalHash, target, calldata, nativeValue); await expect( serviceGovernance - .connect(multisig) - .executeMultisigProposal(target, calldata, nativeValue, { value: nativeValue }), + .connect(operator) + .executeOperatorProposal(target, calldata, nativeValue, { value: nativeValue }), ) - .to.emit(serviceGovernance, 'MultisigExecuted') + .to.emit(serviceGovernance, 'OperatorProposalExecuted') .withArgs(proposalHash, target, calldata, nativeValue) .and.to.emit(targetContract, 'TargetCalled'); }); - it('should cancel an approved multisig proposal', async () => { + it('should cancel an approved operator proposal', async () => { const govCommandID = formatBytes32String('9'); const nativeValue = 900; let [payload, proposalHash] = await getPayloadAndProposalHash( - ApproveMultisigProposal, + ApproveOperatorProposal, target, nativeValue, calldata, ); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigApproved') + .to.emit(serviceGovernance, 'OperatorProposalApproved') .withArgs(proposalHash, target, calldata, nativeValue); [payload, proposalHash] = await getPayloadAndProposalHash( - CancelMultisigApproval, + CancelOperatorApproval, target, nativeValue, calldata, ); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigCancelled') + .to.emit(serviceGovernance, 'OperatorProposalCancelled') .withArgs(proposalHash, target, calldata, nativeValue); }); - it('should execute a multisig proposal and increase balance of target', async () => { + it('should execute a operator proposal and increase balance of target', async () => { const govCommandID = formatBytes32String('10'); const nativeValue = 1000; const [payload, proposalHash] = await getPayloadAndProposalHash( - ApproveMultisigProposal, + ApproveOperatorProposal, target, nativeValue, calldata, ); await expect(serviceGovernance.execute(govCommandID, governanceChain, governanceAddress.address, payload)) - .to.emit(serviceGovernance, 'MultisigApproved') + .to.emit(serviceGovernance, 'OperatorProposalApproved') .withArgs(proposalHash, target, calldata, nativeValue); await ownerWallet @@ -341,10 +341,10 @@ describe('AxelarServiceGovernance', () => { const oldBalance = await ethers.provider.getBalance(target); - const tx = await serviceGovernance.connect(multisig).executeMultisigProposal(target, calldata, nativeValue); + const tx = await serviceGovernance.connect(operator).executeOperatorProposal(target, calldata, nativeValue); await expect(tx) - .to.emit(serviceGovernance, 'MultisigExecuted') + .to.emit(serviceGovernance, 'OperatorProposalExecuted') .withArgs(proposalHash, target, calldata, nativeValue) .and.to.emit(targetContract, 'TargetCalled'); @@ -352,24 +352,24 @@ describe('AxelarServiceGovernance', () => { expect(newBalance).to.equal(oldBalance.add(nativeValue)); }); - it('should transfer multisig address to new address', async () => { - const newMultisig = governanceAddress.address; - await expect(serviceGovernance.connect(multisig).transferMultisig(newMultisig)) - .to.emit(serviceGovernance, 'MultisigTransferred') - .withArgs(multisig.address, newMultisig); - await expect(await serviceGovernance.multisig()).to.equal(newMultisig); + it('should transfer operator address to new address', async () => { + const newOperator = governanceAddress.address; + await expect(serviceGovernance.connect(operator).transferOperatorship(newOperator)) + .to.emit(serviceGovernance, 'OperatorshipTransferred') + .withArgs(operator.address, newOperator); + await expect(await serviceGovernance.operator()).to.equal(newOperator); await expectRevert( - async (gasOptions) => serviceGovernance.connect(multisig).transferMultisig(newMultisig, gasOptions), + async (gasOptions) => serviceGovernance.connect(operator).transferOperatorship(newOperator, gasOptions), serviceGovernance, 'NotAuthorized', ); }); - it('should transfer multisig by a governance proposal', async () => { + it('should transfer operatorship by a governance proposal', async () => { const govCommandID = formatBytes32String('10'); - const newMultisig = serviceGovernance.address; - const transferCalldata = serviceGovernance.interface.encodeFunctionData('transferMultisig', [newMultisig]); + const newOperator = serviceGovernance.address; + const transferCalldata = serviceGovernance.interface.encodeFunctionData('transferOperatorship', [newOperator]); const [payload, proposalHash, eta] = await getPayloadAndProposalHash( ScheduleTimeLockProposal, @@ -393,14 +393,14 @@ describe('AxelarServiceGovernance', () => { await expect(tx) .to.emit(serviceGovernance, 'ProposalExecuted') .withArgs(proposalHash, serviceGovernance.address, transferCalldata, 0, executionTimestamp) - .and.to.emit(serviceGovernance, 'MultisigTransferred') - .withArgs(governanceAddress.address, newMultisig); + .and.to.emit(serviceGovernance, 'OperatorshipTransferred') + .withArgs(governanceAddress.address, newOperator); - await expect(await serviceGovernance.multisig()).to.equal(newMultisig); + await expect(await serviceGovernance.operator()).to.equal(newOperator); await expectRevert( async (gasOptions) => - serviceGovernance.connect(governanceAddress).transferMultisig(newMultisig, gasOptions), + serviceGovernance.connect(governanceAddress).transferOperatorship(newOperator, gasOptions), serviceGovernance, 'NotAuthorized', ); @@ -411,7 +411,7 @@ describe('AxelarServiceGovernance', () => { const bytecodeHash = keccak256(bytecode); const expected = { - london: '0x4ee32f41f8ec59746ff29e3e6c4f9e3a291868f98caeb21b87de446c3655ce78', + london: '0x87891d8e17e62bddae5afa47c6231b236207b7c9cfff0810bc62b226a3765600', }[getEVMVersion()]; expect(bytecodeHash).to.be.equal(expected);