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

build: inherit create 3 #6

Merged
merged 4 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 16 additions & 10 deletions src/DeployerBase.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.20;

Check warning on line 2 in src/DeployerBase.sol

View workflow job for this annotation

GitHub Actions / solidity

Compiler version ^0.8.20 does not satisfy the 0.8.18 semver requirement

import {Positions} from "./Positions.sol";
import {Proxy} from "@zkevm-stb/Proxy.sol";
import {ICREATE3Factory} from "./interfaces/ICREATE3Factory.sol";
import {CREATE3} from "./libraries/CREATE3.sol";
import {IPolygonZkEVMBridge} from "./interfaces/Polygon/IPolygonZkEVMBridge.sol";

/**
Expand All @@ -13,10 +13,6 @@
contract DeployerBase is Positions {
uint32 internal constant ORIGIN_NETWORK_ID = 0;

/// @notice Address of the ICREATE3Factory contract used for deployment
ICREATE3Factory internal constant create3Factory =
ICREATE3Factory(0x93FEC2C00BfE902F733B57c5a6CeeD7CD1384AE1);

/*//////////////////////////////////////////////////////////////
POSITION ID'S
//////////////////////////////////////////////////////////////*/
Expand All @@ -27,7 +23,7 @@
keccak256("Escrow Implementation");

/// @notice Address of the PolygonZkEVMBridge contract
IPolygonZkEVMBridge public immutable polygonZkEVMBridge;

Check warning on line 26 in src/DeployerBase.sol

View workflow job for this annotation

GitHub Actions / solidity

Immutable variables name are set to be in capitalized SNAKE_CASE

constructor(
address _polygonZkEVMBridge,
Expand All @@ -50,7 +46,7 @@
address _l1TokenAddress
) public view virtual returns (address) {
return
create3Factory.getDeployed(
_getDeployed(
getPositionHolder(L2_DEPLOYER),
keccak256(abi.encodePacked(bytes("L2Token:"), _l1TokenAddress))
);
Expand All @@ -65,7 +61,7 @@
address _l1TokenAddress
) public view virtual returns (address) {
return
create3Factory.getDeployed(
_getDeployed(
getPositionHolder(L1_DEPLOYER),
keccak256(abi.encodePacked(bytes("L1Escrow:"), _l1TokenAddress))
);
Expand All @@ -80,7 +76,7 @@
address _l1TokenAddress
) public view virtual returns (address) {
return
create3Factory.getDeployed(
_getDeployed(
getPositionHolder(L2_DEPLOYER),
keccak256(abi.encodePacked(bytes("L2Escrow:"), _l1TokenAddress))
);
Expand All @@ -95,7 +91,7 @@
address _l1TokenAddress
) public view virtual returns (address) {
return
create3Factory.getDeployed(
_getDeployed(
getPositionHolder(L2_DEPLOYER),
keccak256(
abi.encodePacked(
Expand All @@ -106,6 +102,16 @@
);
}

/**
* @dev Get the expected address based on the deployer and salt.
*/
function _getDeployed(
address deployer,
bytes32 salt
) internal view virtual returns (address) {
return CREATE3.getDeployed(deployer, salt);
}

/**
* @notice Deploy a contract using CREATE3
* @param _salt Salt value for contract deployment
Expand All @@ -123,6 +129,6 @@
abi.encode(_implementation, _initData)
);

return create3Factory.deploy(_salt, _creationCode);
return CREATE3.deploy(_salt, _creationCode, 0);
}
}
24 changes: 12 additions & 12 deletions src/L1Deployer.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.20;

Check warning on line 2 in src/L1Deployer.sol

View workflow job for this annotation

GitHub Actions / solidity

Compiler version ^0.8.20 does not satisfy the 0.8.18 semver requirement

import {Proxy} from "@zkevm-stb/Proxy.sol";

Check warning on line 4 in src/L1Deployer.sol

View workflow job for this annotation

GitHub Actions / solidity

imported name Proxy is not used
import {RoleManager} from "./RoleManager.sol";
import {L1YearnEscrow} from "./L1YearnEscrow.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
Expand All @@ -25,7 +25,7 @@
struct ChainConfig {
IPolygonRollupContract rollupContract;
address escrowManager;
mapping(address => address) escrows;
mapping(address => address) escrows; // asset => escrow contract
}

/// @notice Only allow either governance or the position holder to call.
Expand All @@ -46,7 +46,7 @@
IMMUTABLE'S
//////////////////////////////////////////////////////////////*/

IPolygonRollupManager public immutable rollupManager;

Check warning on line 49 in src/L1Deployer.sol

View workflow job for this annotation

GitHub Actions / solidity

Immutable variables name are set to be in capitalized SNAKE_CASE

/*//////////////////////////////////////////////////////////////
STORAGE
Expand Down Expand Up @@ -113,7 +113,7 @@
_registerRollup(_rollupID, address(0));
}

// Verify that the vault is not already set for that chain.
// Verify that an escrow is not already deployed for that chain.
_l1Escrow = getEscrow(_rollupID, _asset);
if (_l1Escrow != address(0)) revert AlreadyDeployed(_l1Escrow);

Expand Down Expand Up @@ -155,22 +155,23 @@
uint32 _rollupID,
address _escrowManager
) internal virtual {
ChainConfig storage chainConfig_ = _chainConfig[_rollupID];

IPolygonRollupContract _rollupContract = rollupManager
.rollupIDToRollupData(_rollupID)
.rollupContract;

// Checks the rollup ID is valid
address admin = _rollupContract.admin();
// If the caller is not the rollup Admin.
if (msg.sender != _rollupContract.admin()) {
if (
msg.sender != _rollupContract.admin() ||
_escrowManager == address(0)
) {
// Default the manager to be the admin
_escrowManager = admin;
}

chainConfig_.rollupContract = _rollupContract;
chainConfig_.escrowManager = _escrowManager;
_chainConfig[_rollupID].rollupContract = _rollupContract;
_chainConfig[_rollupID].escrowManager = _escrowManager;

emit RegisteredNewRollup(
_rollupID,
Expand Down Expand Up @@ -202,7 +203,7 @@
* @notice Creates a new custom vault and escrow for a specific asset on the specified rollup.
* @param _rollupID The ID of the rollup.
* @param _asset The address of the asset for which the vault and escrow are created.
* @return _l1Escrow The address of the newly created L1 escrow.
* @return _l1Escrow The address of the L1 escrow.
* @return _vault The address of the newly created vault.
*/
function newCustomVault(
Expand All @@ -219,17 +220,18 @@
}

/**
* @notice Creates a new custom vault for a specific asset on the specified rollup.
* @notice Adds a new custom vault for a specific asset on the specified rollup.
* @param _rollupID The ID of the rollup.
* @param _asset The address of the asset for which the vault is created.
* @param _vault The address of the vault.
* @return _l1Escrow The address of the newly created L1 escrow.
* @return _l1Escrow The address of the L1 escrow.
*/
function newCustomVault(
uint32 _rollupID,
address _asset,
address _vault
) external virtual onlyRollupAdmin(_rollupID) returns (address _l1Escrow) {
// If the vault has not been registered yet.
if (!isVaultsRoleManager(_vault)) {
_addNewVault(_rollupID, _vault);
}
Expand All @@ -250,8 +252,6 @@
if (_l1Escrow == address(0)) {
_l1Escrow = _deployL1Escrow(_rollupID, _asset, _vault);
}

_assetToVault[_asset][_rollupID] = _vault;
}

/*//////////////////////////////////////////////////////////////
Expand All @@ -262,7 +262,7 @@
* @dev Deploys a new L1 Escrow and send a message to the bridge to
* tell the L2 deployer to deploy the needed contract on the L2
*/
function _deployL1Escrow(

Check warning on line 265 in src/L1Deployer.sol

View workflow job for this annotation

GitHub Actions / solidity

Function body contains 51 lines but allowed no more than 50 lines
uint32 _rollupID,
address _asset,
address _vault
Expand Down
13 changes: 8 additions & 5 deletions src/L1YearnEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ contract L1YearnEscrow is L1Escrow {
}
}

// Check again to account for if there was underlying
// Check again to account for if there was loose underlying
if (amount > maxWithdraw) {
// Send an equivalent amount of shares for the difference.
uint256 shares = _vault.convertToShares(amount - maxWithdraw);
Expand Down Expand Up @@ -239,15 +239,18 @@ contract L1YearnEscrow is L1Escrow {
// Max approve the new vault
originToken.forceApprove(_vaultAddress, 2 ** 256 - 1);

// Deposit any loose funds
// Deposit any loose funds over minimum buffer
uint256 balance = originToken.balanceOf(address(this));
if (balance != 0)
IVault(_vaultAddress).deposit(balance, address(this));
uint256 minimumBuffer = $.minimumBuffer;
if (balance > minimumBuffer)
IVault(_vaultAddress).deposit(
balance - minimumBuffer,
address(this)
);
}

// Update Storage
$.vaultAddress = IVault(_vaultAddress);

emit UpdateVaultAddress(_vaultAddress);
}

Expand Down
22 changes: 22 additions & 0 deletions src/RoleManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,28 @@ contract RoleManager is DeployerBase {
VAULT MANAGEMENT
//////////////////////////////////////////////////////////////*/

/**
* @notice Deploys a new vault to the RoleManager for the default version.
* @dev This will override any existing default vault.
* @param _asset Address of the asset to be used.
*/
function newVault(
address _asset
) external virtual onlyPositionHolder(GOVERNATOR) {
_newVault(ORIGIN_NETWORK_ID, _asset);
}

/**
* @notice Adds a new vault to the RoleManager for the default version.
* @dev This will override any existing default vault.
* @param _vault Address of the vault to be added.
*/
function addNewVault(
address _vault
) external virtual onlyPositionHolder(GOVERNATOR) {
_addNewVault(ORIGIN_NETWORK_ID, _vault);
}

/**
* @notice Adds a new vault to the RoleManager with the specified category and debt allocator.
* @dev If not already endorsed this function will endorse the vault.
Expand Down
13 changes: 0 additions & 13 deletions src/interfaces/ICREATE3Factory.sol

This file was deleted.

18 changes: 18 additions & 0 deletions src/libraries/Bytes32AddressLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Library for converting between addresses and bytes32 values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Bytes32AddressLib.sol)
library Bytes32AddressLib {
function fromLast20Bytes(
bytes32 bytesValue
) internal pure returns (address) {
return address(uint160(uint256(bytesValue)));
}

function fillLast12Bytes(
address addressValue
) internal pure returns (bytes32) {
return bytes32(bytes20(addressValue));
}
}
91 changes: 91 additions & 0 deletions src/libraries/CREATE3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {Bytes32AddressLib} from "./Bytes32AddressLib.sol";

/// @notice Deploy to deterministic addresses without an initcode factor.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol)
/// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol)
library CREATE3 {
using Bytes32AddressLib for bytes32;

//--------------------------------------------------------------------------------//
// Opcode | Opcode + Arguments | Description | Stack View //
//--------------------------------------------------------------------------------//
// 0x36 | 0x36 | CALLDATASIZE | size //
// 0x3d | 0x3d | RETURNDATASIZE | 0 size //
// 0x3d | 0x3d | RETURNDATASIZE | 0 0 size //
// 0x37 | 0x37 | CALLDATACOPY | //
// 0x36 | 0x36 | CALLDATASIZE | size //
// 0x3d | 0x3d | RETURNDATASIZE | 0 size //
// 0x34 | 0x34 | CALLVALUE | value 0 size //
// 0xf0 | 0xf0 | CREATE | newContract //
//--------------------------------------------------------------------------------//
// Opcode | Opcode + Arguments | Description | Stack View //
//--------------------------------------------------------------------------------//
// 0x67 | 0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode | bytecode //
// 0x3d | 0x3d | RETURNDATASIZE | 0 bytecode //
// 0x52 | 0x52 | MSTORE | //
// 0x60 | 0x6008 | PUSH1 08 | 8 //
// 0x60 | 0x6018 | PUSH1 18 | 24 8 //
// 0xf3 | 0xf3 | RETURN | //
//--------------------------------------------------------------------------------//
bytes internal constant PROXY_BYTECODE =
hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";

bytes32 internal constant PROXY_BYTECODE_HASH = keccak256(PROXY_BYTECODE);

function deploy(
bytes32 salt,
bytes memory creationCode,
uint256 value
) internal returns (address deployed) {
bytes memory proxyChildBytecode = PROXY_BYTECODE;

address proxy;
assembly {
// Deploy a new contract with our pre-made bytecode via CREATE2.
// We start 32 bytes into the code to avoid copying the byte length.
proxy := create2(
0,
add(proxyChildBytecode, 32),
mload(proxyChildBytecode),
salt
)
}
require(proxy != address(0), "DEPLOYMENT_FAILED");

deployed = getDeployed(address(this), salt);
(bool success, ) = proxy.call{value: value}(creationCode);
require(success && deployed.code.length != 0, "INITIALIZATION_FAILED");
}

function getDeployed(
address deployer,
bytes32 salt
) internal pure returns (address) {
address proxy = keccak256(
abi.encodePacked(
// Prefix:
bytes1(0xFF),
// Creator:
deployer,
// Salt:
salt,
// Bytecode hash:
PROXY_BYTECODE_HASH
)
).fromLast20Bytes();

return
keccak256(
abi.encodePacked(
// 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01)
// 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)
hex"d6_94",
proxy,
hex"01" // Nonce of the proxy contract (1)
)
).fromLast20Bytes();
}
}
Loading
Loading