The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hyperlane-monorepo/solidity/optics-core/lib/index.js

237 lines
5.8 KiB

require('@nomiclabs/hardhat-waffle');
const { assert } = require('chai');
const { extendEnvironment } = require('hardhat/config');
const {
deployUpgradeSetup,
deployUpgradeSetupAndProxy,
deployImplementation,
deployUpgradeBeaconController,
deployProxyWithImplementation,
getInitializeData,
} = require('../scripts/deployUpgradeSetup');
const { deployOptics } = require('../scripts/deployOptics');
const HomeAbi = require('../../../abis/Home.abi.json');
const ReplicaAbi = require('../../../abis/Replica.abi.json');
extendEnvironment((hre) => {
let { ethers } = hre;
const State = {
UNINITIALIZED: 0,
ACTIVE: 1,
FAILED: 2,
};
test: cross chain governance (#312) * fix: OpticsIdentifier as_ref casts ethereum address conditionally * feature: adds GovernanceRouter test boilerplate and fixes ConnectionManager test setup * test: adds testProcess and revert message utility * test: adds test for handle revert with unenrolled replica * test: adds test for reverting in handle on nonGovernorRouter message * rename: formattedMessage --> opticsMessage * prog: blocked on incorrect setting of governorDomain = localDomain * fix: fix after domainHash rebase * test: adds success case transfer governor test * test: adds setRouter message success case * prog: Call message success case failing due to datalen mismatches * prog: storing in dynamic struct array reverts silently * add: initial setup * add: transfer governorship test * add: signUpdate * refactor: combine bridgerouter tests * fix: cast to address, set sequence * delete: old gov router tests * Fix transfer governor test * fix: debug call storage, get sequence * fix: bad merge rust code * revert: stale changes * refactor: nits, create thirdDomain/thirdRouter vars * refactor: extract some code into formatOpticsMessage * refactor: formatOpticsMessage * refactor: deployOptics and devDeployOptics * fix: bug, clean up code * lint * fix: add numCalls (#315) * fix: initial stab at adding numCalls * debugging: numCall type conversion * fix: read _numCalls from bytes29 * use MSG_PREFIX_LEN * clean: remove unused imports * fix: data bug, refactor a bit * add: Transaction reverted silently * fix: bug in formatCalls * refactor: formatCalls * add: check ret value for testProcess from GovernorRouter * enhance: more explicit naming * rename: BYTE_LEN to NUM_ITEMS * slow down turbo * enhance: assign _numCalls variable Co-authored-by: Luke Tchang <ltchang@stanford.edu> Co-authored-by: anna-caroll <anna.s.carroll@gmail.com>
4 years ago
const GovernanceMessage = {
CALL: 1,
TRANSFERGOVERNOR: 2,
SETROUTER: 3,
};
const MessageStatus = {
NONE: 0,
PENDING: 1,
PROCESSED: 2,
};
class Common extends ethers.Contract {
constructor(address, abi, providerOrSigner) {
super(address, abi, providerOrSigner);
}
async submitDoubleUpdate(left, right) {
if (left.oldRoot !== right.oldRoot) {
throw new Error('Old roots do not match');
}
return await this.doubleUpdate(
right.oldRoot,
[left.newRoot, right.newRoot],
left.signature,
right.signature,
);
}
}
class Home extends Common {
constructor(address, providerOrSigner) {
super(address, HomeAbi, providerOrSigner);
}
async submitSignedUpdate(update) {
return await this.update(
update.oldRoot,
update.newRoot,
update.signature,
);
}
// Returns list of Dispatch events with given destination and sequence
async dispatchByDestinationAndSequence(destination, sequence) {
const filter = this.filters.Dispatch(
null,
destinationAndSequence(destination, sequence),
);
return await this.queryFilter(filter);
}
}
class Replica extends Common {
constructor(address, providerOrSigner) {
super(address, ReplicaAbi, providerOrSigner);
}
async submitSignedUpdate(update) {
return await this.update(
update.oldRoot,
update.newRoot,
update.signature,
);
}
}
test: cross chain governance (#312) * fix: OpticsIdentifier as_ref casts ethereum address conditionally * feature: adds GovernanceRouter test boilerplate and fixes ConnectionManager test setup * test: adds testProcess and revert message utility * test: adds test for handle revert with unenrolled replica * test: adds test for reverting in handle on nonGovernorRouter message * rename: formattedMessage --> opticsMessage * prog: blocked on incorrect setting of governorDomain = localDomain * fix: fix after domainHash rebase * test: adds success case transfer governor test * test: adds setRouter message success case * prog: Call message success case failing due to datalen mismatches * prog: storing in dynamic struct array reverts silently * add: initial setup * add: transfer governorship test * add: signUpdate * refactor: combine bridgerouter tests * fix: cast to address, set sequence * delete: old gov router tests * Fix transfer governor test * fix: debug call storage, get sequence * fix: bad merge rust code * revert: stale changes * refactor: nits, create thirdDomain/thirdRouter vars * refactor: extract some code into formatOpticsMessage * refactor: formatOpticsMessage * refactor: deployOptics and devDeployOptics * fix: bug, clean up code * lint * fix: add numCalls (#315) * fix: initial stab at adding numCalls * debugging: numCall type conversion * fix: read _numCalls from bytes29 * use MSG_PREFIX_LEN * clean: remove unused imports * fix: data bug, refactor a bit * add: Transaction reverted silently * fix: bug in formatCalls * refactor: formatCalls * add: check ret value for testProcess from GovernorRouter * enhance: more explicit naming * rename: BYTE_LEN to NUM_ITEMS * slow down turbo * enhance: assign _numCalls variable Co-authored-by: Luke Tchang <ltchang@stanford.edu> Co-authored-by: anna-caroll <anna.s.carroll@gmail.com>
4 years ago
class GovernanceRouter {
static formatTransferGovernor(newDomain, newAddress) {
return ethers.utils.solidityPack(
['bytes1', 'uint32', 'bytes32'],
[GovernanceMessage.TRANSFERGOVERNOR, newDomain, newAddress],
);
}
static formatSetRouter(domain, address) {
return ethers.utils.solidityPack(
['bytes1', 'uint32', 'bytes32'],
[GovernanceMessage.SETROUTER, domain, address],
);
}
static formatCalls(callsData) {
let callBody = '0x';
const numCalls = callsData.length;
for (let i = 0; i < numCalls; i++) {
const { to, dataLen, data } = callsData[i];
if (!to || !dataLen || !data) {
throw new Error(`Missing data in Call ${i + 1}: \n ${callsData[i]}`);
}
let hexBytes = ethers.utils.solidityPack(
['bytes32', 'uint256', 'bytes'],
[to, dataLen, data],
);
// remove 0x before appending
callBody += hexBytes.slice(2);
}
return ethers.utils.solidityPack(
['bytes1', 'bytes1', 'bytes'],
[GovernanceMessage.CALL, numCalls, callBody],
);
}
}
class Updater {
constructor(signer, address, localDomain, disableWarn) {
if (!disableWarn) {
throw new Error('Please use `Updater.fromSigner()` to instantiate.');
}
this.localDomain = localDomain ? localDomain : 0;
this.signer = signer;
this.address = address;
}
static async fromSigner(signer, localDomain) {
return new Updater(signer, await signer.getAddress(), localDomain, true);
}
domain() {
return ethers.utils.solidityKeccak256(
['uint32', 'string'],
[this.localDomain, 'OPTICS'],
);
}
message(oldRoot, newRoot) {
return ethers.utils.concat([this.domain(), oldRoot, newRoot]);
}
async signUpdate(oldRoot, newRoot) {
let message = this.message(oldRoot, newRoot);
let msgHash = ethers.utils.arrayify(ethers.utils.keccak256(message));
let signature = await this.signer.signMessage(msgHash);
return {
origin: this.localDomain,
oldRoot,
newRoot,
signature,
};
}
}
const formatMessage = (
localDomain,
senderAddr,
sequence,
destinationDomain,
recipientAddr,
body,
) => {
senderAddr = optics.ethersAddressToBytes32(senderAddr);
recipientAddr = optics.ethersAddressToBytes32(recipientAddr);
return ethers.utils.solidityPack(
['uint32', 'bytes32', 'uint32', 'uint32', 'bytes32', 'bytes'],
[
localDomain,
senderAddr,
sequence,
destinationDomain,
recipientAddr,
body,
],
);
};
const messageToLeaf = (message) => {
return ethers.utils.solidityKeccak256(['bytes'], [message]);
};
const ethersAddressToBytes32 = (address) => {
return ethers.utils
.hexZeroPad(ethers.utils.hexStripZeros(address), 32)
.toLowerCase();
};
const destinationAndSequence = (destination, sequence) => {
assert(destination < Math.pow(2, 32) - 1);
assert(sequence < Math.pow(2, 32) - 1);
return ethers.BigNumber.from(destination)
.mul(ethers.BigNumber.from(2).pow(32))
.add(ethers.BigNumber.from(sequence));
};
hre.optics = {
State,
MessageStatus,
Common,
Home,
Replica,
test: cross chain governance (#312) * fix: OpticsIdentifier as_ref casts ethereum address conditionally * feature: adds GovernanceRouter test boilerplate and fixes ConnectionManager test setup * test: adds testProcess and revert message utility * test: adds test for handle revert with unenrolled replica * test: adds test for reverting in handle on nonGovernorRouter message * rename: formattedMessage --> opticsMessage * prog: blocked on incorrect setting of governorDomain = localDomain * fix: fix after domainHash rebase * test: adds success case transfer governor test * test: adds setRouter message success case * prog: Call message success case failing due to datalen mismatches * prog: storing in dynamic struct array reverts silently * add: initial setup * add: transfer governorship test * add: signUpdate * refactor: combine bridgerouter tests * fix: cast to address, set sequence * delete: old gov router tests * Fix transfer governor test * fix: debug call storage, get sequence * fix: bad merge rust code * revert: stale changes * refactor: nits, create thirdDomain/thirdRouter vars * refactor: extract some code into formatOpticsMessage * refactor: formatOpticsMessage * refactor: deployOptics and devDeployOptics * fix: bug, clean up code * lint * fix: add numCalls (#315) * fix: initial stab at adding numCalls * debugging: numCall type conversion * fix: read _numCalls from bytes29 * use MSG_PREFIX_LEN * clean: remove unused imports * fix: data bug, refactor a bit * add: Transaction reverted silently * fix: bug in formatCalls * refactor: formatCalls * add: check ret value for testProcess from GovernorRouter * enhance: more explicit naming * rename: BYTE_LEN to NUM_ITEMS * slow down turbo * enhance: assign _numCalls variable Co-authored-by: Luke Tchang <ltchang@stanford.edu> Co-authored-by: anna-caroll <anna.s.carroll@gmail.com>
4 years ago
GovernanceRouter,
Updater,
formatMessage,
messageToLeaf,
ethersAddressToBytes32,
destinationAndSequence,
deployUpgradeSetupAndProxy,
deployImplementation,
deployUpgradeBeaconController,
deployUpgradeSetup,
deployOptics,
deployProxyWithImplementation,
getInitializeData,
};
});