Make MultisigIsm HIP compliant (#1478)

pull/1480/head
Asa Oines 2 years ago committed by GitHub
parent fdc6de49da
commit 05b2bdc8d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      solidity/contracts/isms/MultisigIsm.sol
  2. 1
      solidity/contracts/test/TestIsm.sol
  3. 16
      solidity/interfaces/IInterchainSecurityModule.sol
  4. 19
      solidity/interfaces/IMultisigIsm.sol
  5. 37
      solidity/test/isms/multisigIsm.test.ts
  6. 1
      typescript/helloworld
  7. 1
      typescript/token
  8. 4
      typescript/utils/src/types.ts
  9. 67
      yarn.lock

@ -25,6 +25,10 @@ contract MultisigIsm is IMultisigIsm, Ownable {
using MultisigIsmMetadata for bytes; using MultisigIsmMetadata for bytes;
using MerkleLib for MerkleLib.Tree; using MerkleLib for MerkleLib.Tree;
// ============ Constants ============
uint8 public constant moduleType = 3;
// ============ Mutable Storage ============ // ============ Mutable Storage ============
/// @notice The validator threshold for each remote domain. /// @notice The validator threshold for each remote domain.
@ -219,6 +223,25 @@ contract MultisigIsm is IMultisigIsm, Ownable {
return _validators; return _validators;
} }
/**
* @notice Returns the set of validators responsible for verifying _message
* and the number of signatures required
* @dev Can change based on the content of _message
* @param _message Hyperlane formatted interchain message
* @return validators The array of validator addresses
* @return threshold The number of validator signatures needed
*/
function validatorsAndThreshold(bytes calldata _message)
external
view
returns (address[] memory, uint8)
{
uint32 _origin = _message.origin();
address[] memory _validators = validators(_origin);
uint8 _threshold = threshold[_origin];
return (_validators, _threshold);
}
/** /**
* @notice Returns the number of validators enrolled in the validator set. * @notice Returns the number of validators enrolled in the validator set.
* @param _domain The remote domain of the validator set. * @param _domain The remote domain of the validator set.

@ -4,6 +4,7 @@ pragma solidity >=0.8.0;
import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol"; import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol";
contract TestIsm is IInterchainSecurityModule { contract TestIsm is IInterchainSecurityModule {
uint8 public constant moduleType = 0;
bool public accept; bool public accept;
function setAccept(bool _val) external { function setAccept(bool _val) external {

@ -2,7 +2,21 @@
pragma solidity >=0.6.11; pragma solidity >=0.6.11;
interface IInterchainSecurityModule { interface IInterchainSecurityModule {
// Called by the Mailbox to determine whether or not the message should be accepted. /**
* @notice Returns an enum that represents the type of security model
* encoded by this ISM.
* @dev Relayers infer how to fetch and format metadata.
*/
function moduleType() external view returns (uint8);
/**
* @notice Defines a security model responsible for verifying interchain
* messages based on the provided metadata.
* @param _metadata Off-chain metadata provided by a relayer, specific to
* the security model encoded by the module (e.g. validator signatures)
* @param _message Hyperlane encoded interchain message
* @return True if the message was verified
*/
function verify(bytes calldata _metadata, bytes calldata _message) function verify(bytes calldata _metadata, bytes calldata _message)
external external
returns (bool); returns (bool);

@ -4,15 +4,16 @@ pragma solidity >=0.6.0;
import {IInterchainSecurityModule} from "./IInterchainSecurityModule.sol"; import {IInterchainSecurityModule} from "./IInterchainSecurityModule.sol";
interface IMultisigIsm is IInterchainSecurityModule { interface IMultisigIsm is IInterchainSecurityModule {
function isEnrolled(uint32 _domain, address _validator) /**
* @notice Returns the set of validators responsible for verifying _message
* and the number of signatures required
* @dev Can change based on the content of _message
* @param _message Hyperlane formatted interchain message
* @return validators The array of validator addresses
* @return threshold The number of validator signatures needed
*/
function validatorsAndThreshold(bytes calldata _message)
external external
view view
returns (bool); returns (address[] memory validators, uint8 threshold);
function threshold(uint32 _domain) external view returns (uint8);
function validators(uint32 _domain)
external
view
returns (address[] memory);
} }

@ -3,7 +3,7 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { expect } from 'chai'; import { expect } from 'chai';
import { ethers } from 'hardhat'; import { ethers } from 'hardhat';
import { Validator, utils } from '@hyperlane-xyz/utils'; import { Validator, types, utils } from '@hyperlane-xyz/utils';
import { import {
TestMailbox, TestMailbox,
@ -13,6 +13,7 @@ import {
TestRecipient__factory, TestRecipient__factory,
} from '../../types'; } from '../../types';
import { import {
dispatchMessage,
dispatchMessageAndReturnMetadata, dispatchMessageAndReturnMetadata,
getCommitment, getCommitment,
signCheckpoint, signCheckpoint,
@ -54,6 +55,14 @@ describe('MultisigIsm', async () => {
}); });
}); });
describe('#moduleType', () => {
it('returns the correct type', async () => {
expect(await multisigIsm.moduleType()).to.equal(
types.InterchainSecurityModuleType.MULTISIG,
);
});
});
describe('#enrollValidators', () => { describe('#enrollValidators', () => {
let validatorAddresses: string[]; let validatorAddresses: string[];
const domains = [ORIGIN_DOMAIN, DESTINATION_DOMAIN]; const domains = [ORIGIN_DOMAIN, DESTINATION_DOMAIN];
@ -317,6 +326,32 @@ describe('MultisigIsm', async () => {
}); });
}); });
describe('#validatorsAndThreshold', () => {
const threshold = 7;
let message: string;
beforeEach(async () => {
await multisigIsm.enrollValidators(
[ORIGIN_DOMAIN],
[validators.map((v) => v.address)],
);
await multisigIsm.setThreshold(ORIGIN_DOMAIN, threshold);
const dispatch = await dispatchMessage(
mailbox,
DESTINATION_DOMAIN,
utils.addressToBytes32(multisigIsm.address),
'hello',
);
message = dispatch.message;
});
it('returns the validators and threshold', async () => {
expect(await multisigIsm.validatorsAndThreshold(message)).to.deep.equal([
validators.map((v) => v.address),
threshold,
]);
});
});
describe('#validatorCount', () => { describe('#validatorCount', () => {
beforeEach(async () => { beforeEach(async () => {
// Must be done sequentially so gas estimation is correct. // Must be done sequentially so gas estimation is correct.

@ -1 +0,0 @@
Subproject commit 646f1e7beb18a77e5ca2535dba130f75793aea0f

@ -1 +0,0 @@
Subproject commit a294fdf5ea498a018178fd90744c9c09276d9686

@ -58,3 +58,7 @@ export type ParsedMultisigIsmMetadata = {
signatures: ethers.utils.BytesLike[]; signatures: ethers.utils.BytesLike[];
validators: ethers.utils.BytesLike[]; validators: ethers.utils.BytesLike[];
}; };
export enum InterchainSecurityModuleType {
MULTISIG = 3,
}

@ -3713,71 +3713,16 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@hyperlane-xyz/helloworld@1.0.0-beta3, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": "@hyperlane-xyz/helloworld@npm:1.0.0-beta3":
version: 0.0.0-use.local version: 1.0.0-beta3
resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" resolution: "@hyperlane-xyz/helloworld@npm:1.0.0-beta3"
dependencies: dependencies:
"@hyperlane-xyz/sdk": 1.0.0-beta3 "@hyperlane-xyz/sdk": 1.0.0-beta3
"@nomiclabs/hardhat-ethers": ^2.0.5
"@nomiclabs/hardhat-waffle": ^2.0.2
"@openzeppelin/contracts-upgradeable": ^4.8.0 "@openzeppelin/contracts-upgradeable": ^4.8.0
"@trivago/prettier-plugin-sort-imports": ^3.2.0
"@typechain/ethers-v5": 10.0.0
"@typechain/hardhat": ^6.0.0
"@types/mocha": ^9.1.0
"@typescript-eslint/eslint-plugin": ^5.27.0
"@typescript-eslint/parser": ^5.27.0
chai: ^4.3.0
eslint: ^8.16.0
eslint-config-prettier: ^8.5.0
ethereum-waffle: ^3.4.4
ethers: ^5.6.8 ethers: ^5.6.8
hardhat: ^2.8.4 checksum: ee13cfc499f1ed636b3d05151bff5316737f87189551f517fb9781838c68dd48eb89c1f353994f2728d0e8e8d8303f2a7c83ffca03ef931f1e859065596c747f
hardhat-gas-reporter: ^1.0.7 languageName: node
prettier: ^2.4.1 linkType: hard
prettier-plugin-solidity: ^1.0.0-beta.5
solhint: ^3.3.2
solhint-plugin-prettier: ^0.0.5
solidity-coverage: ^0.7.14
ts-node: ^10.8.0
typechain: 8.0.0
typescript: ^4.7.2
languageName: unknown
linkType: soft
"@hyperlane-xyz/hyperlane-token@workspace:typescript/token":
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/hyperlane-token@workspace:typescript/token"
dependencies:
"@hyperlane-xyz/core": 1.0.0-beta3
"@hyperlane-xyz/sdk": 1.0.0-beta3
"@hyperlane-xyz/utils": 1.0.0-beta3
"@nomiclabs/hardhat-ethers": ^2.0.5
"@nomiclabs/hardhat-waffle": ^2.0.2
"@openzeppelin/contracts-upgradeable": ^4.8.0
"@trivago/prettier-plugin-sort-imports": ^3.2.0
"@typechain/ethers-v5": 10.0.0
"@typechain/hardhat": ^6.0.0
"@types/mocha": ^9.1.0
"@typescript-eslint/eslint-plugin": ^5.27.0
"@typescript-eslint/parser": ^5.27.0
chai: ^4.3.0
eslint: ^8.16.0
eslint-config-prettier: ^8.5.0
ethereum-waffle: ^3.4.4
ethers: ^5.6.8
hardhat: ^2.8.4
hardhat-gas-reporter: ^1.0.7
prettier: ^2.4.1
prettier-plugin-solidity: ^1.0.0-beta.5
solhint: ^3.3.2
solhint-plugin-prettier: ^0.0.5
solidity-coverage: ^0.7.14
ts-node: ^10.8.0
typechain: 8.0.0
typescript: ^4.7.2
languageName: unknown
linkType: soft
"@hyperlane-xyz/infra@workspace:typescript/infra": "@hyperlane-xyz/infra@workspace:typescript/infra":
version: 0.0.0-use.local version: 0.0.0-use.local

Loading…
Cancel
Save