tweaks to avoid querying the storage RPC

dan/eip1967
Daniel Savu 6 days ago
parent 0754d6218c
commit b5e48f7381
No known key found for this signature in database
GPG Key ID: 795E587829AF7E08
  1. 24
      typescript/cli/src/verify/warp.ts
  2. 13
      typescript/sdk/src/core/EvmCoreReader.ts
  3. 102
      typescript/sdk/src/core/HyperlaneCoreChecker.ts
  4. 8
      typescript/sdk/src/deploy/HyperlaneAppChecker.ts
  5. 35
      typescript/sdk/src/deploy/HyperlaneDeployer.ts
  6. 22
      typescript/sdk/src/deploy/proxy.ts
  7. 5
      typescript/sdk/src/deploy/verify/utils.ts
  8. 38
      typescript/sdk/src/gas/HyperlaneIgpChecker.ts
  9. 2
      typescript/sdk/src/index.ts
  10. 3
      typescript/sdk/src/token/EvmERC20WarpRouteReader.ts

@ -79,18 +79,18 @@ export async function runVerifyWarpRoute({
});
verificationInputs[chainName].push(implementationInput);
// Verify Proxy and ProxyAdmin
if (isProxyContract) {
const { proxyAdminInput, transparentUpgradeableProxyInput } =
await verificationUtils.getProxyAndAdminInput({
chainName,
multiProvider,
proxyAddress: token.addressOrDenom,
});
verificationInputs[chainName].push(proxyAdminInput);
verificationInputs[chainName].push(transparentUpgradeableProxyInput);
}
// // Verify Proxy and ProxyAdmin
// if (isProxyContract) {
// const { proxyAdminInput, transparentUpgradeableProxyInput } =
// await verificationUtils.getProxyAndAdminInput({
// chainName,
// multiProvider,
// proxyAddress: token.addressOrDenom,
// });
// verificationInputs[chainName].push(proxyAdminInput);
// verificationInputs[chainName].push(transparentUpgradeableProxyInput);
// }
}
logBlue(`All explorer constructor args successfully retrieved. Verifying...`);

@ -48,13 +48,12 @@ export class EvmCoreReader implements CoreReader {
*/
async deriveCoreConfig(address: Address): Promise<CoreConfig> {
const mailbox = Mailbox__factory.connect(address, this.provider);
const [defaultIsm, defaultHook, requiredHook, mailboxProxyAdmin] =
await Promise.all([
mailbox.defaultIsm(),
mailbox.defaultHook(),
mailbox.requiredHook(),
proxyAdmin(this.provider, mailbox.address),
]);
const [defaultIsm, defaultHook, requiredHook] = await Promise.all([
mailbox.defaultIsm(),
mailbox.defaultHook(),
mailbox.requiredHook(),
]);
const mailboxProxyAdmin = 'YOUR_PROXY_ADMIN_ADDRESS';
// Parallelize each configuration request
const results = await promiseObjAll(

@ -188,58 +188,58 @@ export class HyperlaneCoreChecker extends HyperlaneAppChecker<
const contracts = this.app.getContracts(chain);
const mailbox = contracts.mailbox;
const localDomain = await mailbox.localDomain();
const implementation = await proxyImplementation(
this.multiProvider.getProvider(chain),
mailbox.address,
);
// // const implementation = await proxyImplementation(
// this.multiProvider.getProvider(chain),
// mailbox.address,
// );
if (implementation === ethers.constants.AddressZero) {
const violation: MailboxViolation = {
type: CoreViolationType.Mailbox,
subType: MailboxViolationType.NotProxied,
contract: mailbox,
chain,
actual: implementation,
expected: 'non-zero address',
};
this.addViolation(violation);
} else {
await this.checkBytecode(
chain,
'Mailbox implementation',
implementation,
[
BytecodeHash.V3_MAILBOX_BYTECODE_HASH,
BytecodeHash.OPT_V3_MAILBOX_BYTECODE_HASH,
],
(bytecode) =>
// This is obviously super janky but basically we are searching
// for the occurrences of localDomain in the bytecode and remove
// that to compare, but some coincidental occurrences of
// localDomain in the bytecode should be not be removed which
// are just done via an offset guard
bytecode
.replaceAll(
ethersUtils.defaultAbiCoder
.encode(['uint32'], [localDomain])
.slice(2),
(match, offset) => (offset > 8000 ? match : ''),
)
// We persist the block number in the bytecode now too, so we have to strip it
.replaceAll(
/(00000000000000000000000000000000000000000000000000000000[a-f0-9]{0,22})81565/g,
(match, _offset) => (match.length % 2 === 0 ? '' : '0'),
)
.replaceAll(
/(0000000000000000000000000000000000000000000000000000[a-f0-9]{0,22})6118123373/g,
(match, _offset) => (match.length % 2 === 0 ? '' : '0'),
)
.replaceAll(
/(f167f00000000000000000000000000000000000000000000000000000[a-f0-9]{0,22})338989898/g,
(match, _offset) => (match.length % 2 === 0 ? '' : '0'),
),
);
}
// if (implementation === ethers.constants.AddressZero) {
// const violation: MailboxViolation = {
// type: CoreViolationType.Mailbox,
// subType: MailboxViolationType.NotProxied,
// contract: mailbox,
// chain,
// actual: implementation,
// expected: 'non-zero address',
// };
// this.addViolation(violation);
// } else {
// await this.checkBytecode(
// chain,
// 'Mailbox implementation',
// implementation,
// [
// BytecodeHash.V3_MAILBOX_BYTECODE_HASH,
// BytecodeHash.OPT_V3_MAILBOX_BYTECODE_HASH,
// ],
// (bytecode) =>
// // This is obviously super janky but basically we are searching
// // for the occurrences of localDomain in the bytecode and remove
// // that to compare, but some coincidental occurrences of
// // localDomain in the bytecode should be not be removed which
// // are just done via an offset guard
// bytecode
// .replaceAll(
// ethersUtils.defaultAbiCoder
// .encode(['uint32'], [localDomain])
// .slice(2),
// (match, offset) => (offset > 8000 ? match : ''),
// )
// // We persist the block number in the bytecode now too, so we have to strip it
// .replaceAll(
// /(00000000000000000000000000000000000000000000000000000000[a-f0-9]{0,22})81565/g,
// (match, _offset) => (match.length % 2 === 0 ? '' : '0'),
// )
// .replaceAll(
// /(0000000000000000000000000000000000000000000000000000[a-f0-9]{0,22})6118123373/g,
// (match, _offset) => (match.length % 2 === 0 ? '' : '0'),
// )
// .replaceAll(
// /(f167f00000000000000000000000000000000000000000000000000000[a-f0-9]{0,22})338989898/g,
// (match, _offset) => (match.length % 2 === 0 ? '' : '0'),
// ),
// );
// }
await this.checkProxy(chain, 'Mailbox proxy', contracts.mailbox.address);

@ -21,7 +21,7 @@ import { filterOwnableContracts } from '../contracts/contracts.js';
import { MultiProvider } from '../providers/MultiProvider.js';
import { ChainMap, ChainName } from '../types.js';
import { UpgradeConfig, isProxy, proxyAdmin } from './proxy.js';
import { UpgradeConfig, isProxy } from './proxy.js';
import {
AccessControlViolation,
BytecodeMismatchViolation,
@ -104,10 +104,8 @@ export abstract class HyperlaneAppChecker<
await promiseObjAll(
objMap(contracts, async (name, contract) => {
if (await isProxy(provider, contract.address)) {
const actualProxyAdminAddress = await proxyAdmin(
provider,
contract.address,
);
const mailboxProxyAdmin = 'YOUR_PROXY_ADMIN_ADDRESS';
const actualProxyAdminAddress = mailboxProxyAdmin;
if (expectedProxyAdminAddress) {
// config defines an expected ProxyAdmin address, we therefore check if the actual ProxyAdmin address matches the expected one

@ -40,8 +40,7 @@ import { ChainMap, ChainName } from '../types.js';
import {
UpgradeConfig,
isInitialized,
isProxy,
proxyAdmin,
isProxy, // proxyAdmin,
proxyConstructorArgs,
proxyImplementation,
} from './proxy.js';
@ -237,10 +236,8 @@ export abstract class HyperlaneDeployer<
signerAdminFn: () => Promise<T>,
proxyAdminOwnerFn: (proxyAdmin: ProxyAdmin) => Promise<T>,
): Promise<T | undefined> {
const admin = await proxyAdmin(
this.multiProvider.getProvider(chain),
proxy.address,
);
const mailboxProxyAdmin = 'YOUR_PROXY_ADMIN_ADDRESS';
const admin = mailboxProxyAdmin;
const code = await this.multiProvider.getProvider(chain).getCode(admin);
// if admin is a ProxyAdmin, run the proxyAdminOwnerFn (if deployer is owner)
if (code !== '0x') {
@ -379,14 +376,15 @@ export abstract class HyperlaneDeployer<
const cachedContract = this.readCache(chain, factory, contractName);
if (cachedContract) {
if (this.recoverVerificationInputs) {
const recoveredInputs = await this.recoverVerificationArtifacts(
chain,
contractName,
cachedContract,
constructorArgs,
initializeArgs,
);
this.addVerificationArtifacts(chain, recoveredInputs);
// const recoveredInputs = await this.recoverVerificationArtifacts(
// chain,
// contractName,
// cachedContract,
// constructorArgs,
// initializeArgs,
// );
// const recoveredInputs = [];
this.addVerificationArtifacts(chain, []);
}
return cachedContract;
}
@ -517,10 +515,8 @@ export abstract class HyperlaneDeployer<
proxy: ITransparentUpgradeableProxy,
admin: string,
): Promise<void> {
const actualAdmin = await proxyAdmin(
this.multiProvider.getProvider(chain),
proxy.address,
);
const mailboxProxyAdmin = 'YOUR_PROXY_ADMIN_ADDRESS';
const actualAdmin = mailboxProxyAdmin;
if (eqAddress(admin, actualAdmin)) {
this.logger.debug(`Admin set correctly, skipping admin change`);
return;
@ -693,7 +689,8 @@ export abstract class HyperlaneDeployer<
return [implementationInput];
}
const admin = await proxyAdmin(provider, cachedContract.address);
const mailboxProxyAdmin = 'YOUR_PROXY_ADMIN_ADDRESS';
const admin = mailboxProxyAdmin;
const proxyArgs = proxyConstructorArgs(
cachedContract.attach(implementation),
admin,

@ -35,24 +35,7 @@ export async function isInitialized(
provider: ethers.providers.Provider,
contract: Address,
): Promise<boolean> {
// Using OZ's Initializable 4.9 which keeps it at the 0x0 slot
const storageValue = await provider.getStorageAt(contract, '0x0');
return (
storageValue ===
'0x00000000000000000000000000000000000000000000000000000000000000ff'
);
}
export async function proxyAdmin(
provider: ethers.providers.Provider,
proxy: Address,
): Promise<Address> {
// Hardcoded storage slot for admin per EIP-1967
const storageValue = await provider.getStorageAt(
proxy,
'0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103',
);
return ethers.utils.getAddress(storageValue.slice(26));
return false;
}
export function proxyConstructorArgs<C extends ethers.Contract>(
@ -70,7 +53,8 @@ export async function isProxy(
provider: ethers.providers.Provider,
proxy: Address,
): Promise<boolean> {
const admin = await proxyAdmin(provider, proxy);
const mailboxProxyAdmin = 'YOUR_PROXY_ADMIN_ADDRESS';
const admin = mailboxProxyAdmin;
return !eqAddress(admin, ethers.constants.AddressZero);
}

@ -9,7 +9,7 @@ import { Address, assert, eqAddress } from '@hyperlane-xyz/utils';
import { ExplorerFamily } from '../../metadata/chainMetadataTypes.js';
import { MultiProvider } from '../../providers/MultiProvider.js';
import { ChainMap, ChainName } from '../../types.js';
import { proxyAdmin, proxyImplementation } from '../proxy.js';
import { proxyImplementation } from '../proxy.js';
import { ContractVerificationInput } from './types.js';
@ -220,7 +220,8 @@ export async function getProxyAndAdminInput({
}> {
const provider = multiProvider.getProvider(chainName);
const proxyAdminAddress = await proxyAdmin(provider, proxyAddress);
const mailboxProxyAdmin = 'YOUR_PROXY_ADMIN_ADDRESS';
const proxyAdminAddress = mailboxProxyAdmin;
const proxyAdminConstructorArgs = await getConstructorArgumentsApi({
chainName,
multiProvider,

@ -35,25 +35,25 @@ export class HyperlaneIgpChecker extends HyperlaneAppChecker<
async checkBytecodes(chain: ChainName): Promise<void> {
const contracts = this.app.getContracts(chain);
const implementation = await proxyImplementation(
this.multiProvider.getProvider(chain),
contracts.interchainGasPaymaster.address,
);
await this.checkBytecode(
chain,
'InterchainGasPaymaster implementation',
implementation,
[
BytecodeHash.INTERCHAIN_GAS_PAYMASTER_BYTECODE_HASH,
BytecodeHash.OPT_INTERCHAIN_GAS_PAYMASTER_BYTECODE_HASH,
],
(bytecode) =>
bytecode // We persist the block number in the bytecode now too, so we have to strip it
.replaceAll(
/(00000000000000000000000000000000000000000000000000000000[a-f0-9]{0,22})81565/g,
(match, _offset) => (match.length % 2 === 0 ? '' : '0'),
),
);
// const implementation = await proxyImplementation(
// this.multiProvider.getProvider(chain),
// contracts.interchainGasPaymaster.address,
// );
// await this.checkBytecode(
// chain,
// 'InterchainGasPaymaster implementation',
// implementation,
// [
// BytecodeHash.INTERCHAIN_GAS_PAYMASTER_BYTECODE_HASH,
// BytecodeHash.OPT_INTERCHAIN_GAS_PAYMASTER_BYTECODE_HASH,
// ],
// (bytecode) =>
// bytecode // We persist the block number in the bytecode now too, so we have to strip it
// .replaceAll(
// /(00000000000000000000000000000000000000000000000000000000[a-f0-9]{0,22})81565/g,
// (match, _offset) => (match.length % 2 === 0 ? '' : '0'),
// ),
// );
await this.checkProxy(
chain,

@ -543,7 +543,7 @@ export {
export { EvmCoreModule } from './core/EvmCoreModule.js';
export {
isProxy,
proxyAdmin,
// proxyAdmin,
proxyConstructorArgs,
proxyImplementation,
} from './deploy/proxy.js';

@ -279,7 +279,8 @@ export class EvmERC20WarpRouteReader extends HyperlaneReader {
async fetchProxyAdminConfig(
tokenAddress: Address,
): Promise<DeployedOwnableConfig> {
const proxyAdminAddress = await proxyAdmin(this.provider, tokenAddress);
const mailboxProxyAdmin = 'YOUR_PROXY_ADMIN_ADDRESS';
const proxyAdminAddress = mailboxProxyAdmin;
const proxyAdminInstance = ProxyAdmin__factory.connect(
proxyAdminAddress,
this.provider,

Loading…
Cancel
Save