Skip to content

Commit

Permalink
Merge branch 'dev' into dev-governance-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
GalloDaSballo committed Oct 15, 2024
2 parents 12f94ed + 1952cc5 commit 0b1ab3a
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/Governance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ contract Governance is Multicall, UserProxyFactory, ReentrancyGuard, IGovernance
// check if user has enough unallocated lqty
require(_lqtyAmount <= lqtyStaked - userState.allocatedLQTY, "Governance: insufficient-unallocated-lqty");

(uint256 accruedLUSD, uint256 accruedETH) = userProxy.unstake(_lqtyAmount, msg.sender, msg.sender);
(uint256 accruedLUSD, uint256 accruedETH) = userProxy.unstake(_lqtyAmount, msg.sender);

emit WithdrawLQTY(msg.sender, _lqtyAmount, accruedLUSD, accruedETH);
}
Expand All @@ -201,7 +201,7 @@ contract Governance is Multicall, UserProxyFactory, ReentrancyGuard, IGovernance
function claimFromStakingV1(address _rewardRecipient) external returns (uint256 accruedLUSD, uint256 accruedETH) {
address payable userProxyAddress = payable(deriveUserProxyAddress(msg.sender));
require(userProxyAddress.code.length != 0, "Governance: user-proxy-not-deployed");
return UserProxy(userProxyAddress).unstake(0, _rewardRecipient, _rewardRecipient);
return UserProxy(userProxyAddress).unstake(0, _rewardRecipient);
}

/*//////////////////////////////////////////////////////////////
Expand Down
10 changes: 5 additions & 5 deletions src/UserProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,24 @@ contract UserProxy is IUserProxy {
}

/// @inheritdoc IUserProxy
function unstake(uint256 _amount, address _lqtyRecipient, address _lusdEthRecipient)
function unstake(uint256 _amount, address _recipient)
public
onlyStakingV2
returns (uint256 lusdAmount, uint256 ethAmount)
{
stakingV1.unstake(_amount);

uint256 lqtyAmount = lqty.balanceOf(address(this));
if (lqtyAmount > 0) lqty.safeTransfer(_lqtyRecipient, lqtyAmount);
if (lqtyAmount > 0) lqty.safeTransfer(_recipient, lqtyAmount);
lusdAmount = lusd.balanceOf(address(this));
if (lusdAmount > 0) lusd.safeTransfer(_lusdEthRecipient, lusdAmount);
if (lusdAmount > 0) lusd.safeTransfer(_recipient, lusdAmount);
ethAmount = address(this).balance;
if (ethAmount > 0) {
(bool success,) = payable(_lusdEthRecipient).call{value: ethAmount}("");
(bool success,) = payable(_recipient).call{value: ethAmount}("");
require(success, "UserProxy: eth-fail");
}

emit Unstake(_amount, _lqtyRecipient, _lusdEthRecipient, lusdAmount, ethAmount);
emit Unstake(_amount, _recipient, lusdAmount, ethAmount);
}

/// @inheritdoc IUserProxy
Expand Down
7 changes: 3 additions & 4 deletions src/interfaces/IUserProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {PermitParams} from "../utils/Types.sol";
interface IUserProxy {
event Stake(uint256 amount, address lqtyFrom);
event Unstake(
uint256 lqtyUnstaked, address lqtyRecipient, address lusdEthRecipient, uint256 lusdAmount, uint256 ethAmount
uint256 lqtyUnstaked, address indexed lqtyRecipient, uint256 lusdAmount, uint256 ethAmount
);

/// @notice Address of the LQTY token
Expand Down Expand Up @@ -38,11 +38,10 @@ interface IUserProxy {
function stakeViaPermit(uint256 _amount, address _lqtyFrom, PermitParams calldata _permitParams) external;
/// @notice Unstakes a given amount of LQTY tokens from the V1 staking contract and claims the accrued rewards
/// @param _amount Amount of LQTY tokens to unstake
/// @param _lqtyRecipient Address to which the unstaked LQTY tokens should be sent
/// @param _lusdEthRecipient Address to which the unstaked LUSD and ETH rewards should be sent
/// @param _recipient Address to which the tokens should be sent
/// @return lusdAmount Amount of LUSD tokens claimed
/// @return ethAmount Amount of ETH claimed
function unstake(uint256 _amount, address _lqtyRecipient, address _lusdEthRecipient)
function unstake(uint256 _amount, address _recipient)
external
returns (uint256 lusdAmount, uint256 ethAmount);
/// @notice Returns the current amount LQTY staked by a user in the V1 staking contract
Expand Down
52 changes: 52 additions & 0 deletions test/SafeCallWithMinGas.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import {Test} from "forge-std/Test.sol";

import {safeCallWithMinGas} from "src/utils/SafeCallMinGas.sol";

contract BasicRecipient {
bool public callWasValid;

function validCall() external {
callWasValid = true;
}
}
contract FallbackRecipient {
bytes public received;

fallback() external payable {
received = msg.data;
}
}

contract SafeCallWithMinGasTests is Test {

function test_basic_nonExistent(uint256 gas, uint256 value, bytes memory theData) public {
vm.assume(gas < 30_000_000);
// Call to non existent succeeds
address nonExistent = address(0x123123123);
assert(nonExistent.code.length == 0);

safeCallWithMinGas(address(0x123123123), gas, value, theData);
}

function test_basic_contractData(uint256 gas, uint256 value, bytes memory theData) public {
vm.assume(gas < 30_000_000);
vm.assume(gas > 50_000 + theData.length * 2_100); /// @audit Approximation
FallbackRecipient recipient = new FallbackRecipient();
// Call to non existent succeeds

vm.deal(address(this), value);

safeCallWithMinGas(address(recipient), gas, value, theData);
assertEq(keccak256(recipient.received()), keccak256(theData), "same data");
}
function test_basic_contractCall() public {
BasicRecipient recipient = new BasicRecipient();
// Call to non existent succeeds

safeCallWithMinGas(address(recipient), 35_000, 0, abi.encodeCall(BasicRecipient.validCall, ()));
assertEq(recipient.callWasValid(), true, "Call success");
}
}
4 changes: 2 additions & 2 deletions test/UserProxy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ contract UserProxyTest is Test {

userProxy.stake(1e18, user);

(uint256 lusdAmount, uint256 ethAmount) = userProxy.unstake(0, user, user);
(uint256 lusdAmount, uint256 ethAmount) = userProxy.unstake(0, user);
assertEq(lusdAmount, 0);
assertEq(ethAmount, 0);

Expand All @@ -123,7 +123,7 @@ contract UserProxyTest is Test {
uint256 lusdBalance = uint256(vm.load(stakingV1, bytes32(uint256(4))));
vm.store(stakingV1, bytes32(uint256(4)), bytes32(abi.encodePacked(lusdBalance + 1e18)));

(lusdAmount, ethAmount) = userProxy.unstake(1e18, user, user);
(lusdAmount, ethAmount) = userProxy.unstake(1e18, user);
assertEq(lusdAmount, 1e18);
assertEq(ethAmount, 1e18);

Expand Down

0 comments on commit 0b1ab3a

Please sign in to comment.