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: proxies and custom factory #23

Merged
merged 44 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
a262f7c
feat: create first version of factory contract
0xDiscotech May 13, 2024
dcf3621
chore: move external interfaces to external folder
0xDiscotech May 13, 2024
d84629a
feat: create scripts for mainnet and sepolia deployment
0xDiscotech May 13, 2024
2376741
refactor: add owner on constructor params
0xDiscotech May 13, 2024
a77a13d
feat: precalculate l1 create3 proxy deployer address
0xDiscotech May 14, 2024
60b49cc
fix: send usdc creation code as param
0xDiscotech May 14, 2024
834b949
feat: deploy impl and proxy usdc contracts
0xDiscotech May 15, 2024
c9dcfa7
refactor: use struct params to send more data as arg on deploy
0xDiscotech May 15, 2024
cdd0f21
fix: calculate guarded salt for l2
0xDiscotech May 15, 2024
513c911
feat: add natspec and organize the code on the interface and lib
0xDiscotech May 16, 2024
7f61441
refactor: update constructor args and deploy struct values
0xDiscotech May 16, 2024
d85e5b0
Merge branch 'dev' into feat/factory
0xDiscotech May 16, 2024
2b669e7
feat: create unit tests for the factory contract
0xDiscotech May 16, 2024
bcef49d
feat: add return values unit test
0xDiscotech May 16, 2024
268b1b1
chore: remove unused portal interface
0xDiscotech May 16, 2024
b486001
chore: remove console sol import due to a bug on ci
0xDiscotech May 16, 2024
2034e74
Merge branch 'dev' into feat/factory
0xDiscotech May 16, 2024
361e86c
Merge branch 'dev' into feat/proxies-and-custom-factory
0xDiscotech May 22, 2024
06683fa
feat: create l2 op usdc factory
0xDiscotech May 22, 2024
0060052
Merge branch 'dev' into feat/proxies-and-custom-factory
0xDiscotech May 22, 2024
d2bf283
feat: update l1 factory and l2 factory using create and bytecode depl…
0xDiscotech May 23, 2024
8dcd139
refactor: remove the create deployer contract and move the unique nee…
0xDiscotech May 23, 2024
8ec77da
refactor: send the hardcoded usdc proxy bytecode on l1 and deploy it …
0xDiscotech May 23, 2024
955c22e
refactor: add init txs on an upgrade manager implementation struct
0xDiscotech May 24, 2024
ebb10ec
chore: rename proxy usd creation code
0xDiscotech May 24, 2024
a243828
fix: ex comments
0xDiscotech May 24, 2024
6910875
feat: unit tests for l1 factory
0xDiscotech May 24, 2024
5d753aa
feat: create some unit tests for l2 factory
0xDiscotech May 24, 2024
868e513
Merge branch 'dev' into feat/proxies-and-custom-factory
0xDiscotech May 24, 2024
86ab7f3
feat: add natspec over factory contracts and unit tests
0xDiscotech May 24, 2024
5326503
chore: uncomment expect calls on factory l2 tests
0xDiscotech May 24, 2024
7a600ce
chore: update portal address on deployment scripts
0xDiscotech May 24, 2024
95cfbf7
fix: change mock all calls order on l1 factory tests due to an issue
0xDiscotech May 24, 2024
85ab68a
fix: use struct impl address on l1 factory instead of constant
0xDiscotech May 24, 2024
dc6bdb2
fix: byecode bad usage on l2 factory tests
0xDiscotech May 25, 2024
3846152
refactor: improve bytecode deployer
0xDiscotech May 25, 2024
558b7fb
fix: linter warnings
0xDiscotech May 25, 2024
bee19b8
fix: bug on l1 factory
0xDiscotech May 25, 2024
6429925
chore: add natspec to bytecode deployer and move it to utils
0xDiscotech May 27, 2024
dc0527a
refactor: user l1 messenger to get the portal on l1 factory
0xDiscotech May 27, 2024
d2b40f4
fix: deploy adapter impl and then proxy with it as arg on l2 factory
0xDiscotech May 27, 2024
c65580e
chore: use address alias lib
0xDiscotech May 27, 2024
6dd2afb
test: add test on extra zeros returned by the bytecode deplpoyer
0xDiscotech May 27, 2024
6b90c67
refactor: add l1 messenger as var on l1 factory instead of fuzzing it
0xDiscotech May 27, 2024
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
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
MAINNET_RPC=
MAINNET_DEPLOYER_PK=
L1_FACTORY_MAINNET=

SEPOLIA_RPC=
SEPOLIA_DEPLOYER_PK=
L1_FACTORY_SEPOLIA=

ETHERSCAN_API_KEY=
8 changes: 3 additions & 5 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ number_underscore = 'thousands'
multiline_func_header = 'params_first'
sort_imports = true

[profile.default]
solc_version = '0.8.25'
libs = ['node_modules']
optimizer_runs = 10_000

Comment on lines -11 to -15
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After I added this to the toml:

[profile.optimized]
via_ir = true
out = 'out-via-ir'

forge build asked me (with a warning) to run forge config --fix. This was removed after running that command

[profile.optimized]
via_ir = true
out = 'out-via-ir'

[profile.default.optimizer_details]
yul = false
Comment on lines +15 to +16
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed this becasue the msize() of the BytecodeDeployer contract didn't due to Yul optimizer issues


[profile.test]
via_ir = true
out = 'out-via-ir'
Expand Down
2 changes: 1 addition & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ forge-std/=node_modules/forge-std/src
isolmate/=node_modules/isolmate/src

contracts/=src/contracts
interfaces/=src/interfaces
interfaces/=src/interfaces
8 changes: 0 additions & 8 deletions script/Deploy.sol

This file was deleted.

32 changes: 32 additions & 0 deletions script/mainnet/FactoryDeploy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {BytecodeDeployer} from 'contracts/BytecodeDeployer.sol';
import {L1OpUSDCFactory} from 'contracts/L1OpUSDCFactory.sol';
import {Script} from 'forge-std/Script.sol';
import {console} from 'forge-std/Test.sol';
import {IL1OpUSDCFactory} from 'interfaces/IL1OpUSDCFactory.sol';

contract FactoryDeploy is Script {
address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address public deployer = vm.rememberKey(vm.envUint('MAINNET_DEPLOYER_PK'));

function run() public {
vm.startBroadcast(deployer);

console.log('Deploying L1OpUSDCFactory ...');
IL1OpUSDCFactory _l1Factory = new L1OpUSDCFactory(USDC, deployer);
console.log('L1OpUSDCFactory deployed at:', address(_l1Factory));

console.log('L1OpUSDCBridgeAdapter deployed at:', address(_l1Factory.L1_ADAPTER()));
console.log('L1 UpgradeManager deployed at:', address(_l1Factory.UPGRADE_MANAGER()));
console.log('-----');
console.log('aliased l1 factory deployment address:', _l1Factory.ALIASED_SELF());
console.log('L2OpUSDCBridgeAdapter deployment address:', _l1Factory.L2_ADAPTER());
console.log('L2 USDC proxy deployed deployment address:', _l1Factory.L2_USDC_PROXY());
console.log('L2 USDC implementation deployed deployment address:', _l1Factory.L2_USDC_IMPLEMENTATION());
console.log('L2OpUSDCFactory deployed at:', _l1Factory.L2_FACTORY());

vm.stopBroadcast();
}
}
21 changes: 21 additions & 0 deletions script/mainnet/FactoryDeployMainnet.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Script} from 'forge-std/Script.sol';
import {IL1OpUSDCFactory} from 'interfaces/IL1OpUSDCFactory.sol';
import {ICrossDomainMessenger} from 'interfaces/external/ICrossDomainMessenger.sol';
import {IOptimismPortal} from 'interfaces/external/IOptimismPortal.sol';

contract FactoryDeployMainnet is Script {
address public constant L1_CROSS_DOMAIN_MESSENGER = 0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1;
uint32 public constant MIN_GAS_LIMIT = 8_000_000;
IL1OpUSDCFactory public immutable L1_FACTORY = IL1OpUSDCFactory(vm.envAddress('L1_FACTORY_MAINNET'));
address public deployer = vm.rememberKey(vm.envUint('MAINNET_DEPLOYER_PK'));

function run() public {
vm.startBroadcast(deployer);
// Deploy the l2 contracts
L1_FACTORY.deployL2UsdcAndAdapter(L1_CROSS_DOMAIN_MESSENGER, MIN_GAS_LIMIT);
vm.stopBroadcast();
}
}
32 changes: 32 additions & 0 deletions script/sepolia/FactoryDeploy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {BytecodeDeployer} from 'contracts/BytecodeDeployer.sol';
import {L1OpUSDCFactory} from 'contracts/L1OpUSDCFactory.sol';
import {Script} from 'forge-std/Script.sol';
import {console} from 'forge-std/Test.sol';
import {IL1OpUSDCFactory} from 'interfaces/IL1OpUSDCFactory.sol';

contract FactoryDeploy is Script {
address public constant USDC = 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238;
address public deployer = vm.rememberKey(vm.envUint('SEPOLIA_DEPLOYER_PK'));

function run() public {
vm.startBroadcast(deployer);

console.log('Deploying L1OpUSDCFactory ...');
IL1OpUSDCFactory _l1Factory = new L1OpUSDCFactory(USDC, deployer);
console.log('L1OpUSDCFactory deployed at:', address(_l1Factory));

console.log('L1OpUSDCBridgeAdapter deployed at:', address(_l1Factory.L1_ADAPTER()));
console.log('L1 UpgradeManager deployed at:', address(_l1Factory.UPGRADE_MANAGER()));
console.log('-----');
console.log('aliased l1 factory deployment address:', _l1Factory.ALIASED_SELF());
console.log('L2OpUSDCBridgeAdapter deployment address:', _l1Factory.L2_ADAPTER());
console.log('L2 USDC proxy deployed deployment address:', _l1Factory.L2_USDC_PROXY());
console.log('L2 USDC implementation deployed deployment address:', _l1Factory.L2_USDC_IMPLEMENTATION());
console.log('L2OpUSDCFactory deployed at:', _l1Factory.L2_FACTORY());

vm.stopBroadcast();
}
}
21 changes: 21 additions & 0 deletions script/sepolia/FactoryDeployBase.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {Script} from 'forge-std/Script.sol';
import {IL1OpUSDCFactory} from 'interfaces/IL1OpUSDCFactory.sol';
import {ICrossDomainMessenger} from 'interfaces/external/ICrossDomainMessenger.sol';

contract FactoryDeployBase is Script {
address public constant L1_CROSS_DOMAIN_MESSENGER = 0xC34855F4De64F1840e5686e64278da901e261f20;
uint32 public constant MIN_GAS_LIMIT = 12_000_000;
IL1OpUSDCFactory public immutable L1_FACTORY = IL1OpUSDCFactory(vm.envAddress('L1_FACTORY_SEPOLIA'));

address public deployer = vm.rememberKey(vm.envUint('SEPOLIA_DEPLOYER_PK'));

function run() public {
vm.startBroadcast(deployer);
// Deploy the l2 contracts
L1_FACTORY.deployL2UsdcAndAdapter(L1_CROSS_DOMAIN_MESSENGER, MIN_GAS_LIMIT);
vm.stopBroadcast();
}
}
23 changes: 23 additions & 0 deletions script/sepolia/FactoryDeployOp.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {L1OpUSDCBridgeAdapter} from 'contracts/L1OpUSDCBridgeAdapter.sol';
import {L2OpUSDCBridgeAdapter} from 'contracts/L2OpUSDCBridgeAdapter.sol';
import {Script} from 'forge-std/Script.sol';
import {IL1OpUSDCFactory} from 'interfaces/IL1OpUSDCFactory.sol';
import {ICrossDomainMessenger} from 'interfaces/external/ICrossDomainMessenger.sol';

contract FactoryDeployOp is Script {
address public constant L1_CROSS_DOMAIN_MESSENGER = 0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef;
uint32 public constant MIN_GAS_LIMIT = 12_000_000;
IL1OpUSDCFactory public immutable L1_FACTORY = IL1OpUSDCFactory(vm.envAddress('L1_FACTORY_SEPOLIA'));

address public deployer = vm.rememberKey(vm.envUint('SEPOLIA_DEPLOYER_PK'));

function run() public {
vm.startBroadcast(deployer);
// Deploy the l2 contracts
L1_FACTORY.deployL2UsdcAndAdapter(L1_CROSS_DOMAIN_MESSENGER, MIN_GAS_LIMIT);
vm.stopBroadcast();
}
}
17 changes: 17 additions & 0 deletions src/contracts/BytecodeDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

contract BytecodeDeployer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add natspec here describing that this is a wrapper contract etc

Also I think it would be good if this was inside utils

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes!

/**
* @notice Deploys the contract with the given bytecode
* @param _bytecode The bytecode to be assigned to the contract
*/
constructor(bytes memory _bytecode) {
// TODO: add some check or will revert if the bytecode is invalid?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will never revert thr contract will be unusuable, you can deploy an address qhatever

assembly {
let _dataStart := add(_bytecode, 32)
let _dataEnd := sub(msize(), _dataStart)
return(_dataStart, _dataEnd)
}
}
}
162 changes: 162 additions & 0 deletions src/contracts/L1OpUSDCFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {BytecodeDeployer} from 'contracts/BytecodeDeployer.sol';

Check warning on line 4 in src/contracts/L1OpUSDCFactory.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Variable "BytecodeDeployer" is unused
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import

import {USDC_PROXY_BYTECODE} from 'contracts/utils/USDCCreationCode.sol';

import {L1OpUSDCBridgeAdapter} from 'contracts/L1OpUSDCBridgeAdapter.sol';

import {ERC1967Proxy} from '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol';
import {UpgradeManager} from 'contracts/UpgradeManager.sol';
import {AddressAliasHelper} from 'contracts/utils/AddressAliasHelper.sol';
import {IL1OpUSDCBridgeAdapter} from 'interfaces/IL1OpUSDCBridgeAdapter.sol';
import {IL1OpUSDCFactory} from 'interfaces/IL1OpUSDCFactory.sol';

import {L2OpUSDCFactory} from 'contracts/L2OpUSDCFactory.sol';
import {IUpgradeManager} from 'interfaces/IUpgradeManager.sol';
import {ICrossDomainMessenger} from 'interfaces/external/ICrossDomainMessenger.sol';
import {IOptimismPortal} from 'interfaces/external/IOptimismPortal.sol';

/**
* @title L1OpUSDCFactory
* @notice Factory contract to deploy and setup the `L1OpUSDCBridgeAdapter` contract on L1, the
* `L2OpUSDCBridgeAdapter` and USDC proxy and implementation contracts on L2 on a single transaction.
*/
contract L1OpUSDCFactory is IL1OpUSDCFactory {
uint256 internal constant _ZERO_VALUE = 0;

address internal constant _ZERO_ADDRESS = address(0);

bool internal constant _IS_CREATION = true;

address public constant L2_MESSENGER = 0x4200000000000000000000000000000000000007;

address public immutable ALIASED_SELF = AddressAliasHelper.applyL1ToL2Alias(address(this));

IL1OpUSDCBridgeAdapter public immutable L1_ADAPTER;

IUpgradeManager public immutable UPGRADE_MANAGER;

address public immutable L2_FACTORY;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to save the l2 factory? This contract should be useless after its deployed anyway

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True


address public immutable L2_ADAPTER;

address public immutable L2_USDC_PROXY;

address public immutable L2_USDC_IMPLEMENTATION;

constructor(address _usdc, address _owner) {
// Calculate l1 adapter
uint256 _thisNonceFirstTx = 1;
L1_ADAPTER = IL1OpUSDCBridgeAdapter(_precalculateCreateAddress(address(this), _thisNonceFirstTx));

/// NOTE: When the `msg.sender` is not a contract, the first nonce is 0, otherwise it is 1. The aliased address this
/// won't have any code on the L2, so its first nonce is 0.
// Calculate l2 factory address
uint256 _aliasedAddressFirstNonce = 0;
hexshire marked this conversation as resolved.
Show resolved Hide resolved
L2_FACTORY = _precalculateCreateAddress(ALIASED_SELF, _aliasedAddressFirstNonce);
// Calculate the l2 deployments using the l2 factory
uint256 _l2FactoryFirstNonce = 1;
L2_USDC_IMPLEMENTATION = _precalculateCreateAddress(L2_FACTORY, _l2FactoryFirstNonce);
uint256 _l2FactorySecondNonce = 2;
L2_USDC_PROXY = _precalculateCreateAddress(L2_FACTORY, _l2FactorySecondNonce);
uint256 _l2FactoryThirdNonce = 3;
L2_ADAPTER = _precalculateCreateAddress(L2_FACTORY, _l2FactoryThirdNonce);

// Calculate the upgrade manager using 3 as nonce since first the l1 adapter and its implementation will be deployed
uint256 _thisNonceThirdTx = 3;
UPGRADE_MANAGER = IUpgradeManager(_precalculateCreateAddress(address(this), _thisNonceThirdTx));

// Deploy the L1 adapter
new L1OpUSDCBridgeAdapter(_usdc, L2_ADAPTER, address(UPGRADE_MANAGER), address(this));
emit L1AdapterDeployed(address(L1_ADAPTER));

// Deploy the upgrade manager implementation
address _upgradeManagerImplementation = address(new UpgradeManager(address(L1_ADAPTER)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are we going to set the owner of the upgrade manager? Maybe a constructor param?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is set on the line 77 on the initialize tx

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh i am blind not enough coffee

// Deploy and initialize the upgrade manager proxy
bytes memory _initializeTx = abi.encodeWithSelector(IUpgradeManager.initialize.selector, _owner);
UpgradeManager(address(new ERC1967Proxy(address(_upgradeManagerImplementation), _initializeTx)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using ERC1967Proxy will left an incorrect name in Etherscan or any explorer... maybe is a good idea to wrap the proxy with a better name like UpgradeManagerProxy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a good idea to check this when we'll be verifying the contracts. If etherscan set the name to ERC1967Proxy, then makes sense to cast it to UpgradeManager. The same happens on L2 when deploying the l2 adapter

emit UpgradeManagerDeployed(address(UPGRADE_MANAGER));
}

/**
* @inheritdoc IL1OpUSDCFactory
*/
function deployL2UsdcAndAdapter(address _l1Messenger, uint32 _minGasLimit) external {
// Get the l2 usdc proxy init code
bytes memory _usdcProxyCArgs = abi.encode(L2_USDC_IMPLEMENTATION);
bytes memory _usdcProxyInitCode = bytes.concat(USDC_PROXY_BYTECODE, _usdcProxyCArgs);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the proxy of USDC will be always the same, I think is better to just encode the implementation address as unique argument and deploy by the giving init code and not the bytecode.


// Get the bytecode of the l2 usdc implementation and the l2 adapter
IUpgradeManager.Implementation memory _l2UsdcImplementation = UPGRADE_MANAGER.bridgedUSDCImplementation();
bytes memory _l2UsdcImplementationBytecode = _l2UsdcImplementation.implementation.code;

IUpgradeManager.Implementation memory _l2AdapterImplementation = UPGRADE_MANAGER.l2AdapterImplementation();
bytes memory _l2AdapterBytecode = _l2AdapterImplementation.implementation.code;

// Get the l2 factory init code
bytes memory _l2FactoryCreationCode = type(L2OpUSDCFactory).creationCode;
bytes memory _l2FactoryCArgs = abi.encode(
_usdcProxyInitCode,
_l2UsdcImplementationBytecode,
_l2UsdcImplementation.initTxs,
_l2AdapterBytecode,
_l2AdapterImplementation.initTxs
);
bytes memory _l2FactoryInitCode = bytes.concat(_l2FactoryCreationCode, _l2FactoryCArgs);

// Deploy L2 op usdc factory through portal
IOptimismPortal _portal = ICrossDomainMessenger(_l1Messenger).portal();
_portal.depositTransaction(_ZERO_ADDRESS, _ZERO_VALUE, _minGasLimit, _IS_CREATION, _l2FactoryInitCode);
}

/**
* @notice Precalculates the address of a contract that will be deployed thorugh `CREATE` opcode.
* @param _deployer The deployer address.
* @param _nonce The next nonce of the deployer address.
* @return _precalculatedAddress The address where the contract will be stored
*/
function _precalculateCreateAddress(
address _deployer,
uint256 _nonce
) internal pure returns (address _precalculatedAddress) {
bytes memory data;
bytes1 len = bytes1(0x94);

// The integer zero is treated as an empty byte string and therefore has only one length prefix,
// 0x80, which is calculated via 0x80 + 0.
if (_nonce == 0x00) {
data = abi.encodePacked(bytes1(0xd6), len, _deployer, bytes1(0x80));
}
// A one-byte integer in the [0x00, 0x7f] range uses its own value as a length prefix, there is no
// additional "0x80 + length" prefix that precedes it.
else if (_nonce <= 0x7f) {
data = abi.encodePacked(bytes1(0xd6), len, _deployer, uint8(_nonce));
}
// TODO: Needs check, but the following could be removed
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think since the following lines could be removed, but need to double-check it. Just an optimization

// In the case of `_nonce > 0x7f` and `_nonce <= type(uint8).max`, we have the following encoding scheme
// (the same calculation can be carried over for higher _nonce bytes):
// 0xda = 0xc0 (short RLP prefix) + 0x1a (= the bytes length of: 0x94 + address + 0x84 + _nonce, in hex),
// 0x94 = 0x80 + 0x14 (= the bytes length of an address, 20 bytes, in hex),
// 0x84 = 0x80 + 0x04 (= the bytes length of the _nonce, 4 bytes, in hex).
else if (_nonce <= type(uint8).max) {
data = abi.encodePacked(bytes1(0xd7), len, _deployer, bytes1(0x81), uint8(_nonce));
} else if (_nonce <= type(uint16).max) {
data = abi.encodePacked(bytes1(0xd8), len, _deployer, bytes1(0x82), uint16(_nonce));
} else if (_nonce <= type(uint24).max) {
data = abi.encodePacked(bytes1(0xd9), len, _deployer, bytes1(0x83), uint24(_nonce));
} else if (_nonce <= type(uint32).max) {
data = abi.encodePacked(bytes1(0xda), len, _deployer, bytes1(0x84), uint32(_nonce));
} else if (_nonce <= type(uint40).max) {
data = abi.encodePacked(bytes1(0xdb), len, _deployer, bytes1(0x85), uint40(_nonce));
} else if (_nonce <= type(uint48).max) {
data = abi.encodePacked(bytes1(0xdc), len, _deployer, bytes1(0x86), uint48(_nonce));
} else if (_nonce <= type(uint56).max) {
data = abi.encodePacked(bytes1(0xdd), len, _deployer, bytes1(0x87), uint56(_nonce));
} else {
data = abi.encodePacked(bytes1(0xde), len, _deployer, bytes1(0x88), uint64(_nonce));
}

_precalculatedAddress = address(uint160(uint256(keccak256(data))));
}
}
Loading
Loading