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

added beacon & refactored #4

Merged
merged 8 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ PRIVATE_KEY=YOUR PRIVATE KEY

# RPC Endpoints
INFURA_KEY=INFURA PROJECT ID
ALCHEMY_KEY=ALCHEMY PROJECT ID

# Additional keys
ETHERSCAN_KEY=ETHERSCAN API KEY
Expand Down
103 changes: 76 additions & 27 deletions contracts/Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
pragma solidity ^0.8.20;

import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {IFreezableBeaconProxy, FreezableBeaconProxy} from "./proxy/FreezableBeaconProxy.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";

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

abstract contract Factory is IFactory, OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable {
mapping(uint8 => address) internal _implementations;
mapping(uint8 poolType => UpgradeableBeacon) internal _beacons;
mapping(bytes32 => bool) private _usedSalts;

/**
* @dev It is used exclusively for storing information about the detached proxies.
*
* `_msgSender()` -> `poolName` -> `poolType` -> `proxy`
*/
mapping(address => mapping(string => mapping(uint8 => address))) public deployedProxies;
mapping(address deployer => mapping(string protocol => mapping(uint8 poolType => address proxy)))
public deployedProxies;

function __Factory_init() internal onlyInitializing {}

Expand All @@ -37,13 +37,48 @@ abstract contract Factory is IFactory, OwnableUpgradeable, PausableUpgradeable,
}

/**
* @notice The function to set implementation for the specific pool.
*
* @notice The function to freeze the specific pool.
* @param protocol_ the name of the protocol.
* @param poolType_ the type of the pool.
* @param implementation_ the implementation the pool will point to.
*/
function setImplementation(uint8 poolType_, address implementation_) public onlyOwner {
_implementations[poolType_] = implementation_;
function freezePool(string calldata protocol_, uint8 poolType_) public {
address proxy_ = deployedProxies[_msgSender()][protocol_][poolType_];

require(proxy_ != address(0), "F: pool not found");

IFreezableBeaconProxy(proxy_).freeze();
}

/**
* @notice The function to unfreeze the specific pool.
* @param protocol_ the name of the protocol.
* @param poolType_ the type of the pool.
*/
function unfreezePool(string calldata protocol_, uint8 poolType_) public {
address proxy_ = deployedProxies[_msgSender()][protocol_][poolType_];

require(proxy_ != address(0), "F: pool not found");

IFreezableBeaconProxy(proxy_).unfreeze();
}

/**
* The function to set the implementation for the specific pool.
*
* @param poolTypes_ The types of the pools.
* @param implementations_ The new implementations pools will point to.
*/
function setImplementations(uint8[] calldata poolTypes_, address[] calldata implementations_) public onlyOwner {
for (uint256 i = 0; i < poolTypes_.length; i++) {
uint8 poolType_ = poolTypes_[i];
address implementation_ = implementations_[i];

if (address(_beacons[poolType_]) == address(0)) {
_beacons[poolType_] = new UpgradeableBeacon(implementation_);
} else if (_beacons[poolType_].implementation() != implementation_) {
_beacons[poolType_].upgradeTo(implementation_);
}
}
}

/**
Expand All @@ -53,55 +88,69 @@ abstract contract Factory is IFactory, OwnableUpgradeable, PausableUpgradeable,
* @return implementation the implementation which the pool points to.
*/
function getImplementation(uint8 poolType_) public view returns (address) {
return _implementations[poolType_];
return UpgradeableBeacon(getBeacon(poolType_)).implementation();
}

/**
* @notice The function to get beacon of the specific pools.
*
* @param poolType_ the type of the pools.
* @return beacon the beacon which the pool points to.
*/
function getBeacon(uint8 poolType_) public view returns (address) {
address beacon_ = address(_beacons[poolType_]);

require(beacon_ != address(0), "F: beacon not found");

return beacon_;
}

/**
* @notice The function to deploy new `ERC1967Proxy`.
*
* @param protocol_ the name of the protocol.
* @param poolType_ the type of the pool.
* @param poolName_ the name of the pool.
* @return proxy the proxy address for the `poolType_`.
*/
function _deploy2(uint8 poolType_, string calldata poolName_) internal returns (address) {
require(bytes(poolName_).length != 0, "F: poolName_ is empty");
bytes32 salt_ = _calculatePoolSalt(_msgSender(), poolName_, poolType_);
function _deploy2(string calldata protocol_, uint8 poolType_) internal returns (address) {
require(bytes(protocol_).length != 0, "F: poolName_ is empty");
bytes32 salt_ = _calculatePoolSalt(_msgSender(), protocol_, poolType_);

address implementation_ = getImplementation(poolType_);
require(implementation_ != address(0), "F: implementation not found");
address beacon_ = getBeacon(poolType_);
require(beacon_ != address(0), "F: beacon not found");

require(!_usedSalts[salt_], "F: salt used");
_usedSalts[salt_] = true;

address proxy_ = address(new ERC1967Proxy{salt: salt_}(implementation_, bytes("")));
address proxy_ = address(new FreezableBeaconProxy{salt: salt_}(beacon_, bytes("")));

deployedProxies[_msgSender()][poolName_][poolType_] = proxy_;
deployedProxies[_msgSender()][protocol_][poolType_] = proxy_;

emit ProxyDeployed(proxy_, implementation_, poolType_, poolName_);
emit ProxyDeployed(proxy_, UpgradeableBeacon(beacon_).implementation(), poolType_, protocol_);

return proxy_;
}

function _predictPoolAddress(
uint8 poolType_,
string calldata poolName_,
address sender_
address deployer_,
string calldata protocol_,
uint8 poolType_
) internal view returns (address) {
bytes32 salt_ = _calculatePoolSalt(sender_, poolName_, uint8(poolType_));
bytes32 salt_ = _calculatePoolSalt(deployer_, protocol_, uint8(poolType_));

bytes32 bytecodeHash_ = keccak256(
abi.encodePacked(type(ERC1967Proxy).creationCode, abi.encode(getImplementation(poolType_), bytes("")))
abi.encodePacked(type(FreezableBeaconProxy).creationCode, abi.encode(getBeacon(poolType_), bytes("")))
);

return Create2.computeAddress(salt_, bytecodeHash_);
}

function _calculatePoolSalt(
address sender_,
string calldata poolName_,
string calldata protocol_,
uint8 poolType_
) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(sender_, poolName_, poolType_));
return keccak256(abi.encodePacked(sender_, protocol_, poolType_));
}

function _authorizeUpgrade(address) internal view override onlyOwner {}
Expand Down
17 changes: 1 addition & 16 deletions contracts/L1/Distribution.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.20;

import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

import {PRECISION} from "@solarity/solidity-lib/utils/Globals.sol";
Expand All @@ -13,11 +12,9 @@ import {IDistribution} from "../interfaces/L1/IDistribution.sol";
import {IFeeConfig} from "../interfaces/L1/IFeeConfig.sol";
import {IL1Sender} from "../interfaces/L1/IL1Sender.sol";

contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable {
contract Distribution is IDistribution, OwnableUpgradeable {
using SafeERC20 for IERC20;

bool public isNotUpgradeable;

address public depositToken;
address public l1Sender;
address public feeConfig;
Expand Down Expand Up @@ -60,7 +57,6 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable {
Pool[] calldata poolsInfo_
) external initializer {
__Ownable_init();
__UUPSUpgradeable_init();

for (uint256 i; i < poolsInfo_.length; ++i) {
createPool(poolsInfo_[i]);
Expand Down Expand Up @@ -358,15 +354,4 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable {

return bridgeMessageId_;
}

/**********************************************************************************************/
/*** UUPS ***/
/**********************************************************************************************/
function removeUpgradeability() external onlyOwner {
isNotUpgradeable = true;
}

function _authorizeUpgrade(address) internal view override onlyOwner {
require(!isNotUpgradeable, "DS: upgrade isn't available");
}
}
6 changes: 1 addition & 5 deletions contracts/L1/FeeConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@
pragma solidity ^0.8.20;

import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

import {PRECISION} from "@solarity/solidity-lib/utils/Globals.sol";

import {IFeeConfig} from "../interfaces/L1/IFeeConfig.sol";

contract FeeConfig is IFeeConfig, OwnableUpgradeable, UUPSUpgradeable {
contract FeeConfig is IFeeConfig, OwnableUpgradeable {
address public treasury;
uint256 public baseFee;

mapping(address => uint256) public fees;

function __FeeConfig_init(address treasury_, uint256 baseFee_) external initializer {
__Ownable_init();
__UUPSUpgradeable_init();

treasury = treasury_;
baseFee = baseFee_;
Expand Down Expand Up @@ -48,6 +46,4 @@ contract FeeConfig is IFeeConfig, OwnableUpgradeable, UUPSUpgradeable {

return (fee_, treasury);
}

function _authorizeUpgrade(address) internal override onlyOwner {}
}
16 changes: 8 additions & 8 deletions contracts/L1/L1Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {IDistribution} from "../interfaces/L1/IDistribution.sol";
import {IL1Factory} from "../interfaces/L1/IL1Factory.sol";
import {IL1Sender} from "../interfaces/L1/IL1Sender.sol";
import {IOwnable} from "../interfaces/IOwnable.sol";
import {IFreezableBeaconProxy} from "../interfaces/proxy/IFreezableBeaconProxy.sol";

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

Expand Down Expand Up @@ -55,8 +56,8 @@ contract L1Factory is IL1Factory, Factory {
}

function deploy(L1Params calldata l1Params_) external whenNotPaused {
address distributionProxy_ = _deploy2(uint8(PoolType.DISTRIBUTION), l1Params_.protocolName);
address l1SenderProxy_ = _deploy2(uint8(PoolType.L1_SENDER), l1Params_.protocolName);
address distributionProxy_ = _deploy2(l1Params_.protocolName, uint8(PoolType.DISTRIBUTION));
address l1SenderProxy_ = _deploy2(l1Params_.protocolName, uint8(PoolType.L1_SENDER));

IDistribution(distributionProxy_).Distribution_init(
depositTokenExternalDeps.token,
Expand All @@ -82,19 +83,18 @@ contract L1Factory is IL1Factory, Factory {
IL1Sender(l1SenderProxy_).L1Sender__init(distributionProxy_, lzConfig_, arbConfig_);

if (l1Params_.isNotUpgradeable) {
IDistribution(distributionProxy_).removeUpgradeability();
IFreezableBeaconProxy(distributionProxy_).freeze();
}

IOwnable(distributionProxy_).transferOwnership(_msgSender());
IOwnable(l1SenderProxy_).transferOwnership(_msgSender());
}

function predictAddresses(
string calldata poolName_,
address sender_
address deployer_,
string calldata protocol_
) external view returns (address distribution_, address l1Sender_) {
distribution_ = _predictPoolAddress(uint8(PoolType.DISTRIBUTION), poolName_, sender_);

l1Sender_ = _predictPoolAddress(uint8(PoolType.L1_SENDER), poolName_, sender_);
distribution_ = _predictPoolAddress(deployer_, protocol_, uint8(PoolType.DISTRIBUTION));
l1Sender_ = _predictPoolAddress(deployer_, protocol_, uint8(PoolType.L1_SENDER));
}
}
6 changes: 1 addition & 5 deletions contracts/L1/L1Sender.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ import {ILayerZeroEndpoint} from "@layerzerolabs/lz-evm-sdk-v1-0.7/contracts/int
import {IGatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol";

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

import {IWStETH} from "../interfaces/tokens/IWStETH.sol";
import {IL1Sender, IERC165} from "../interfaces/L1/IL1Sender.sol";

contract L1Sender is IL1Sender, OwnableUpgradeable, UUPSUpgradeable {
contract L1Sender is IL1Sender, OwnableUpgradeable {
address public unwrappedDepositToken;
address public distribution;

Expand All @@ -34,7 +33,6 @@ contract L1Sender is IL1Sender, OwnableUpgradeable, UUPSUpgradeable {
DepositTokenConfig calldata depositTokenConfig_
) external initializer {
__Ownable_init();
__UUPSUpgradeable_init();

distribution = distribution_;
rewardTokenConfig = rewardTokenConfig_;
Expand Down Expand Up @@ -112,6 +110,4 @@ contract L1Sender is IL1Sender, OwnableUpgradeable, UUPSUpgradeable {
config.adapterParams // adapterParams (see "Advanced Features")
);
}

function _authorizeUpgrade(address) internal view override onlyOwner {}
}
33 changes: 17 additions & 16 deletions contracts/L2/L2Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ contract L2Factory is IL2Factory, Factory {
UniswapExternalDeps public uniswapExternalDeps;
LzExternalDeps public lzExternalDeps;

mapping(address deployer => mapping(string protocol => address)) public mor20;
dovgopoly marked this conversation as resolved.
Show resolved Hide resolved

constructor() {
_disableInitializers();
}
Expand Down Expand Up @@ -41,40 +43,39 @@ contract L2Factory is IL2Factory, Factory {
}

function deploy(L2Params calldata l2Params_) external whenNotPaused {
address l2MessageReceiver = _deploy2(uint8(PoolType.L2_MESSAGE_RECEIVER), l2Params_.protocolName);
address l2TokenReceiver = _deploy2(uint8(PoolType.L2_TOKEN_RECEIVER), l2Params_.protocolName);
address l2MessageReceiver_ = _deploy2(l2Params_.protocolName, uint8(PoolType.L2_MESSAGE_RECEIVER));
address l2TokenReceiver_ = _deploy2(l2Params_.protocolName, uint8(PoolType.L2_TOKEN_RECEIVER));

address mor20 = MOR20Deployer.deployMOR20(
address mor20_ = MOR20Deployer.deployMOR20(
l2Params_.mor20Name,
l2Params_.mor20Symbol,
lzExternalDeps.oftEndpoint,
_msgSender(),
l2MessageReceiver
l2MessageReceiver_
);
deployedProxies[_msgSender()][l2Params_.protocolName][uint8(PoolType.MOR20)] = mor20;
mor20[_msgSender()][l2Params_.protocolName] = mor20_;

IL2MessageReceiver(l2MessageReceiver).L2MessageReceiver__init(
mor20,
IL2MessageReceiver(l2MessageReceiver_).L2MessageReceiver__init(
mor20_,
IL2MessageReceiver.Config(lzExternalDeps.endpoint, l2Params_.l1Sender, lzExternalDeps.senderChainId)
);

IL2TokenReceiver(l2TokenReceiver).L2TokenReceiver__init(
IL2TokenReceiver(l2TokenReceiver_).L2TokenReceiver__init(
uniswapExternalDeps.router,
uniswapExternalDeps.nonfungiblePositionManager,
l2Params_.firstSwapParams_,
IL2TokenReceiver.SwapParams(l2Params_.firstSwapParams_.tokenOut, mor20, l2Params_.secondSwapFee)
IL2TokenReceiver.SwapParams(l2Params_.firstSwapParams_.tokenOut, mor20_, l2Params_.secondSwapFee)
);

IOwnable(l2MessageReceiver).transferOwnership(_msgSender());
IOwnable(l2TokenReceiver).transferOwnership(_msgSender());
IOwnable(l2MessageReceiver_).transferOwnership(_msgSender());
IOwnable(l2TokenReceiver_).transferOwnership(_msgSender());
}

function predictAddresses(
string calldata poolName_,
address sender_
address deployer_,
string calldata protocol_
) external view returns (address l2MessageReceiver_, address l2TokenReceiver_) {
l2MessageReceiver_ = _predictPoolAddress(uint8(PoolType.L2_MESSAGE_RECEIVER), poolName_, sender_);

l2TokenReceiver_ = _predictPoolAddress(uint8(PoolType.L2_TOKEN_RECEIVER), poolName_, sender_);
l2MessageReceiver_ = _predictPoolAddress(deployer_, protocol_, uint8(PoolType.L2_MESSAGE_RECEIVER));
l2TokenReceiver_ = _predictPoolAddress(deployer_, protocol_, uint8(PoolType.L2_TOKEN_RECEIVER));
}
}
Loading
Loading