Skip to content

Commit

Permalink
Aggregation hook deployer (#2769)
Browse files Browse the repository at this point in the history
Co-authored-by: Yorke Rhodes <[email protected]>
fixes hyperlane-xyz/issues#624
  • Loading branch information
aroralanuk authored Oct 5, 2023
1 parent 388824d commit d69d76a
Show file tree
Hide file tree
Showing 34 changed files with 427 additions and 285 deletions.
4 changes: 4 additions & 0 deletions solidity/contracts/Mailbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ contract Mailbox is IMailbox, Indexed, Versioned, OwnableUpgradeable {

/// INTERACTIONS ///
uint256 requiredValue = requiredHook.quoteDispatch(metadata, message);
// if underpaying, defer to required hook's reverting behavior
if (msg.value < requiredValue) {
requiredValue = msg.value;
}
requiredHook.postDispatch{value: requiredValue}(metadata, message);
hook.postDispatch{value: msg.value - requiredValue}(metadata, message);

Expand Down
2 changes: 1 addition & 1 deletion solidity/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module.exports = {
typechain: {
outDir: './types',
target: 'ethers-v5',
alwaysGenerateOverloads: false,
alwaysGenerateOverloads: true,
},
mocha: {
bail: true,
Expand Down
2 changes: 1 addition & 1 deletion typescript/helloworld/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ module.exports = {
typechain: {
outDir: './src/types',
target: 'ethers-v5',
alwaysGenerateOverloads: false, // should overloads with full signatures like deposit(uint256) be generated always, even if there are no overloads?
alwaysGenerateOverloads: true,
},
};
4 changes: 2 additions & 2 deletions typescript/helloworld/src/test/helloworld.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ describe('HelloWorld', async () => {
const body = 'Hello';
await expect(
local.sendHelloWorld(remoteDomain, body, {
value: (await quoteGasPayment(body)).sub(1),
value: 0,
}),
).to.be.revertedWith('insufficient interchain gas payment');
).to.be.revertedWith('StaticProtocolFee: insufficient protocol fee');
});

it('handles a message', async () => {
Expand Down
44 changes: 36 additions & 8 deletions typescript/infra/config/environments/mainnet2/core.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import { ChainMap, CoreConfig, HookType } from '@hyperlane-xyz/sdk';
import { BigNumber, ethers } from 'ethers';

import {
AggregationHookConfig,
ChainMap,
CoreConfig,
HookType,
IgpHookConfig,
MerkleTreeHookConfig,
ProtocolFeeHookConfig,
} from '@hyperlane-xyz/sdk';
import { objMap } from '@hyperlane-xyz/utils';

import { aggregationIsm } from '../../aggregationIsm';
import { Contexts } from '../../contexts';

import { igp } from './igp';
import { owners } from './owners';

export const core: ChainMap<CoreConfig> = objMap(owners, (local, owner) => {
Expand All @@ -23,15 +34,32 @@ export const core: ChainMap<CoreConfig> = objMap(owners, (local, owner) => {
};
}

const merkleHook: MerkleTreeHookConfig = {
type: HookType.MERKLE_TREE,
};

const igpHook: IgpHookConfig = {
type: HookType.INTERCHAIN_GAS_PAYMASTER,
...igp[local],
};

const defaultHook: AggregationHookConfig = {
type: HookType.AGGREGATION,
hooks: [merkleHook, igpHook],
};

const requiredHook: ProtocolFeeHookConfig = {
type: HookType.PROTOCOL_FEE,
maxProtocolFee: ethers.utils.parseUnits('1', 'gwei'), // 1 gwei of native token
protocolFee: BigNumber.from(1), // 1 wei
beneficiary: owner,
owner,
};

return {
owner,
upgrade,
defaultIsm,
defaultHook: {
type: HookType.INTERCHAIN_GAS_PAYMASTER,
},
requiredHook: {
type: HookType.MERKLE_TREE,
},
defaultHook,
requiredHook,
};
});
22 changes: 11 additions & 11 deletions typescript/infra/config/environments/mainnet2/igp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
import { exclude, objMap } from '@hyperlane-xyz/utils';

import { MainnetChains, supportedChainNames } from './chains';
import { core } from './core';
import { owners } from './owners';

// TODO: make this generic
Expand All @@ -25,20 +24,21 @@ function getGasOracles(local: MainnetChains) {
}

export const igp: ChainMap<IgpConfig> = objMap(owners, (chain, owner) => {
const overhead = Object.fromEntries(
exclude(chain, supportedChainNames).map((remote) => [
remote,
multisigIsmVerificationCost(
defaultMultisigIsmConfigs[remote].threshold,
defaultMultisigIsmConfigs[remote].validators.length,
),
]),
);

return {
owner,
oracleKey: DEPLOYER_ADDRESS,
beneficiary: KEY_FUNDER_ADDRESS,
gasOracleType: getGasOracles(chain),
overhead: Object.fromEntries(
exclude(chain, supportedChainNames).map((remote) => [
remote,
multisigIsmVerificationCost(
defaultMultisigIsmConfigs[remote].threshold,
defaultMultisigIsmConfigs[remote].validators.length,
),
]),
),
upgrade: core[chain].upgrade,
overhead,
};
});
37 changes: 31 additions & 6 deletions typescript/infra/config/environments/test/core.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { BigNumber, ethers } from 'ethers';

import {
AggregationHookConfig,
ChainMap,
CoreConfig,
HookType,
IgpHookConfig,
MerkleTreeHookConfig,
ModuleType,
RoutingIsmConfig,
} from '@hyperlane-xyz/sdk';
import { ProtocolFeeHookConfig } from '@hyperlane-xyz/sdk/src/hook/types';
import { objMap } from '@hyperlane-xyz/utils';

import { aggregationIsm } from './aggregationIsm';
import { igp } from './igp';
import { chainToValidator } from './multisigIsm';
import { owners } from './owners';

Expand All @@ -22,14 +29,32 @@ export const core: ChainMap<CoreConfig> = objMap(owners, (local, owner) => {
),
};

const merkleHook: MerkleTreeHookConfig = {
type: HookType.MERKLE_TREE,
};

const igpHook: IgpHookConfig = {
type: HookType.INTERCHAIN_GAS_PAYMASTER,
...igp[local],
};

const defaultHook: AggregationHookConfig = {
type: HookType.AGGREGATION,
hooks: [merkleHook, igpHook],
};

const requiredHook: ProtocolFeeHookConfig = {
type: HookType.PROTOCOL_FEE,
maxProtocolFee: ethers.utils.parseUnits('1', 'gwei'), // 1 gwei of native token
protocolFee: BigNumber.from(1), // 1 wei
beneficiary: owner,
owner,
};

return {
owner,
defaultIsm,
defaultHook: {
type: HookType.INTERCHAIN_GAS_PAYMASTER,
},
requiredHook: {
type: HookType.MERKLE_TREE,
},
defaultHook,
requiredHook,
};
});
16 changes: 0 additions & 16 deletions typescript/infra/config/environments/test/hooks.ts

This file was deleted.

19 changes: 10 additions & 9 deletions typescript/infra/config/environments/test/igp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@ function getGasOracles(local: TestChains) {
}

export const igp: ChainMap<IgpConfig> = objMap(owners, (chain, owner) => {
const overhead = Object.fromEntries(
exclude(chain, chainNames).map((remote) => [
remote,
multisigIsmVerificationCost(
multisigIsm[remote].threshold,
multisigIsm[remote].validators.length,
),
]),
);
return {
owner,
oracleKey: owner,
beneficiary: owner,
gasOracleType: getGasOracles(chain),
overhead: Object.fromEntries(
exclude(chain, chainNames).map((remote) => [
remote,
multisigIsmVerificationCost(
multisigIsm[remote].threshold,
multisigIsm[remote].validators.length,
),
]),
),
overhead,
};
});
2 changes: 0 additions & 2 deletions typescript/infra/config/environments/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { agents } from './agent';
import { testConfigs } from './chains';
import { core } from './core';
import { storageGasOracleConfig } from './gas-oracle';
import { merkleTree } from './hooks';
import { igp } from './igp';
import { infra } from './infra';
import { owners } from './owners';
Expand All @@ -18,7 +17,6 @@ export const environment: EnvironmentConfig = {
chainMetadataConfigs: testConfigs,
agents,
core,
hook: merkleTree,
igp,
owners,
infra,
Expand Down
44 changes: 37 additions & 7 deletions typescript/infra/config/environments/testnet3/core.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
import { ChainMap, CoreConfig, HookType } from '@hyperlane-xyz/sdk';
import { BigNumber, ethers } from 'ethers';

import {
AggregationHookConfig,
ChainMap,
CoreConfig,
HookType,
IgpHookConfig,
MerkleTreeHookConfig,
ProtocolFeeHookConfig,
} from '@hyperlane-xyz/sdk';
import { objMap } from '@hyperlane-xyz/utils';

import { aggregationIsm } from '../../aggregationIsm';
import { Contexts } from '../../contexts';

import { igp } from './igp';
import { owners } from './owners';

export const core: ChainMap<CoreConfig> = objMap(owners, (local, owner) => {
const defaultIsm = aggregationIsm('testnet3', local, Contexts.Hyperlane);

const merkleHook: MerkleTreeHookConfig = {
type: HookType.MERKLE_TREE,
};

const igpHook: IgpHookConfig = {
type: HookType.INTERCHAIN_GAS_PAYMASTER,
...igp[local],
};

const defaultHook: AggregationHookConfig = {
type: HookType.AGGREGATION,
hooks: [merkleHook, igpHook],
};

const requiredHook: ProtocolFeeHookConfig = {
type: HookType.PROTOCOL_FEE,
maxProtocolFee: ethers.utils.parseUnits('1', 'gwei'), // 1 gwei of native token
protocolFee: BigNumber.from(1), // 1 wei
beneficiary: owner,
owner,
};

return {
owner,
defaultIsm,
defaultHook: {
type: HookType.INTERCHAIN_GAS_PAYMASTER,
},
requiredHook: {
type: HookType.MERKLE_TREE,
},
defaultHook,
requiredHook,
};
});
19 changes: 5 additions & 14 deletions typescript/infra/scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import {
ChainMap,
HyperlaneCoreDeployer,
HyperlaneDeployer,
HyperlaneHookDeployer,
HyperlaneIgpDeployer,
HyperlaneIsmFactory,
HyperlaneIsmFactoryDeployer,
HyperlaneProxyFactoryDeployer,
InterchainAccountDeployer,
InterchainQueryDeployer,
LiquidityLayerDeployer,
Expand Down Expand Up @@ -61,24 +60,16 @@ async function main() {

let config: ChainMap<unknown> = {};
let deployer: HyperlaneDeployer<any, any>;
if (module === Modules.ISM_FACTORY) {
if (module === Modules.PROXY_FACTORY) {
config = objMap(envConfig.core, (_chain) => true);
deployer = new HyperlaneIsmFactoryDeployer(multiProvider);
deployer = new HyperlaneProxyFactoryDeployer(multiProvider);
} else if (module === Modules.CORE) {
config = envConfig.core;
const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
getAddresses(environment, Modules.ISM_FACTORY),
getAddresses(environment, Modules.PROXY_FACTORY),
multiProvider,
);
deployer = new HyperlaneCoreDeployer(multiProvider, ismFactory);
} else if (module === Modules.HOOK) {
if (!envConfig.hook) {
throw new Error(`No hook config for ${environment}`);
}
config = envConfig.hook;
const core = getAddresses(environment, Modules.CORE);
const mailboxes = objMap(core, (_, contracts) => contracts.mailbox);
deployer = new HyperlaneHookDeployer(multiProvider, mailboxes);
} else if (module === Modules.INTERCHAIN_GAS_PAYMASTER) {
config = envConfig.igp;
deployer = new HyperlaneIgpDeployer(multiProvider);
Expand Down Expand Up @@ -123,7 +114,7 @@ async function main() {
true, // use deployer as owner
);
const ismFactory = HyperlaneIsmFactory.fromAddressesMap(
getAddresses(environment, Modules.ISM_FACTORY),
getAddresses(environment, Modules.PROXY_FACTORY),
multiProvider,
);
deployer = new HelloWorldDeployer(multiProvider, ismFactory);
Expand Down
2 changes: 1 addition & 1 deletion typescript/infra/scripts/helloworld/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import {
chainMetadata,
filterAddressesToProtocol,
hyperlaneEnvironments,
hyperlaneEnvironmentsWithSealevel,
igpFactories,
} from '@hyperlane-xyz/sdk';
import { hyperlaneEnvironmentsWithSealevel } from '@hyperlane-xyz/sdk/src';
import { ProtocolType, objMerge } from '@hyperlane-xyz/utils';

import { Contexts } from '../../config/contexts';
Expand Down
Loading

0 comments on commit d69d76a

Please sign in to comment.