Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: modify gas oracle TS tooling to be friendly for all protocol types #5198

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
820e1af
it aint pretty and it dont work, but it sorta works
tkporter Jan 14, 2025
12b2caf
printing gas oracles mostly works, gonna do a little cleanup
tkporter Jan 14, 2025
ee4c7c9
a little cweanup
tkporter Jan 14, 2025
e080a97
some cleanup, getting there
tkporter Jan 15, 2025
b80f703
Merge branch 'main' of github.com:abacus-network/abacus-monorepo into…
tkporter Jan 15, 2025
9dd4108
it's hideous but seemingly works
tkporter Jan 15, 2025
06d0a02
Merge branch 'main' of github.com:abacus-network/abacus-monorepo into…
tkporter Jan 15, 2025
c833035
evm quotes are the same
tkporter Jan 15, 2025
29f8041
IGP configure script, woo
tkporter Jan 15, 2025
458d83a
nits
tkporter Jan 15, 2025
cf5df0d
Merge branch 'main' of github.com:abacus-network/abacus-monorepo into…
tkporter Jan 17, 2025
d966e64
some measures in e2e
tkporter Jan 17, 2025
876cec1
some kleenup
tkporter Jan 17, 2025
1ba7130
cleaning up
tkporter Jan 17, 2025
e854ee6
add hardcoded connections
tkporter Jan 17, 2025
782db53
testnet svm setting
tkporter Jan 17, 2025
ad01cab
starting to set mainnets
tkporter Jan 17, 2025
60e8667
Merge branch 'main' of github.com:abacus-network/abacus-monorepo into…
tkporter Jan 17, 2025
ca20724
gas oracle config
tkporter Jan 17, 2025
d4227ab
rust nit
tkporter Jan 17, 2025
0a97475
e2e passes
tkporter Jan 17, 2025
f348e2a
rm old configs
tkporter Jan 17, 2025
5ad7621
rm the rust changes for now
tkporter Jan 17, 2025
eb53191
rm gas oracle config for now
tkporter Jan 17, 2025
f66ca53
nits
tkporter Jan 17, 2025
c94f5a1
Merge branch 'main' into trevor/igp-consolidation
paulbalaji Jan 20, 2025
6f22ec5
pr comments
tkporter Jan 20, 2025
e72bf6c
nit
tkporter Jan 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions typescript/cli/src/config/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export const createIGPConfig = callWithConfigCreationLogs(
// Calculate storage gas oracle config
const oracleConfig = getLocalStorageGasOracleConfig({
local: localChain,
localProtocolType: context.multiProvider.getProtocol(localChain),
gasOracleParams: prices,
exchangeRateMarginPct,
});
Expand Down
21 changes: 4 additions & 17 deletions typescript/infra/config/environments/mainnet3/igp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,19 @@ import {
ChainTechnicalStack,
HookType,
IgpConfig,
getTokenExchangeRateFromValues,
} from '@hyperlane-xyz/sdk';
import { exclude, objMap } from '@hyperlane-xyz/utils';

import {
AllStorageGasOracleConfigs,
EXCHANGE_RATE_MARGIN_PCT,
getAllStorageGasOracleConfigs,
getOverhead,
} from '../../../src/config/gas-oracle.js';
import { mustGetChainNativeToken } from '../../../src/utils/utils.js';
import { getChain } from '../../registry.js';

import { ethereumChainNames } from './chains.js';
import gasPrices from './gasPrices.json';
import { DEPLOYER, ethereumChainOwners } from './owners.js';
import { DEPLOYER, chainOwners } from './owners.js';
import { supportedChainNames } from './supportedChainNames.js';
import rawTokenPrices from './tokenPrices.json';

Expand All @@ -42,24 +39,14 @@ export function getOverheadWithOverrides(local: ChainName, remote: ChainName) {
const storageGasOracleConfig: AllStorageGasOracleConfigs =
getAllStorageGasOracleConfigs(
supportedChainNames,
tokenPrices,
gasPrices,
(local, remote) =>
getTokenExchangeRateFromValues({
local,
remote,
tokenPrices,
exchangeRateMarginPct: EXCHANGE_RATE_MARGIN_PCT,
decimals: {
local: mustGetChainNativeToken(local).decimals,
remote: mustGetChainNativeToken(remote).decimals,
},
}),
(local) => parseFloat(tokenPrices[local]),
(local, remote) => getOverheadWithOverrides(local, remote),
true,
);

export const igp: ChainMap<IgpConfig> = objMap(
ethereumChainOwners,
chainOwners,
(local, owner): IgpConfig => ({
type: HookType.INTERCHAIN_GAS_PAYMASTER,
...owner,
Expand Down
31 changes: 11 additions & 20 deletions typescript/infra/config/environments/test/gas-oracle.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import { BigNumber, ethers } from 'ethers';

import {
ChainMap,
ChainName,
GasPriceConfig,
TOKEN_EXCHANGE_RATE_DECIMALS,
} from '@hyperlane-xyz/sdk';
import { ChainMap, GasPriceConfig } from '@hyperlane-xyz/sdk';

import {
AllStorageGasOracleConfigs,
Expand All @@ -14,31 +7,29 @@ import {

import { testChainNames } from './chains.js';

const TEST_TOKEN_EXCHANGE_RATE = ethers.utils.parseUnits(
'1',
TOKEN_EXCHANGE_RATE_DECIMALS,
);
const TEST_TOKEN_EXCHANGE_RATE = '1';
const TEST_GAS_PRICE_CONFIG: GasPriceConfig = {
amount: '2',
decimals: 9, // gwei
};

const tokenPrices: ChainMap<string> = {
test1: TEST_TOKEN_EXCHANGE_RATE,
test2: TEST_TOKEN_EXCHANGE_RATE,
test3: TEST_TOKEN_EXCHANGE_RATE,
};

const gasPrices: ChainMap<GasPriceConfig> = {
test1: TEST_GAS_PRICE_CONFIG,
test2: TEST_GAS_PRICE_CONFIG,
test3: TEST_GAS_PRICE_CONFIG,
};

function getTokenExchangeRate(
_local: ChainName,
_remote: ChainName,
): BigNumber {
return TEST_TOKEN_EXCHANGE_RATE;
}

export const storageGasOracleConfig: AllStorageGasOracleConfigs =
getAllStorageGasOracleConfigs(
testChainNames,
tokenPrices,
gasPrices,
getTokenExchangeRate,
(_local, _remote) => 0,
false,
);
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
"decimals": 9
},
"solanatestnet": {
"amount": "0.0001",
"amount": "0.01",
paulbalaji marked this conversation as resolved.
Show resolved Hide resolved
"decimals": 1
},
"soneiumtestnet": {
Expand All @@ -108,7 +108,7 @@
"decimals": 9
},
"sonicsvmtestnet": {
"amount": "0.0001",
"amount": "0.01",
"decimals": 1
},
"suavetoliman": {
Expand Down
23 changes: 4 additions & 19 deletions typescript/infra/config/environments/testnet4/igp.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import {
ChainMap,
HookType,
IgpConfig,
getTokenExchangeRateFromValues,
} from '@hyperlane-xyz/sdk';
import { ChainMap, HookType, IgpConfig } from '@hyperlane-xyz/sdk';
import { Address, exclude, objMap } from '@hyperlane-xyz/utils';

import {
AllStorageGasOracleConfigs,
EXCHANGE_RATE_MARGIN_PCT,
getAllStorageGasOracleConfigs,
getOverhead,
} from '../../../src/config/gas-oracle.js';
import { mustGetChainNativeToken } from '../../../src/utils/utils.js';

import { ethereumChainNames } from './chains.js';
import gasPrices from './gasPrices.json';
Expand All @@ -25,18 +18,10 @@ const tokenPrices: ChainMap<string> = rawTokenPrices;
export const storageGasOracleConfig: AllStorageGasOracleConfigs =
getAllStorageGasOracleConfigs(
supportedChainNames,
tokenPrices,
gasPrices,
(local, remote) =>
getTokenExchangeRateFromValues({
local,
remote,
tokenPrices,
exchangeRateMarginPct: EXCHANGE_RATE_MARGIN_PCT,
decimals: {
local: mustGetChainNativeToken(local).decimals,
remote: mustGetChainNativeToken(remote).decimals,
},
}),
(local, remote) => getOverhead(local, remote, ethereumChainNames),
false,
);

export const igp: ChainMap<IgpConfig> = objMap(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"sepolia": "10",
"solanatestnet": "10",
"soneiumtestnet": "10",
"sonictestnet": "10",
"sonicblaze": "10",
"sonicsvmtestnet": "10",
"suavetoliman": "10",
Expand Down
4 changes: 3 additions & 1 deletion typescript/infra/config/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ export function getWarpCoreConfig(warpRouteId: string): WarpCoreConfig {
return warpRouteConfig;
}

export function getWarpAddresses(warpRouteId: string) {
export function getWarpAddresses(
warpRouteId: string,
): ChainMap<ChainAddresses> {
const warpCoreConfig = getWarpCoreConfig(warpRouteId);
return warpConfigToWarpAddresses(warpCoreConfig);
}
Expand Down
7 changes: 7 additions & 0 deletions typescript/infra/scripts/agent-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ export function withChainsRequired<T>(
return withChains(args, chainOptions).demandOption('chains');
}

export function withOutputFile<T>(args: Argv<T>) {
return args
.describe('outFile', 'output file')
.string('outFile')
.alias('o', 'outFile');
}

export function withWarpRouteId<T>(args: Argv<T>) {
return args.describe('warpRouteId', 'warp route id').string('warpRouteId');
}
Expand Down
131 changes: 131 additions & 0 deletions typescript/infra/scripts/sealevel-helpers/print-gas-oracles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import {
ChainMap,
ChainName,
ProtocolAgnositicGasOracleConfig,
} from '@hyperlane-xyz/sdk';
import {
ProtocolType,
objFilter,
objMap,
stringifyObject,
} from '@hyperlane-xyz/utils';

import { WarpRouteIds } from '../../config/environments/mainnet3/warp/warpIds.js';
import { getChain, getWarpAddresses } from '../../config/registry.js';
import { DeployEnvironment } from '../../src/config/environment.js';
import { writeJsonAtPath } from '../../src/utils/utils.js';
import { getArgs, withOutputFile } from '../agent-utils.js';
import { getEnvironmentConfig } from '../core-utils.js';

// This script exists to print the gas oracle configs for a given environment
// so they can easily be copied into the Sealevel tooling. :'(

interface GasOracleConfigWithOverhead {
oracleConfig: ProtocolAgnositicGasOracleConfig;
overhead?: number;
}

async function main() {
const { environment, outFile } = await withOutputFile(getArgs()).argv;

const environmentConfig = getEnvironmentConfig(environment);

const allConnectedChains = getChainConnections(environment);

// Construct a nested map of origin -> destination -> { oracleConfig, overhead }
let gasOracles = objMap(environmentConfig.igp, (origin, igpConfig) => {
// Only SVM origins for now
if (getChain(origin).protocol !== ProtocolType.Sealevel) {
return undefined;
}

// If there's no oracle config, don't do anything for this origin
if (!igpConfig.oracleConfig) {
return undefined;
}
// Get the set of chains that are connected to this origin via warp routes
const connectedChainsSet = allConnectedChains[origin];
if (!connectedChainsSet) {
return undefined;
}
const connectedChains = [...connectedChainsSet];

return connectedChains.reduce((agg, destination) => {
const oracleConfig = igpConfig.oracleConfig[destination];
if (oracleConfig.tokenDecimals === undefined) {
throw new Error(
`Token decimals not defined for ${origin} -> ${destination}`,
);
}
agg[destination] = {
oracleConfig,
overhead: igpConfig?.overhead?.[destination],
};
return agg;
}, {} as ChainMap<GasOracleConfigWithOverhead>);
});

// Filter out undefined values
gasOracles = objFilter(
gasOracles,
(_, value): value is ChainMap<GasOracleConfigWithOverhead> | undefined =>
value !== undefined,
);

console.log(stringifyObject(gasOracles, 'json', 2));

if (outFile) {
console.log(`Writing config to ${outFile}`);
writeJsonAtPath(outFile, gasOracles);
}
}

// Gets the chains in the provided warp route
function getWarpChains(warpRouteId: string): ChainName[] {
const warpRouteAddresses = getWarpAddresses(warpRouteId);
return Object.keys(warpRouteAddresses);
}

// Because there is a limit to how many chains we want to figure in an SVM IGP,
// we limit the chains to only those that are connected via warp routes.
// Returns a record of origin chain -> set of chains that are connected via warp routes.
function getChainConnections(
environment: DeployEnvironment,
): ChainMap<Set<ChainName>> {
// A list of connected chains
let connectedChains = [];

if (environment === 'mainnet3') {
// All the mainnet3 warp route chains
connectedChains = Object.values(WarpRouteIds).map(getWarpChains);
} else if (environment === 'testnet4') {
connectedChains = [
// As testnet warp routes are not tracked well, hardcode the connected chains.
// For SOL/solanatestnet-sonicsvmtestnet
['solanatestnet', 'sonicsvmtestnet'],
];
} else {
throw new Error(`Unknown environment: ${environment}`);
}

return connectedChains.reduce((agg, chains) => {
// Make sure each chain is connected to every other chain
chains.forEach((chainA) => {
chains.forEach((chainB) => {
if (chainA === chainB) {
return;
}
if (agg[chainA] === undefined) {
agg[chainA] = new Set();
}
agg[chainA].add(chainB as ChainName);
});
});
return agg;
}, {} as ChainMap<Set<ChainName>>);
}

main().catch((err) => {
console.error(err);
process.exit(1);
});
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ async function main() {
}
}

console.warn;

console.log(JSON.stringify(config, null, 2));
}

Expand Down
14 changes: 8 additions & 6 deletions typescript/infra/scripts/warp-routes/generate-warp-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import { WarpRouteDeployConfigSchema } from '@hyperlane-xyz/sdk';

import { getWarpConfig } from '../../config/warp.js';
import { writeYamlAtPath } from '../../src/utils/utils.js';
import { getArgs, withWarpRouteIdRequired } from '../agent-utils.js';
import {
getArgs,
withOutputFile,
withWarpRouteIdRequired,
} from '../agent-utils.js';
import { getEnvironmentConfig, getHyperlaneCore } from '../core-utils.js';

async function main() {
const { warpRouteId, environment, outFile } = await withWarpRouteIdRequired(
getArgs(),
)
.string('outFile')
.describe('outFile', 'The file to write the config to').argv;
const { warpRouteId, environment, outFile } = await withOutputFile(
withWarpRouteIdRequired(getArgs()),
).argv;

const { multiProvider } = await getHyperlaneCore(environment);
const envConfig = getEnvironmentConfig(environment);
Expand Down
Loading
Loading