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

Conversation

0xDiscotech
Copy link
Contributor

🤖 Linear

Closes OPT-67

* chore: clean factory contract a bit

* fix: factory errors
* feat: add salt as param

* chore: polish factory contract and remove some notes
* feat: add more values on deploy values struct

* fix: remove broken deploy create 2 and init function usage

* chore: update deployment scripts values
* feat: add deployment addresses returned struct

* chore: update natspec based on changes

* feat: create internal functions for salt logic

* refactor: create common script contract and update mainnet and sepolia ones
* refactor: update some vars visibility and names on the contract

* chore: update natspec based on changes
* chore: add natspec over unit tests

* fix: one return value on factory contract

* chore: remove unused createx contract
chore: undo changes over pkg json and remappings
* refactor: update l1 factory and scripts
…oyer

* feat: create bytecode deployer

* refactor: pre calculate all addresses in l1 factory constructor

* refactor: update interfaces with new and needed methods

* refactor: update deployment scripts based on new changes
…ded function to l1 factory

* fix: imports over deleted files and unneccessary imports

* chore: add some comments on vars natspec
…with create deploy on l2

* refacor: update deploy functions params and natspec
* feat: add init txs calls while sending a message and execution on l2 factory

* fix: upgrade manager tests

* chore: add some comments and stack vars
@0xDiscotech 0xDiscotech self-assigned this May 24, 2024
Copy link

linear bot commented May 24, 2024

OPT-67 Implement the solution for deploying bridged usdc and l2 adapter to the same address

dependent on spike OPT-51

UpgradeManager:

  • l2AdapterImplementation should be a struct with data and address

  • bridgedUSDCImplementation should be a struct with data and address

  • Create our own minimalistic factory that will use create2 to deploy all contracts

  • The factory will be a onetime deployment and will deploy everything in its constructor leading it deploy all contracts in one message

@0xDiscotech
Copy link
Contributor Author

0xDiscotech commented May 24, 2024

Deployments info (precalculated addresses on the L1 Factory deployment):

Deploying L1OpUSDCFactory ...

L1:

  L1OpUSDCFactory deployed at: 0x10F5176D7c8d78789F714f5eec37F0A01c869D58
  L1OpUSDCBridgeAdapter deployed at: 0xeaaA51C30C4848Cdd0126337D9aBee983d1Fd533
  L1 UpgradeManager deployed at: 0xd6254ebE0Fb0F01EA7f9BBea8a136460C4D5EF1b

L2:

Aliased L1 factory deployment address: 0x2206176d7c8d78789F714F5EEc37f0a01c86AE69
L2OpUSDCBridgeAdapter impl deployment address: 0x449Ded3EAdd5A5b3b8402fBf4BFB29Ce61a698De
L2OpUSDCBridgeAdapter proxy deployment address: 0x0af46d456f122a1500fda51651ad4F37a87aA729
L2 USDC proxy deployed deployment address: 0x095C1dC0071753F24bc7874ad27f9fa2D3e60098
L2 USDC implementation deployed deployment address: 0xd4d9225d89CCF3BF09B9E08E8A12ec51947255f7

The addresses were deployed to OP-Sepolia and Base Sepolia.

The addresses are the same ✅

Comment on lines -11 to -15
[profile.default]
solc_version = '0.8.25'
libs = ['node_modules']
optimizer_runs = 10_000

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

Comment on lines +15 to +16
[profile.default.optimizer_details]
yul = false
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

Comment on lines 87 to 88
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.

* feat: add args to the expect deposit tx call on test
* fix: use expect call instead of mock call to avoid foundry issues
* feat: add unit test over bytecode deployer

* chore: undo toml changes
* fix: revert the bytecode deployer to the previous version

* fix: update tests based on new changes
@0xDiscotech 0xDiscotech marked this pull request as ready for review May 25, 2024 02:29
// 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 Factory contract for deploying the L2 USDC implementation, proxy, and `L2OpUSDCBridgeAdapter` contracts all
* at once on the constructor
*/
contract L2OpUSDCFactory is IL2OpUSDCFactory {
Copy link
Contributor

Choose a reason for hiding this comment

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

Will the address of this L2 factory always be the same because of the aliased sender? If thats the case can we use CREATE2 for proxy and impl deployments, It will make the logic much simpler on L1 and cheaper to check

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah that'd be better. However I need to check what happens when the deployment on L2 reverts

Copy link
Contributor

Choose a reason for hiding this comment

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

It should only revert if the address on L2 is already occupied, meaning we have already deployed our contracts on that given chain, according to OP team the portal shouldnt revert

emit DeployedUSDCProxy(_usdcProxy);

// Deploy L2 adapter
address _adapter = address(new BytecodeDeployer(_l2AdapterBytecode));
Copy link
Contributor

@excaliborr excaliborr May 27, 2024

Choose a reason for hiding this comment

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

We also need the L2 Adapter proxy deployed, we have the init code for this as its just the proxy contract with impl address as 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.

True, good catch

constructor(address _usdc, address _owner) {
// Calculate L1 adapter
uint256 _thisNonceFirstTx = 1;
L1_ADAPTER = _precalculateCreateAddress(address(this), _thisNonceFirstTx);
Copy link
Contributor

@excaliborr excaliborr May 27, 2024

Choose a reason for hiding this comment

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

For these wouldnt CREATE2 be easier? For the L1 adapter and UpgradeManager? Probably also much cheaper to precalculate the address, and simpler

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree!

* @param _portal The address of the portal contract for the respective L2 chain
* @param _minGasLimit The minimum gas limit for the L2 deployment
*/
function deployL2UsdcAndAdapter(address _portal, uint32 _minGasLimit) external {
Copy link
Contributor

@excaliborr excaliborr May 27, 2024

Choose a reason for hiding this comment

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

lets send the _messenger and get the portal from there as we will need the messenger address for permissioned checks and logic later

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Where will the _messenger be needed? on L2?

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 thought we would set it on an init tx when deployed

Copy link
Contributor

Choose a reason for hiding this comment

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

Each op-chain has a unique _l1Messenger, which has the portal accessible through a variable iirc, we will only be able to deploy for a given whitelisted _messenger which will be a check we will add in a future PR, you only need the _messenger to get the portal for now

See tasks here:
https://linear.app/defi-wonderland/issue/OPT-70/add-upgrademanager-permissioned-functions-to-the-factory

Copy link
Contributor Author

@0xDiscotech 0xDiscotech May 27, 2024

Choose a reason for hiding this comment

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

Awesome. Yes, the portal will be accessible through the messenger

* refactor: update mock and expect usage on  l1 factory deploy function tests due to foundry error

* chore: removed unnecessary imports on mainnet script
address _upgradeManagerImplementation = address(new UpgradeManager(L1_ADAPTER));
// 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

// Execute the USDC initialization transactions
if (_usdcImplInitTxs.length > 0) {
// Initialize usdc implementation
for (uint256 i = 0; i < _usdcImplInitTxs.length; i++) {
Copy link
Member

@hexshire hexshire May 27, 2024

Choose a reason for hiding this comment

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

Suggested change
for (uint256 i = 0; i < _usdcImplInitTxs.length; i++) {
for (uint256 i; i < _usdcImplInitTxs.length; i++) {

emit DeployedL2AdapterImplementation(_adapterImplementation);

// Deploy L2 adapter proxy
bytes memory _adapterInitTx = _l2AdapterInitTxs.length > 0 ? _l2AdapterInitTxs[0] : bytes('');
Copy link
Contributor

Choose a reason for hiding this comment

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

Its better if we always send bytes('') this will also effect CREATE2 later, and we can call the initialization functions in the loop later

Copy link
Contributor

Choose a reason for hiding this comment

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

Important to keep in mind we currently call _disableInitializors in the constructor of the L2 Adapter as well, do we need this call? Doesnt need to be in this PR but I wanted to point it out

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah good point. I'd do everything related to the CREATE2 update on that PR, but will create a note about this. Also, I don't think we should hardcode any call on that contract but instead receiving it from the init txs array.
We should research which calls do we need to do in order to properly setup the proxy - @hexshire Do you have the answer here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ye I agree, we should probably remove this call and handle initialization functions in future implementations imo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

100% agreed

*/
function test_callBridgedUSDCImplementation(address _l1Messenger, uint32 _minGasLimit) public {
// Mock all the `deployL2UsdcAndAdapter` function calls
_mockDeployFunctionCalls(_l1Messenger);
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe tests are failing because we are fuzzing the _l1Messenger address and foundry cant fuzz that logic cause of its vm, we can set something like this in the base

  // cant fuzz this because of foundry's VM
  address internal _messenger = makeAddr('messenger');

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ty ser!

Copy link
Contributor

@excaliborr excaliborr left a comment

Choose a reason for hiding this comment

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

lgtm!

@excaliborr excaliborr merged commit a0eb0dd into dev May 27, 2024
4 checks passed
@excaliborr excaliborr deleted the feat/proxies-and-custom-factory branch May 27, 2024 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants