Skip to content
Open
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
58 changes: 58 additions & 0 deletions deploy/ethereum/002_deployRenzoIntegration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import * as WrappedTokenArtifact from "../../artifacts/src/WrappedToken.sol/WrappedToken.json";

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts } = hre;
const { deploy, execute, get, getOrNull, log, read, save } = deployments;
const { deployer } = await getNamedAccounts();

const EdgelessDeposit = await getOrNull("EdgelessDeposit");
if (!EdgelessDeposit) {
await deploy("RenzoStrategy", {
from: deployer,
log: true,
proxy: {
execute: {
init: {
methodName: "initialize",
args: [deployer, (await get("StakingManager")).address],
},
},
proxyContract: "OpenZeppelinTransparentProxy",
},
});

await execute(
"StakingManager",
{ from: deployer, log: true },
"addStrategy",
await read("StakingManager", "ETH_ADDRESS"),
(await get("RenzoStrategy")).address,
);

await execute(
"StakingManager",
{ from: deployer, log: true },
"setActiveStrategy",
await read("StakingManager", "ETH_ADDRESS"),
1,
);
} else {
log("EdgelessDeposit already deployed, skipping...");
}
await hre.run("etherscan-verify", {
apiKey: process.env.ETHERSCAN_API_KEY,
});

await hre.run("verify:verify", {
address: (await get("Edgeless Wrapped ETH")).address,
constructorArguments: [
(await get("EdgelessDeposit")).address,
await read("Edgeless Wrapped ETH", "name"),
await read("Edgeless Wrapped ETH", "symbol"),
],
});
};
export default func;
func.skip = async () => true;
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ auto_detect_solc = false
block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
bytecode_hash = "none"
evm_version = "paris" # See https://www.evmdiff.com/features?name=PUSH0&kind=opcode
fuzz = { runs = 50 }
fuzz = { runs = 1 }
gas_reports = ["*"]
optimizer = true
optimizer_runs = 10_000
Expand Down
89 changes: 89 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@nomicfoundation/hardhat-verify": "^2.0.3",
"@openzeppelin/contracts": "^5.0.1",
"@openzeppelin/contracts-upgradeable": "^5.0.1",
"@uniswap/v3-periphery": "^1.4.4",
"cloc": "^1.98.0-cloc",
"dotenv": "^16.3.1",
"openzeppelin-foundry-upgrades": "github:OpenZeppelin/openzeppelin-foundry-upgrades"
Expand Down
27 changes: 25 additions & 2 deletions src/EdgelessDeposit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import { WrappedToken } from "./WrappedToken.sol";
contract EdgelessDeposit is Ownable2StepUpgradeable, UUPSUpgradeable {
WrappedToken public wrappedEth;
StakingManager public stakingManager;
uint256[50] private __gap;
IERC20 public ezETH;
uint256[49] private __gap;

event DepositEth(address indexed to, address indexed from, uint256 EthAmount, uint256 mintAmount);
event MintWrappedEth(address indexed to, uint256 amount);
event ReceivedStakingManagerWithdrawal(uint256 amount);
event WithdrawEth(address indexed from, address indexed to, uint256 EthAmountWithdrew, uint256 burnAmount);
event WithdrawEzEth(address indexed from, address indexed to, uint256 EzEthAmountWithdrew, uint256 burnAmount);

error MaxMintExceeded();
error TransferFailed(bytes data);
Expand Down Expand Up @@ -58,6 +60,13 @@ contract EdgelessDeposit is Ownable2StepUpgradeable, UUPSUpgradeable {
emit DepositEth(to, msg.sender, msg.value, amount);
}

function depositEzEth(address to, uint256 amount) external {
wrappedEth.mint(to, amount);
ezETH.transferFrom(msg.sender, address(stakingManager), amount);
stakingManager.stakeEzEth(amount);
emit DepositEth(to, msg.sender, amount, amount);
}

/**
* @notice Withdraw Eth from the Eth pool
* @param to Address to withdraw Eth to
Expand All @@ -72,6 +81,18 @@ contract EdgelessDeposit is Ownable2StepUpgradeable, UUPSUpgradeable {
emit WithdrawEth(msg.sender, to, amount, amount);
}

/**
* @notice Withdraw Eth from the Eth pool
* @param to Address to withdraw Eth to
* @param amount Amount to withdraw
*/
function withdrawEzEth(address to, uint256 amount) external {
wrappedEth.burn(msg.sender, amount);
uint256 withdrawnAmount = stakingManager.withdrawEzEth(amount);
ezETH.transfer(to, withdrawnAmount);
emit WithdrawEzEth(msg.sender, to, withdrawnAmount, amount);
}

/// ---------------------------------- 🔓 Admin Functions 🔓 ----------------------------------
/**
* @notice Mint wrapped tokens based on the amount of Eth staked
Expand All @@ -86,7 +107,9 @@ contract EdgelessDeposit is Ownable2StepUpgradeable, UUPSUpgradeable {
emit MintWrappedEth(to, amount);
}

function upgrade() external onlyOwner { }
function upgrade() external onlyOwner {
ezETH = IERC20(0xbf5495Efe5DB9ce00f80364C8B423567e58d2110);
}

/// -------------------------------- 🏗️ Internal Functions 🏗️ --------------------------------
/**
Expand Down
30 changes: 29 additions & 1 deletion src/StakingManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ contract StakingManager is Ownable2StepUpgradeable, UUPSUpgradeable {
mapping(IStakingStrategy => bool) public isActiveStrategy;
address public staker;
address public constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
uint256[50] private __gap;
IERC20 public ezETH;
uint256[49] private __gap;

event Stake(address indexed asset, uint256 amount);
event StakeEzEth(uint256 amount);
event Withdraw(address indexed asset, uint256 amount);
event WithdrawEzEth(address indexed asset, uint256 amount);
event SetStaker(address staker);
event AddStrategy(address indexed asset, IStakingStrategy indexed strategy);
event SetActiveStrategy(address indexed asset, uint256 index);
Expand Down Expand Up @@ -57,6 +60,16 @@ contract StakingManager is Ownable2StepUpgradeable, UUPSUpgradeable {
strategy.deposit{ value: amount }(amount);
}

function stakeEzEth(uint256 amount) external payable onlyStaker {
_stakeEzEth(amount);
emit StakeEzEth(amount);
}

function _stakeEzEth(uint256 amount) internal {
IStakingStrategy strategy = getActiveStrategy(ETH_ADDRESS);
ezETH.transfer(address(strategy), amount);
}

function withdraw(uint256 amount) external onlyStaker returns (uint256) {
return _withdrawEth(amount);
}
Expand All @@ -73,12 +86,27 @@ contract StakingManager is Ownable2StepUpgradeable, UUPSUpgradeable {
emit Withdraw(ETH_ADDRESS, withdrawnAmount);
}

function withdrawEzEth(uint256 amount) external onlyStaker returns (uint256) {
return _withdrawEzEth(amount);
}

function _withdrawEzEth(uint256 amount) internal returns (uint256 withdrawnAmount) {
IStakingStrategy strategy = getActiveStrategy(address(ezETH));
strategy.withdraw(amount);
ezETH.transfer(staker, amount);
emit WithdrawEzEth(ETH_ADDRESS, withdrawnAmount);
}

/// ---------------------------------- 🔓 Admin Functions 🔓 ----------------------------------
function setStaker(address _staker) external onlyOwner {
staker = _staker;
emit SetStaker(_staker);
}

function setEzETH(address _ezETH) external onlyOwner {
ezETH = IERC20(_ezETH);
}

function addStrategy(address asset, IStakingStrategy strategy) external onlyOwner {
require(ETH_ADDRESS == asset, "Unsupported asset");
require(!isActiveStrategy[strategy], "Strategy already exists");
Expand Down
3 changes: 3 additions & 0 deletions src/interfaces/IRenzo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
interface IRenzo {
function depositETH() external payable;
}
6 changes: 6 additions & 0 deletions src/interfaces/IWETH.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";

interface IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint256 wad) external;
}
Loading