@hyperlane-xyz/sdk
Version:
The official SDK for the Hyperlane Network
61 lines • 3.13 kB
JavaScript
import { ethers } from 'ethers';
import { ProxyAdmin__factory } from '@hyperlane-xyz/core';
import { eqAddress } from '@hyperlane-xyz/utils';
import { transferOwnershipTransactions } from '../contracts/contracts.js';
export async function proxyImplementation(provider, proxy) {
// Hardcoded storage slot for implementation per EIP-1967
const storageValue = await provider.getStorageAt(proxy, '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc');
return ethers.utils.getAddress(storageValue.slice(26));
}
export async function isInitialized(provider, contract) {
// 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, proxy) {
// Hardcoded storage slot for admin per EIP-1967
const storageValue = await provider.getStorageAt(proxy, '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103');
// Return zero address if storage value is empty
if (storageValue === '0x' || storageValue === '0x0') {
return ethers.constants.AddressZero;
}
return ethers.utils.getAddress(storageValue.slice(26));
}
export function proxyConstructorArgs(implementation, proxyAdmin, initializeArgs) {
const initData = initializeArgs
? implementation.interface.encodeFunctionData('initialize', initializeArgs)
: '0x';
return [implementation.address, proxyAdmin, initData];
}
export async function isProxy(provider, proxy) {
const admin = await proxyAdmin(provider, proxy);
return !eqAddress(admin, ethers.constants.AddressZero);
}
export function proxyAdminUpdateTxs(chainId, proxyAddress, actualConfig, expectedConfig) {
const transactions = [];
// Return early because old config files did not have the
// proxyAdmin property
if (!expectedConfig.proxyAdmin?.address) {
return transactions;
}
const actualProxyAdmin = actualConfig.proxyAdmin;
const parsedChainId = typeof chainId === 'string' ? parseInt(chainId) : chainId;
if (actualProxyAdmin.address &&
actualProxyAdmin.address !== expectedConfig.proxyAdmin.address) {
transactions.push({
chainId: parsedChainId,
annotation: `Updating ProxyAdmin for proxy at "${proxyAddress}" from "${actualProxyAdmin.address}" to "${expectedConfig.proxyAdmin.address}"`,
to: actualProxyAdmin.address,
data: ProxyAdmin__factory.createInterface().encodeFunctionData('changeProxyAdmin(address,address)', [proxyAddress, expectedConfig.proxyAdmin.address]),
});
}
else {
transactions.push(
// Internally the createTransferOwnershipTx method already checks if the
// two owner values are the same and produces an empty tx batch if they are
...transferOwnershipTransactions(parsedChainId, actualProxyAdmin.address, actualProxyAdmin, expectedConfig.proxyAdmin));
}
return transactions;
}
//# sourceMappingURL=proxy.js.map