Skip to content

Commit f63b3d3

Browse files
authored
Merge pull request #260 from manifoldfinance/controlc/final_review_fixes
2 parents 2638ca4 + cdb2b0e commit f63b3d3

29 files changed

+68
-1654
lines changed

.gitmodules

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
path = lib/solmate
66
url = https://github.com/transmissions11/solmate
77
branch = "main"
8-
[submodule "lib/pigeon"]
9-
path = lib/pigeon
10-
url = https://github.com/manifoldfinance/pigeon
11-
branch = "OFTV2"
128
[submodule "lib/safe-tools"]
139
path = lib/safe-tools
1410
url = https://github.com/0xKitsune/safe-tools
@@ -18,6 +14,3 @@
1814
[submodule "lib/properties"]
1915
path = lib/properties
2016
url = https://github.com/crytic/properties
21-
[submodule "lib/mev-proxy"]
22-
path = lib/mev-proxy
23-
url = https://github.com/manifoldfinance/mev-proxy

lib/mev-proxy

Lines changed: 0 additions & 1 deletion
This file was deleted.

lib/pigeon

Lines changed: 0 additions & 1 deletion
This file was deleted.

lz-oft-deployment-config-example.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

remappings.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
ds-test/=lib/forge-std/lib/ds-test/src/
22
forge-std/=lib/forge-std/src/
33
solmate/=lib/solmate/src/
4-
pigeon/=lib/pigeon/src/
5-
solady/=lib/pigeon/lib/solady/src/
64
@openzeppelin/=lib/openzeppelin-contracts/
75
safe-contracts/=lib/safe-tools/lib/safe-contracts/contracts/
86
safe-tools/=lib/safe-tools/src/
97
properties/=lib/properties/contracts/
10-
mev-proxy/=lib/mev-proxy/src/

script/Deploy.s.sol

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { WagyuStaker } from "src/WagyuStaker.sol";
88
import { AuthManager } from "src/libraries/AuthManager.sol";
99
import { MevEthShareVault } from "src/MevEthShareVault.sol";
1010
import { IStakingModule } from "src/interfaces/IStakingModule.sol";
11-
import { TransparentUpgradeableProxy } from "mev-proxy/TransparentUpgradeableProxy.sol";
1211

1312
contract DeployScript is Script {
1413
error UnknownChain();
@@ -19,7 +18,6 @@ contract DeployScript is Script {
1918
uint256 chainId;
2019
address beaconDepositContract;
2120
address weth;
22-
address layerZeroEndpoint;
2321
address safe = vm.envAddress("MULTISIG_SAFE");
2422
assembly {
2523
chainId := chainid()
@@ -28,23 +26,21 @@ contract DeployScript is Script {
2826
// Eth mainnet
2927
beaconDepositContract = 0x00000000219ab540356cBB839Cbe05303d7705Fa;
3028
weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
31-
layerZeroEndpoint = 0x66A71Dcef29A0fFBDBE3c6a460a3B5BC225Cd675;
3229
} else if (chainId == 5) {
3330
// Goerli
3431
beaconDepositContract = 0xff50ed3d0ec03aC01D4C79aAd74928BFF48a7b2b;
3532
weth = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6;
36-
layerZeroEndpoint = 0xbfD2135BFfbb0B5378b56643c2Df8a87552Bfa23;
3733
} else {
3834
revert UnknownChain();
3935
}
4036

4137
vm.startBroadcast();
4238
// deploy mevETH
43-
MevEth mevEth = new MevEth(authority, weth, layerZeroEndpoint);
39+
MevEth mevEth = new MevEth(authority, weth);
4440

4541
// deploy sharevault
4642
// MevEthShareVault initialShareVault = new MevEthShareVault(authority, address(mevEth), authority);
47-
address initialShareVault = address(new TransparentUpgradeableProxy(safe, authority, ""));
43+
address initialShareVault = safe;
4844
// deploy staking module
4945
IStakingModule initialStakingModule = new WagyuStaker(authority, beaconDepositContract, address(mevEth));
5046
// initialise mevETH

script/DeployOFT.s.sol

Lines changed: 0 additions & 67 deletions
This file was deleted.

script/WireUpOFT.s.sol

Lines changed: 0 additions & 27 deletions
This file was deleted.

slither.config.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
"ds-test/=lib/ds-test/src/",
1212
"forge-std/=lib/forge-std/src/",
1313
"solmate/=lib/solmate/src/",
14-
"pigeon/=lib/pigeon/src/",
15-
"solady/=lib/pigeon/lib/solady/src/",
1614
"@openzeppelin/=lib/openzeppelin-contracts/",
1715
"safe-contracts/=lib/safe-tools/lib/safe-contracts/contracts/",
1816
"safe-tools/=lib/safe-tools/src/",

src/MevEth.sol

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
11
/// SPDX-License-Identifier: SSPL-1.-0
22

3-
/**
4-
* @custom:org.protocol='mevETH LST Protocol'
5-
* @custom:org.security='mailto:security@manifoldfinance.com'
6-
* @custom:org.vcs-commit=$GIT_COMMIT_SHA
7-
* @custom:org.vendor='CommodityStream, Inc'
8-
* @custom:org.schema-version="1.0"
9-
* @custom.org.encryption="manifoldfinance.com/.well-known/pgp-key.asc"
10-
* @custom:org.preferred-languages="en"
11-
*/
12-
133
pragma solidity ^0.8.19;
144

15-
/*///////////// Manifold Mev Ether /////////////
5+
/*///////////// Mev Protocol ///////////////////////
166
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣷⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀
177
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣷⣤⣀⠀⠀⠀⠀⠀⠉⠑⣶⣤⣄⣀⣠⣤⣶⣶⣿⣿⣿⣿⡇⠀⠀⠀
18-
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⡿⠟⠋⠁⠀⠀⠀⣀⠤⠒⠉⠈⢉⡉⠻⢿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀
198
⠀⠀⠀⠀⣀⣴⣶⣿⣷⡄⠀⠀⠀⠀⢹⣿⣿⣿⣿⠏⠁⠀⢀⠄⠀⠀⠈⢀⠄⠀⢀⡖⠁⠀⢀⠀⠈⠻⣿⣿⣿⣿⡏⠀⠀⠀⠀
209
⠀⠀⢠⣾⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⢸⣿⣿⠏⠀⠀⢀⡴⠁⠀⠀⣠⠖⠁⢀⠞⠋⠀⢠⡇⢸⡄⠀⠀⠈⢻⣿⣿⠁⠀⠀⠀⠀
2110
⠀⣠⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⢸⡿⠁⠀⠀⢀⡞⠀⠀⢀⡴⠃⠀⣰⠋⠀⠀⣰⡿⠀⡜⢳⡀⠘⣦⠀⢿⡇⠀⠀⠀⠀⠀
@@ -36,25 +25,24 @@ pragma solidity ^0.8.19;
3625
⠀⠀⠀⠀⠀⠀⠀⠇⠀⠣⠀⡗⢣⡀⠘⢄⠀⢧⠀⢳⡟⠛⠙⣧⣧⣠⣄⣀⣠⢿⣶⠁⠀⠸⡀⠀⠓⠚⢴⣋⣠⠔⠀⠀⠀⠀⠁
3726
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠧⡤⠙⢤⡈⣦⡼⠀⠀⠧⢶⠚⡇⠈⠁⠈⠃⠀⡰⢿⣄⠀⠀⠑⢤⣀⠀⠀⠀⠈⠁⠀⠀⠀⠀⠀
3827
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
39-
/////////////////////////////////////////////*/
28+
///////////////////////////////////////////////////*/
4029

30+
import { Auth } from "./libraries/Auth.sol";
4131
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
4232
import { FixedPointMathLib } from "solmate/utils/FixedPointMathLib.sol";
33+
import { ERC20 } from "solmate/tokens/ERC20.sol";
4334
import { IERC4626 } from "./interfaces/IERC4626.sol";
4435
import { WETH } from "solmate/tokens/WETH.sol";
4536
import { MevEthErrors } from "./interfaces/Errors.sol";
4637
import { IStakingModule } from "./interfaces/IStakingModule.sol";
47-
import { IMevEthShareVault } from "./interfaces/IMevEthShareVault.sol";
4838
import { IERC20Burnable } from "./interfaces/IERC20Burnable.sol";
4939
import { ITinyMevEth } from "./interfaces/ITinyMevEth.sol";
50-
import { WagyuStaker } from "./WagyuStaker.sol";
51-
import { OFTWithFee } from "./layerZero/oft/OFTWithFee.sol";
5240

5341
/// @title MevEth
54-
/// @author Manifold Finance
42+
/// @author CommodityStream, Inc.
5543
/// @dev Contract that allows deposit of ETH, for a Liquid Staking Receipt (LSR) in return.
5644
/// @dev LSR is represented through an ERC4626 token and interface.
57-
contract MevEth is OFTWithFee, IERC4626, ITinyMevEth {
45+
contract MevEth is Auth, ERC20, IERC4626, ITinyMevEth {
5846
using SafeTransferLib for WETH;
5947
using FixedPointMathLib for uint256;
6048

@@ -77,7 +65,9 @@ contract MevEth is OFTWithFee, IERC4626, ITinyMevEth {
7765
/// @notice Max amount of ETH that can be deposited.
7866
uint128 internal constant MAX_DEPOSIT = type(uint128).max;
7967
/// @notice Min amount of ETH that can be deposited.
80-
uint128 public constant MIN_DEPOSIT = 0.01 ether; // 0.01 eth
68+
uint128 public constant MIN_DEPOSIT = 0.01 ether;
69+
/// @notice Min amount of ETH that can be withdrawn via the queue.
70+
uint128 public MIN_WITHDRAWAL;
8171
/// @notice The address of the MevEthShareVault.
8272
address public mevEthShareVault;
8373
/// @notice The address of the pending MevEthShareVault when a new vault has been committed but not finalized.
@@ -117,15 +107,9 @@ contract MevEth is OFTWithFee, IERC4626, ITinyMevEth {
117107
/// @dev Pending staking module and committed timestamp will both be zero on deployment.
118108
/// @param authority Address of the controlling admin authority.
119109
/// @param weth Address of the WETH contract to use for deposits.
120-
/// @param layerZeroEndpoint Chain specific endpoint for LayerZero.
121-
constructor(
122-
address authority,
123-
address weth,
124-
address layerZeroEndpoint
125-
)
126-
OFTWithFee("Mev Liquid Staked Ether", "mevETH", 18, 8, authority, layerZeroEndpoint)
127-
{
110+
constructor(address authority, address weth) Auth(authority) ERC20("Mev Liquid Staking Receipt", "mevETH", 18) {
128111
WETH9 = WETH(payable(weth));
112+
MIN_WITHDRAWAL = MIN_DEPOSIT;
129113
}
130114

131115
/// @notice Calculate the needed Ether buffer required when creating a new validator.
@@ -194,19 +178,26 @@ contract MevEth is OFTWithFee, IERC4626, ITinyMevEth {
194178
emit StakingUnpaused();
195179
}
196180

197-
/// @notice Event emitted when a new staking module is committed. The MODULE_UPDATE_TIME_DELAY must elapse before the staking module update can be
198-
/// finalized.
181+
/// @notice Event emitted when a new staking module is committed.
182+
/// The MODULE_UPDATE_TIME_DELAY must elapse before the staking module update can be finalized.
199183
event StakingModuleUpdateCommitted(address indexed oldModule, address indexed pendingModule, uint64 indexed eligibleForFinalization);
184+
200185
/// @notice Event emitted when a new staking module is finalized.
201186
event StakingModuleUpdateFinalized(address indexed oldModule, address indexed newModule);
187+
202188
/// @notice Event emitted when a new pending module update is canceled.
203189
event StakingModuleUpdateCanceled(address indexed oldModule, address indexed pendingModule);
204190

205-
/// @notice Starts the process to update the staking module. To finalize the update, the MODULE_UPDATE_TIME_DELAY must elapse and the
206-
/// finalizeUpdateStakingModule function must be called.
191+
/// @notice Starts the process to update the staking module.
192+
/// To finalize the update, the MODULE_UPDATE_TIME_DELAY must elapse
193+
/// and thefinalizeUpdateStakingModule function must be called.
207194
/// @param newModule The new staking module.
208195
/// @dev This function is only callable by addresses with the admin role.
209196
function commitUpdateStakingModule(IStakingModule newModule) external onlyAdmin {
197+
if (address(newModule) == address(0)) {
198+
revert MevEthErrors.InvalidPendingStakingModule();
199+
}
200+
210201
pendingStakingModule = newModule;
211202
pendingStakingModuleCommittedTimestamp = uint64(block.timestamp);
212203
emit StakingModuleUpdateCommitted(address(stakingModule), address(newModule), uint64(block.timestamp + MODULE_UPDATE_TIME_DELAY));
@@ -352,6 +343,7 @@ contract MevEth is OFTWithFee, IERC4626, ITinyMevEth {
352343
/// @notice Grants rewards updating the fraction.elastic.
353344
/// @dev called from validator rewards updates
354345
function grantRewards() external payable {
346+
if (!(msg.sender == address(stakingModule) || msg.sender == mevEthShareVault)) revert MevEthErrors.UnAuthorizedCaller();
355347
if (msg.value == 0) revert MevEthErrors.ZeroValue();
356348

357349
fraction.elastic += uint128(msg.value);
@@ -444,6 +436,10 @@ contract MevEth is OFTWithFee, IERC4626, ITinyMevEth {
444436
withdrawalAmountQueued += delta;
445437
}
446438

439+
function setMinWithdrawal(uint128 newMinimum) public onlyAdmin {
440+
MIN_WITHDRAWAL = newMinimum;
441+
}
442+
447443
/*//////////////////////////////////////////////////////////////
448444
ERC4626 Support
449445
//////////////////////////////////////////////////////////////*/
@@ -604,7 +600,7 @@ contract MevEth is OFTWithFee, IERC4626, ITinyMevEth {
604600
/// @param shares shares that will be burned
605601
function _withdraw(bool useQueue, address receiver, address owner, uint256 assets, uint256 shares) internal {
606602
// If withdraw is less than the minimum deposit / withdraw amount, revert
607-
if (assets < MIN_DEPOSIT) revert MevEthErrors.WithdrawTooSmall();
603+
if (assets < MIN_WITHDRAWAL) revert MevEthErrors.WithdrawTooSmall();
608604
// Sandwich protection
609605
uint256 blockNumber = block.number;
610606

@@ -622,26 +618,28 @@ contract MevEth is OFTWithFee, IERC4626, ITinyMevEth {
622618
_burn(owner, shares);
623619

624620
uint256 availableBalance = address(this).balance - withdrawalAmountQueued; // available balance will be adjusted
625-
621+
uint256 amountToSend = assets;
626622
if (availableBalance < assets) {
627623
if (!useQueue) revert MevEthErrors.NotEnoughEth();
628-
uint128 amountOwed = uint128(assets - availableBalance);
624+
// Available balance is sent, and the remainder must be withdrawn via the queue
625+
uint256 amountOwed = assets - availableBalance;
629626
++queueLength;
630627
withdrawalQueue[queueLength] = WithdrawalTicket({
631628
claimed: false,
632629
receiver: receiver,
633-
amount: amountOwed,
634-
accumulatedAmount: withdrawalQueue[queueLength - 1].accumulatedAmount + amountOwed
630+
amount: uint128(amountOwed),
631+
accumulatedAmount: withdrawalQueue[queueLength - 1].accumulatedAmount + uint128(amountOwed)
635632
});
636-
emit WithdrawalQueueOpened(receiver, queueLength, uint256(amountOwed));
637-
assets = availableBalance;
638-
shares = shares - convertToShares(amountOwed);
633+
emit WithdrawalQueueOpened(receiver, queueLength, amountOwed);
634+
amountToSend = availableBalance;
639635
}
640-
if (assets != 0) {
636+
if (amountToSend != 0) {
637+
// As with ERC4626, we log assets and shares as if there is no queue, and everything has been withdrawn
638+
// as this most closely resembles what is happened
641639
emit Withdraw(msg.sender, owner, receiver, assets, shares);
642640

643-
WETH9.deposit{ value: assets }();
644-
WETH9.safeTransfer(receiver, assets);
641+
WETH9.deposit{ value: amountToSend }();
642+
WETH9.safeTransfer(receiver, amountToSend);
645643
}
646644
}
647645

0 commit comments

Comments
 (0)