diff --git a/.changeset/poor-avocados-arrive.md b/.changeset/poor-avocados-arrive.md new file mode 100644 index 0000000000000..9e00a2d9c2916 --- /dev/null +++ b/.changeset/poor-avocados-arrive.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/core-utils': patch +--- + +Clean up the L1 => L2 address aliasing utilities diff --git a/packages/core-utils/src/alias.ts b/packages/core-utils/src/alias.ts index ded2b3fb74cca..db39b8735134f 100644 --- a/packages/core-utils/src/alias.ts +++ b/packages/core-utils/src/alias.ts @@ -1,22 +1,21 @@ import { ethers } from 'ethers' +import { bnToAddress } from './bn' +// Constant representing the alias to apply to the msg.sender when a contract sends an L1 => L2 +// message. We need this aliasing scheme because a contract can be deployed to the same address +// on both L1 and L2 but with different bytecode (address is not dependent on bytecode when using +// the standard CREATE opcode). We want to treat L1 contracts as having a different address while +// still making it possible for L2 contracts to easily reverse the aliasing scheme and figure out +// the real address of the contract that sent the L1 => L2 message. export const L1_TO_L2_ALIAS_OFFSET = '0x1111000000000000000000000000000000001111' -export const bnToAddress = (bn: ethers.BigNumber | number): string => { - bn = ethers.BigNumber.from(bn) - if (bn.isNegative()) { - bn = ethers.BigNumber.from('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF') - .add(bn) - .add(1) - } - - const addr = bn.toHexString().slice(2).padStart(40, '0') - return ethers.utils.getAddress( - '0x' + addr.slice(addr.length - 40, addr.length) - ) -} - +/** + * Applies the L1 => L2 aliasing scheme to an address. + * + * @param address Address to apply the scheme to. + * @returns Address with the scheme applied. + */ export const applyL1ToL2Alias = (address: string): string => { if (!ethers.utils.isAddress(address)) { throw new Error(`not a valid address: ${address}`) @@ -25,6 +24,12 @@ export const applyL1ToL2Alias = (address: string): string => { return bnToAddress(ethers.BigNumber.from(address).add(L1_TO_L2_ALIAS_OFFSET)) } +/** + * Reverses the L1 => L2 aliasing scheme from an address. + * + * @param address Address to reverse the scheme from. + * @returns Alias with the scheme reversed. + */ export const undoL1ToL2Alias = (address: string): string => { if (!ethers.utils.isAddress(address)) { throw new Error(`not a valid address: ${address}`) diff --git a/packages/core-utils/src/bn.ts b/packages/core-utils/src/bn.ts new file mode 100644 index 0000000000000..a4de2b624278f --- /dev/null +++ b/packages/core-utils/src/bn.ts @@ -0,0 +1,37 @@ +import { ethers } from 'ethers' +import { remove0x, add0x } from './common/hex-strings' + +/** + * Converts an ethers BigNumber into an equivalent Ethereum address representation. + * + * @param bn BigNumber to convert to an address. + * @return BigNumber converted to an address, represented as a hex string. + */ +export const bnToAddress = (bn: ethers.BigNumber | number): string => { + // Coerce numbers into a BigNumber. + bn = ethers.BigNumber.from(bn) + + // Negative numbers are converted to addresses by adding MAX_ADDRESS + 1. + // TODO: Explain this in more detail, it's basically just matching the behavior of doing + // addr(uint256(addr) - some_number) in Solidity where some_number > uint256(addr). + if (bn.isNegative()) { + bn = ethers.BigNumber.from('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF') + .add(bn) + .add(1) + } + + // Convert to a hex string + let addr = bn.toHexString() + // Remove leading 0x so we can mutate the address a bit + addr = remove0x(addr) + // Make sure it's 40 characters (= 20 bytes) + addr = addr.padStart(40, '0') + // Only take the last 40 characters (= 20 bytes) + addr = addr.slice(addr.length - 40, addr.length) + // Add 0x again + addr = add0x(addr) + // Convert into a checksummed address + addr = ethers.utils.getAddress(addr) + + return addr +} diff --git a/packages/core-utils/src/index.ts b/packages/core-utils/src/index.ts index 0e60c32e9cfd5..3604c7b622d79 100644 --- a/packages/core-utils/src/index.ts +++ b/packages/core-utils/src/index.ts @@ -8,3 +8,4 @@ export * from './fees' export * from './provider' export * from './alias' export * from './types' +export * from './bn'