Skip to content

Commit

Permalink
build: l2 deployer
Browse files Browse the repository at this point in the history
  • Loading branch information
Schlagonia committed Apr 18, 2024
1 parent 0a47131 commit 39829a3
Show file tree
Hide file tree
Showing 8 changed files with 372 additions and 83 deletions.
20 changes: 20 additions & 0 deletions src/DeployerBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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 {ICREATE3Factory} from "./interfaces/ICREATE3Factory.sol";

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

Check warning on line 6 in src/DeployerBase.sol

View workflow job for this annotation

GitHub Actions / solidity

imported name ERC20 is not used

contract DeployerBase {
ICREATE3Factory internal constant create3Factory =

Check warning on line 9 in src/DeployerBase.sol

View workflow job for this annotation

GitHub Actions / solidity

Constant name must be in capitalized SNAKE_CASE
ICREATE3Factory(0x93FEC2C00BfE902F733B57c5a6CeeD7CD1384AE1);

address public immutable counterPartContract;

Check warning on line 12 in src/DeployerBase.sol

View workflow job for this annotation

GitHub Actions / solidity

Immutable variables name are set to be in capitalized SNAKE_CASE

address public immutable polygonZkEVMBridge;

Check warning on line 14 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 _counterPartContract, address _polygonZkEVMBridge) {
counterPartContract = _counterPartContract;
polygonZkEVMBridge = _polygonZkEVMBridge;
}
}
102 changes: 59 additions & 43 deletions src/L1Deployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@ pragma solidity ^0.8.20;

import {L1YearnEscrow} from "./L1YearnEscrow.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import {IPolygonZkEVMBridge} from "@zkevm-stb/interfaces/IPolygonZkEVMBridge.sol";
import {IPolygonRollupManager, IPolygonRollupContract} from "./interfaces/Polygon/IPolygonRollupManager.sol";

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

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

import {ICREATE3Factory} from "./interfaces/ICREATE3Factory.sol";

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

// TODO:
// 1. Deposit Limits/module
// create 3 factory
// External create3 Address getters

/// Governace Structure:
/// Governance Structure:
// 1. GOVERNATOR Can change the Holders, Impl and addresses (Rare) 2/3 meta multisig (No Roles)
// 2. CZAR/DADDY Sets strategies All Roles
// 3. Management/SMS Day to Day Ops
Expand All @@ -31,6 +33,8 @@ contract L1Deployer is RoleManager {
address indexed manager
);

event UpdateRollupManager(uint32 indexed rollupID, address indexed manager);

event NewL1Escrow(uint32 indexed rollupID, address indexed l1Escrow);

struct ChainConfig {
Expand All @@ -40,36 +44,37 @@ contract L1Deployer is RoleManager {
}

/// @notice Only allow either governance or the position holder to call.
modifier onlyChainAdmin(uint32 _rollupID) {
_isChainAdmin(_rollupID);
modifier onlyRollupAdmin(uint32 _rollupID) {
_isRollupAdmin(_rollupID);
_;
}

/// @notice Check if the msg sender is governance or the specified position holder.
function _isChainAdmin(uint32 _rollupID) internal view virtual {
function _isRollupAdmin(uint32 _rollupID) internal view virtual {
require(
msg.sender == chainConfig[_rollupID].rollupContract.admin(),
"!admin"
);
}

ICREATE3Factory internal create3Factory =
ICREATE3Factory(0x93FEC2C00BfE902F733B57c5a6CeeD7CD1384AE1);

/*//////////////////////////////////////////////////////////////
POSITION ID'S
//////////////////////////////////////////////////////////////*/

bytes32 public constant ESCROW_IMPLEMENTATION =
keccak256("Escrow Implementation");

bytes32 public constant L2_DEPLOYER = keccak256("L2 Deployer");

uint256 public immutable originalID;
ICREATE3Factory internal constant create3Factory =
ICREATE3Factory(0x93FEC2C00BfE902F733B57c5a6CeeD7CD1384AE1);

address public immutable bridgeAddress;
uint256 public immutable originalID;

address public immutable rollupManager;

address public immutable polygonZkEVMBridge;

/*//////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -97,8 +102,9 @@ contract L1Deployer is RoleManager {
)
{
originalID = block.chainid;
bridgeAddress = IPolygonRollupManager(_rollupManager).bridgeAddress();
rollupManager = _rollupManager;
polygonZkEVMBridge = IPolygonRollupManager(_rollupManager)
.bridgeAddress();

_positions[ESCROW_IMPLEMENTATION].holder = _escrowImplementation;
}
Expand Down Expand Up @@ -130,36 +136,30 @@ contract L1Deployer is RoleManager {
);
}

function updateRollupManager(
uint32 _rollupID,
address _l1Manager
) external virtual onlyRollupAdmin(_rollupID) {
require(_l1Manager != address(0), "ZERO ADDRESS");
chainConfig[_rollupID].manager = _l1Manager;

emit UpdateRollupManager(_rollupID, _l1Manager);
}

/*//////////////////////////////////////////////////////////////
ESCROW CREATION
//////////////////////////////////////////////////////////////*/

function newAsset(
uint32 _rollupID,
address _asset
) external returns (address, address) {
) external virtual returns (address _vault, address _l1Escrow) {
// Verify the rollup Id is valid.
require(
address(chainConfig[_rollupID].rollupContract) != address(0),
"rollup not registered"
);
return _newAsset(_rollupID, _asset, 0);
}

function newAsset(
uint32 _rollupID,
address _asset,
uint256 _minimumBuffer
) external onlyChainAdmin(_rollupID) returns (address, address) {
// Modifier passing implies a valid rollup ID.
return _newAsset(_rollupID, _asset, _minimumBuffer);
}

function _newAsset(
uint32 _rollupID,
address _asset,
uint256 _minimumBuffer
) internal virtual returns (address _vault, address _l1Escrow) {
// Verify that the vault is not already set for that chain.
_l1Escrow = getEscrow(_rollupID, _asset);
if (_l1Escrow != address(0)) revert AlreadyDeployed(_l1Escrow);
Expand All @@ -173,13 +173,13 @@ contract L1Deployer is RoleManager {
}

// Deploy L1 Escrow.
_l1Escrow = _deployL1Escrow(_rollupID, _asset, _vault, _minimumBuffer);
_l1Escrow = _deployL1Escrow(_rollupID, _asset, _vault);
}

function newCustomAsset(
uint32 _rollupID,
address _asset
) external virtual onlyChainAdmin(_rollupID) returns (address _vault) {
) external virtual onlyRollupAdmin(_rollupID) returns (address _vault) {
string memory _rollupIDString = Strings.toString(_rollupID);

// Name is "{SYMBOL}-STB-{rollupID} yVault"
Expand Down Expand Up @@ -218,7 +218,7 @@ contract L1Deployer is RoleManager {
uint32 _rollupID,
address _asset,
address _vault
) external virtual onlyChainAdmin(_rollupID) {
) external virtual onlyRollupAdmin(_rollupID) {
_addNewVault(_rollupID, _vault);
_newCustomAsset(_rollupID, _asset, _vault);
}
Expand All @@ -231,7 +231,7 @@ contract L1Deployer is RoleManager {
address _l1Escrow = getEscrow(_rollupID, _asset);

if (_l1Escrow == address(0)) {
_l1Escrow = _deployL1Escrow(_rollupID, _asset, _vault, 0);
_l1Escrow = _deployL1Escrow(_rollupID, _asset, _vault);
}

_assetToVault[_asset][_rollupID] = _vault;
Expand Down Expand Up @@ -267,8 +267,7 @@ contract L1Deployer is RoleManager {
function _deployL1Escrow(
uint32 _rollupID,
address _asset,
address _vault,
uint256 _minimumBuffer
address _vault
) internal returns (address _l1Escrow) {
ChainConfig storage _chainConfig = chainConfig[_rollupID];

Expand All @@ -278,13 +277,12 @@ contract L1Deployer is RoleManager {
L1YearnEscrow.initialize.selector,
_chainConfig.rollupContract.admin(),
_chainConfig.manager,
bridgeAddress,
polygonZkEVMBridge,
_getL2EscrowAddress(symbol),
_rollupID,
_asset,
_getL2TokenAddress(symbol),
_vault,
_minimumBuffer
_vault
);

bytes memory creationCode = abi.encodePacked(
Expand All @@ -305,40 +303,58 @@ contract L1Deployer is RoleManager {

// Send Message to Bridge for L2
// TODO: Will L2 Deployer be the same each chain?
IPolygonZkEVMBridge(bridgeAddress).bridgeMessage(
IPolygonZkEVMBridge(polygonZkEVMBridge).bridgeMessage(
_rollupID,
getPositionHolder(L2_DEPLOYER),
false,
abi.encode(_asset, _l1Escrow)
abi.encode(_asset, _l1Escrow, ERC20(_asset).name(), string(symbol))
);

emit NewL1Escrow(_rollupID, _l1Escrow);
}

function getL1EscrowAddress(
address _asset
) external view virtual returns (address) {
return _getL1EscrowAddress(bytes(ERC20(_asset).symbol()));
}

function _getL1EscrowAddress(
bytes memory _symbol
) internal returns (address) {
) internal view returns (address) {
return
create3Factory.getDeployed(
address(this),
keccak256(abi.encodePacked(bytes("L1Escrow:"), _symbol))
);
}

function getL2EscrowAddress(
address _asset
) external view virtual returns (address) {
return _getL2EscrowAddress(bytes(ERC20(_asset).symbol()));
}

// Address will be the L2 deployer
function _getL2EscrowAddress(
bytes memory _symbol
) internal returns (address) {
) internal view returns (address) {
return
create3Factory.getDeployed(
getPositionHolder(L2_DEPLOYER),
keccak256(abi.encodePacked(bytes("L2Escrow:"), _symbol))
);
}

function getL2TokenAddress(
address _asset
) external view virtual returns (address) {
return _getL2TokenAddress(bytes(ERC20(_asset).symbol()));
}

function _getL2TokenAddress(
bytes memory _symbol
) internal returns (address) {
) internal view returns (address) {
return
create3Factory.getDeployed(
getPositionHolder(L2_DEPLOYER),
Expand Down
14 changes: 10 additions & 4 deletions src/L1YearnEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ contract L1YearnEscrow is L1Escrow {
* @param _originTokenAddress Token address
* @param _wrappedTokenAddress L2Token address on Polygon ZkEVM
* @param _vaultAddress Address of the vault to use.
* @param _minimumBuffer Buffer if any to keep idle.
*/
function initialize(
address _admin,
Expand All @@ -74,8 +73,7 @@ contract L1YearnEscrow is L1Escrow {
uint32 _counterpartNetwork,
address _originTokenAddress,
address _wrappedTokenAddress,
address _vaultAddress,
uint256 _minimumBuffer
address _vaultAddress
) public virtual initializer {
// Initialize the default escrow.
initialize(
Expand All @@ -91,7 +89,6 @@ contract L1YearnEscrow is L1Escrow {
VaultStorage storage $ = _getVaultStorage();
// Set the vault variables
$.vaultAddress = IVault(_vaultAddress);
$.minimumBuffer = _minimumBuffer;
}

// ****************************
Expand Down Expand Up @@ -177,6 +174,11 @@ contract L1YearnEscrow is L1Escrow {
// * Admin *
// ****************************

/**
* @dev Update the vault to deploy funds into.
* Will fully withdraw from the old vault.
* @param _vaultAddress Address of the new vault to use.
*/
function updateVault(
address _vaultAddress
) external virtual onlyRole(DEFAULT_ADMIN_ROLE) {
Expand All @@ -195,6 +197,10 @@ contract L1YearnEscrow is L1Escrow {
emit UpdateVaultAddress(_vaultAddress);
}

/**
* @dev Update the minimum buffer to keep in the escrow.
* @param _minimumBuffer The new minimum buffer to enforce.
*/
function updateMinimumBuffer(
uint256 _minimumBuffer
) external virtual onlyRole(DEFAULT_ADMIN_ROLE) {
Expand Down
Loading

0 comments on commit 39829a3

Please sign in to comment.