Skip to content

Instantly share code, notes, and snippets.

@romeroadrian
Created March 30, 2023 00:35
Show Gist options
  • Save romeroadrian/a2895a85360276cf4f29d23de3282859 to your computer and use it in GitHub Desktop.
Save romeroadrian/a2895a85360276cf4f29d23de3282859 to your computer and use it in GitHub Desktop.
// 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