-
-
Save romeroadrian/a2895a85360276cf4f29d23de3282859 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.13; | |
import "forge-std/Test.sol"; | |
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; | |
import "../src/SafEth/SafEth.sol"; | |
import "../src/SafEth/derivatives/Reth.sol"; | |
import "../src/SafEth/derivatives/SfrxEth.sol"; | |
import "../src/SafEth/derivatives/WstEth.sol"; | |
contract AuditTest is Test { | |
SafEth public safEthImpl; | |
SafEth public safEth; | |
Reth public rethImpl; | |
Reth public reth; | |
SfrxEth public sfrxEthImpl; | |
SfrxEth public sfrxEth; | |
WstEth public wstEthImpl; | |
WstEth public wstEth; | |
address deployer; | |
address user; | |
address attacker; | |
function setUp() public { | |
deployer = makeAddr("deployer"); | |
user = makeAddr("user"); | |
attacker = makeAddr("attacker"); | |
vm.startPrank(deployer); | |
safEthImpl = new SafEth(); | |
safEth = SafEth(payable(new ERC1967Proxy(address(safEthImpl), ""))); | |
safEth.initialize("Asymmetry Finance ETH", "safETH"); | |
rethImpl = new Reth(); | |
reth = Reth(payable(new ERC1967Proxy(address(rethImpl), ""))); | |
reth.initialize(address(safEth)); | |
sfrxEthImpl = new SfrxEth(); | |
sfrxEth = SfrxEth(payable(new ERC1967Proxy(address(sfrxEthImpl), ""))); | |
sfrxEth.initialize(address(safEth)); | |
wstEthImpl = new WstEth(); | |
wstEth = WstEth(payable(new ERC1967Proxy(address(wstEthImpl), ""))); | |
wstEth.initialize(address(safEth)); | |
vm.stopPrank(); | |
} | |
// Run this test forking mainnet at block height 16906254 | |
function test_SafEth_rebalanceToWeights_InefficientImplementation() public { | |
// Setup derivatives | |
vm.prank(deployer); | |
safEth.addDerivative(address(wstEth), 1e18); | |
vm.prank(deployer); | |
safEth.addDerivative(address(reth), 1e18); | |
vm.prank(deployer); | |
safEth.addDerivative(address(sfrxEth), 1e18); | |
// user has 200 ether | |
uint256 initialAmount = 200 ether; | |
vm.deal(user, initialAmount); | |
// user stakes ether | |
vm.prank(user); | |
safEth.stake{value: initialAmount}(); | |
// protocol owner changes weight and rebalances | |
vm.prank(deployer); | |
safEth.adjustWeight(0, 2e18); | |
vm.prank(deployer); | |
safEth.rebalanceToWeights(); | |
// user unstakes | |
uint256 userShares = safEth.balanceOf(user); | |
vm.prank(user); | |
safEth.unstake(userShares); | |
// Balance is 198.902140399883614284 - A bit more than 0.5% is lost | |
uint256 balanceAfter = user.balance; | |
console.log(balanceAfter); | |
} | |
// Run this test forking mainnet at block height 16906254 | |
function test_Reth_deposit_MissingConditionInCanDeposit() public { | |
// Setup derivative | |
vm.prank(deployer); | |
safEth.addDerivative(address(reth), 1e18); | |
uint256 depositValue = 1 ether; | |
RocketStorageInterface rocketStorage = RocketStorageInterface(reth.ROCKET_STORAGE_ADDRESS()); | |
address dao = rocketStorage.getAddress(keccak256(abi.encodePacked("contract.address", "rocketDAOProtocolProposals"))); | |
address daoSettings = rocketStorage.getAddress(keccak256(abi.encodePacked("contract.address", "rocketDAOProtocolSettingsDeposit"))); | |
uint256 currentMaximumDeposit = RocketDAOProtocolSettingsDepositInterface(daoSettings).getMaximumDepositPoolSize(); | |
// Ensure there's room to deposit | |
vm.prank(dao); | |
(bool success, ) = daoSettings.call(abi.encodeWithSignature("setSettingUint(string,uint256)", "deposit.pool.maximum", currentMaximumDeposit + depositValue)); | |
require(success); | |
// DAO disables deposits | |
vm.prank(dao); | |
(success, ) = daoSettings.call(abi.encodeWithSignature("setSettingBool(string,bool)", "deposit.enabled", false)); | |
require(success); | |
// Deal balance to user | |
vm.deal(user, depositValue); | |
// user tries to stake ether, transaction is reverted | |
vm.prank(user); | |
vm.expectRevert("Deposits into Rocket Pool are currently disabled"); | |
safEth.stake{value: depositValue}(); | |
} | |
// Run this test forking mainnet at block height 15000000 | |
function test_WstEth_withdraw_AssumesPegToEth() public { | |
// Setup derivative | |
vm.prank(deployer); | |
safEth.addDerivative(address(wstEth), 1e18); | |
// Deal balance to user | |
uint256 depositValue = 1 ether; | |
vm.deal(user, depositValue); | |
// user stakes ether | |
vm.prank(user); | |
safEth.stake{value: depositValue}(); | |
// user tries to unstake, action will fail due to stETH being prices at around 0.93-0.95 ETH | |
uint256 userShares = safEth.balanceOf(user); | |
vm.prank(user); | |
vm.expectRevert("Exchange resulted in fewer coins than expected"); | |
safEth.unstake(userShares); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment