Skip to content

Commit

Permalink
psm audit fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ricklista committed Nov 13, 2024
1 parent 15b0fd4 commit fd1cf25
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 44 deletions.
15 changes: 10 additions & 5 deletions contracts/psm/LisUSDPoolSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ contract LisUSDPoolSet is AccessControlUpgradeable, ReentrancyGuardUpgradeable,
event SetWithdrawDelay(uint256 withdrawDelay);
event SetEarnPool(address earnPool);
event SetDistributor(address pool, address distributor);
event RemoveDistributor(address pool);
event RemoveDistributor(address pool, address distributor);
event SetMaxAmount(uint256 maxAmount);

/// @custom:oz-upgrades-unsafe-allow constructor
Expand Down Expand Up @@ -91,10 +91,12 @@ contract LisUSDPoolSet is AccessControlUpgradeable, ReentrancyGuardUpgradeable,
require(_manager != address(0), "manager cannot be zero address");
require(_pauser != address(0), "pauser cannot be zero address");
require(_lisUSD != address(0), "lisUSD cannot be zero address");
require(_maxDuty > RATE_SCALE, "maxDuty cannot be zero");

__AccessControl_init();
__ReentrancyGuard_init();
__UUPSUpgradeable_init();
__Pausable_init();

_setupRole(DEFAULT_ADMIN_ROLE, _admin);
_setupRole(MANAGER, _manager);
Expand Down Expand Up @@ -138,12 +140,14 @@ contract LisUSDPoolSet is AccessControlUpgradeable, ReentrancyGuardUpgradeable,
address account = msg.sender;
uint256 share = balanceOf[account];
uint256 amount = convertToAssets(share);
require(amount > 0, "amount cannot be zero");
_withdraw(account, _pools, share, amount);
}

function _withdraw(address account, address[] memory _pools, uint256 share, uint256 amount) private {
require(share <= balanceOf[account], "insufficient balance");
require(block.timestamp >= withdrawDelay + lastDepositTime[account], "withdraw delay not reached");
require(IERC20(lisUSD).balanceOf(address(this)) >= amount, "not enough balance");

// update shares
balanceOf[account] -= share;
Expand Down Expand Up @@ -175,7 +179,6 @@ contract LisUSDPoolSet is AccessControlUpgradeable, ReentrancyGuardUpgradeable,
);

// transfer lisUSD to account
require(IERC20(lisUSD).balanceOf(address(this)) >= amount, "not enough balance");
IERC20(lisUSD).safeTransfer(account, amount);

emit Transfer(account, address(0), share);
Expand Down Expand Up @@ -361,9 +364,10 @@ contract LisUSDPoolSet is AccessControlUpgradeable, ReentrancyGuardUpgradeable,
* @param pool pool address
*/
function removeDistributor(address pool) external onlyRole(MANAGER) {
address distributor = pools[pool].distributor;
pools[pool].distributor = address(0);

emit RemoveDistributor(pool);
emit RemoveDistributor(pool, distributor);
}

/**
Expand Down Expand Up @@ -395,8 +399,9 @@ contract LisUSDPoolSet is AccessControlUpgradeable, ReentrancyGuardUpgradeable,
pools[pool].active = false;

emit RemovePool(pool);
if (pools[pool].distributor != address(0)) {
emit RemoveDistributor(pool);
address distributor = pools[pool].distributor;
if (distributor != address(0)) {
emit RemoveDistributor(pool, distributor);
}
}

Expand Down
12 changes: 12 additions & 0 deletions contracts/psm/PSM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ contract PSM is AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable {
*/
function setVaultManager(address _vaultManager) external onlyRole(MANAGER) {
require(_vaultManager != address(0), "VaultManager cannot be zero address");
require(_vaultManager != vaultManager, "VaultManager already set");
vaultManager = _vaultManager;
emit SetVaultManager(_vaultManager);
}
Expand Down Expand Up @@ -289,6 +290,17 @@ contract PSM is AccessControlUpgradeable, PausableUpgradeable, UUPSUpgradeable {
return IERC20(lisUSD).balanceOf(address(this)) - fees;
}

/**
* @dev get day buy left
* @return day buy left
*/
function getDayBuyLeft() external view returns (uint256) {
if (getDay() == lastBuyDay) {
return dailyLimit - dayBuyUsed;
}
return dailyLimit;
}

/**
* @dev harvest fees
*/
Expand Down
5 changes: 2 additions & 3 deletions contracts/psm/VaultManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ contract VaultManager is ReentrancyGuardUpgradeable, AccessControlUpgradeable, U

Adapter[] public adapters; // adapter list

uint256 public constant MAX_PRECISION = 10000;
bytes32 public constant MANAGER = keccak256("MANAGER"); // manager role
bytes32 public constant BOT = keccak256("BOT"); // bot role

Expand Down Expand Up @@ -76,7 +75,7 @@ contract VaultManager is ReentrancyGuardUpgradeable, AccessControlUpgradeable, U
}

/**
* @dev deposit token to adapters, only PSM can call this function
* @dev deposit token to adapters, only PSM or manager can call this function
* @param amount deposit amount
*/
function deposit(uint256 amount) external nonReentrant onlyPSMOrManager {
Expand Down Expand Up @@ -112,7 +111,7 @@ contract VaultManager is ReentrancyGuardUpgradeable, AccessControlUpgradeable, U
}

/**
* @dev withdraw token from adapters, only PSM can call this function
* @dev withdraw token from adapters, only PSM or manager can call this function
* @param receiver receiver address
* @param amount withdraw amount
*/
Expand Down
21 changes: 7 additions & 14 deletions contracts/psm/VenusAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import "../interfaces/IVBep20Delegate.sol";
contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {
using SafeERC20 for IERC20;
address public vaultManager; // vault manager address
address public venusPool; // venus pool address
address public token; // token address
address public vToken; // vToken address
uint256 public netDepositAmount; // user net deposit amount
Expand All @@ -24,7 +23,6 @@ contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {
event SetFeeReceiver(address feeReceiver);
event EmergencyWithdraw(address token, uint256 amount);
event SetVaultManager(address vaultManager);
event SetVenusPool(address venusPool);
event SetVToken(address vToken);
event SetToken(address token);

Expand All @@ -43,7 +41,6 @@ contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {
* @param _admin admin address
* @param _manager manager address
* @param _vaultManager vault manager address
* @param _venusPool venus pool address
* @param _token token address
* @param _vToken vToken address
* @param _feeReceiver fee receiver address
Expand All @@ -52,15 +49,13 @@ contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {
address _admin,
address _manager,
address _vaultManager,
address _venusPool,
address _token,
address _vToken,
address _feeReceiver
) public initializer {
require(_admin != address(0), "admin cannot be zero address");
require(_manager != address(0), "manager cannot be zero address");
require(_vaultManager != address(0), "vaultManager cannot be zero address");
require(_venusPool != address(0), "venusPool cannot be zero address");
require(_token != address(0), "token cannot be zero address");
require(_vToken != address(0), "vToken cannot be zero address");
require(_feeReceiver != address(0), "feeReceiver cannot be zero address");
Expand All @@ -73,12 +68,10 @@ contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {

vaultManager = _vaultManager;
token = _token;
venusPool = _venusPool;
vToken = _vToken;
feeReceiver = _feeReceiver;

emit SetVaultManager(_vaultManager);
emit SetVenusPool(_venusPool);
emit SetToken(_token);
emit SetVToken(_vToken);
emit SetFeeReceiver(_feeReceiver);
Expand All @@ -91,12 +84,12 @@ contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {
function deposit(uint256 amount) external onlyVaultManager {
require(amount > 0, "deposit amount cannot be zero");
IERC20(token).safeTransferFrom(vaultManager, address(this), amount);
IERC20(token).safeIncreaseAllowance(venusPool, amount);
IERC20(token).safeIncreaseAllowance(vToken, amount);

netDepositAmount += amount;

// deposit to venus pool
IVBep20Delegate(venusPool).mint(amount);
IVBep20Delegate(vToken).mint(amount);

emit Deposit(amount);
}
Expand All @@ -112,7 +105,7 @@ contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {

netDepositAmount -= amount;

IVBep20Delegate(venusPool).redeemUnderlying(amount);
IVBep20Delegate(vToken).redeemUnderlying(amount);

// transfer token to account
IERC20(token).safeTransfer(account, amount);
Expand Down Expand Up @@ -147,11 +140,11 @@ contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {
* @dev harvest interest to fee receiver
*/
function harvest() public {
uint256 totalAmount = IVBep20Delegate(venusPool).balanceOfUnderlying(address(this));
uint256 totalAmount = IVBep20Delegate(vToken).balanceOfUnderlying(address(this));
if (totalAmount > netDepositAmount) {
// calculate interest and redeem amount
uint256 interest = totalAmount - netDepositAmount;
IVBep20Delegate(venusPool).redeemUnderlying(interest);
IVBep20Delegate(vToken).redeemUnderlying(interest);
IERC20(token).safeTransfer(feeReceiver, interest);

emit Harvest(feeReceiver, interest);
Expand All @@ -160,8 +153,8 @@ contract VenusAdapter is AccessControlUpgradeable, UUPSUpgradeable {

function _withdrawFromVenus(uint256 vTokenAmount) private returns (uint256) {
uint256 before = IERC20(token).balanceOf(address(this));
IERC20(vToken).safeIncreaseAllowance(venusPool, vTokenAmount);
IVBep20Delegate(venusPool).redeem(vTokenAmount);
IERC20(vToken).safeIncreaseAllowance(vToken, vTokenAmount);
IVBep20Delegate(vToken).redeem(vTokenAmount);
return IERC20(token).balanceOf(address(this)) - before;
}

Expand Down
3 changes: 1 addition & 2 deletions test/psm/PSM.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ contract PSMTest is Test {
ProxyAdmin proxyAdmin = ProxyAdmin(0xBd8789025E91AF10487455B692419F82523D29Be);
address lisUSD = 0x0782b6d8c4551B9760e74c0545a9bCD90bdc41E5;
address USDC = 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d;
address venusPool = 0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8;
address vUSDC = 0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8;
uint256 quotaAmount = 1e18;

Expand Down Expand Up @@ -76,7 +75,6 @@ contract PSMTest is Test {
admin,
admin,
address(vaultManager),
venusPool,
USDC,
vUSDC,
quotaAmount,
Expand Down Expand Up @@ -303,6 +301,7 @@ contract PSMTest is Test {
vm.expectRevert("VaultManager cannot be zero address");
psm.setVaultManager(zero);

vm.expectRevert("VaultManager already set");
psm.setVaultManager(address(vaultManager));
vm.stopPrank();

Expand Down
7 changes: 2 additions & 5 deletions test/psm/VaultManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ contract VaultManagerTest is Test {
ProxyAdmin proxyAdmin = ProxyAdmin(0xBd8789025E91AF10487455B692419F82523D29Be);
address lisUSD = 0x0782b6d8c4551B9760e74c0545a9bCD90bdc41E5;
address USDC = 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d;
address venusPool = 0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8;
address vUSDC = 0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8;
uint256 quotaAmount = 1e18;

Expand Down Expand Up @@ -52,7 +51,6 @@ contract VaultManagerTest is Test {
admin,
admin,
address(vaultManager),
venusPool,
USDC,
vUSDC,
quotaAmount,
Expand Down Expand Up @@ -98,13 +96,13 @@ contract VaultManagerTest is Test {

vaultManager.deposit(1000 ether);

uint256 venusAdapterBalance = IVBep20Delegate(venusPool).balanceOfUnderlying(address(venusAdapter));
uint256 venusAdapterBalance = IVBep20Delegate(vUSDC).balanceOfUnderlying(address(venusAdapter));
uint256 vaultManagerBalance = IERC20(USDC).balanceOf(address(vaultManager));
assertTrue(venusAdapterBalance <= 1000 ether && venusAdapterBalance > 999 ether, "venusAdapterBalance 0 error");
assertEq(vaultManagerBalance, 0, "vaultManagerBalance 0 error");

vaultManager.withdraw(user1, 900 ether);
venusAdapterBalance = IVBep20Delegate(venusPool).balanceOfUnderlying(address(venusAdapter));
venusAdapterBalance = IVBep20Delegate(vUSDC).balanceOfUnderlying(address(venusAdapter));
vaultManagerBalance = IERC20(USDC).balanceOf(address(vaultManager));
assertTrue(venusAdapterBalance <= 101 ether && venusAdapterBalance > 99 ether, "venusAdapterBalance 1 error");
assertEq(vaultManagerBalance, 0, "vaultManagerBalance 1 error");
Expand Down Expand Up @@ -270,7 +268,6 @@ contract VaultManagerTest is Test {
admin,
admin,
address(vaultManager),
venusPool,
USDC,
vUSDC,
quotaAmount,
Expand Down
23 changes: 8 additions & 15 deletions test/psm/VenusAdapter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ contract VenusAdapterTest is Test {
VenusAdapter venusAdapter;
address admin = address(0x10);
address user1 = address(0x004319Fd76912890F7920aEE99Df27EBA05ef48D);
address venusPool = 0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8;
address USDC = 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d;
address vUSDC = 0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8;
ProxyAdmin proxyAdmin = ProxyAdmin(0xBd8789025E91AF10487455B692419F82523D29Be);
Expand All @@ -26,7 +25,7 @@ contract VenusAdapterTest is Test {

ERC1967Proxy venusAdapterProxy = new ERC1967Proxy(
address(venusAdapterImpl),
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, user1, venusPool, USDC, vUSDC, admin)
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, user1, USDC, vUSDC, admin)
);

venusAdapter = VenusAdapter(address(venusAdapterProxy));
Expand All @@ -46,7 +45,7 @@ contract VenusAdapterTest is Test {
vm.stopPrank();

vUSDCBalance = IERC20(vUSDC).balanceOf(address(venusAdapter));
uint256 gemAmount = IVBep20Delegate(venusPool).balanceOfUnderlying(address(venusAdapter));
uint256 gemAmount = IVBep20Delegate(vUSDC).balanceOfUnderlying(address(venusAdapter));
assertTrue(vUSDCBalance > 0, "vUSDC 1 error");
assertTrue(gemAmount > 99 ether && gemAmount <= 100 ether, "Staked USDC 1 error");

Expand Down Expand Up @@ -91,43 +90,37 @@ contract VenusAdapterTest is Test {
vm.expectRevert("admin cannot be zero address");
new ERC1967Proxy(
address(venusAdapterImpl),
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, zero, admin, admin, venusPool, USDC, vUSDC, admin)
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, zero, admin, admin, USDC, vUSDC, admin)
);

vm.expectRevert("manager cannot be zero address");
new ERC1967Proxy(
address(venusAdapterImpl),
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, zero, admin, venusPool, USDC, vUSDC, admin)
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, zero, admin, USDC, vUSDC, admin)
);

vm.expectRevert("vaultManager cannot be zero address");
new ERC1967Proxy(
address(venusAdapterImpl),
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, zero, venusPool, USDC, vUSDC, admin)
);

vm.expectRevert("venusPool cannot be zero address");
new ERC1967Proxy(
address(venusAdapterImpl),
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, admin, zero, USDC, vUSDC, admin)
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, zero, USDC, vUSDC, admin)
);

vm.expectRevert("token cannot be zero address");
new ERC1967Proxy(
address(venusAdapterImpl),
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, admin, venusPool, zero, vUSDC, admin)
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, admin, zero, vUSDC, admin)
);

vm.expectRevert("vToken cannot be zero address");
new ERC1967Proxy(
address(venusAdapterImpl),
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, admin, venusPool, USDC, zero, admin)
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, admin, USDC, zero, admin)
);

vm.expectRevert("feeReceiver cannot be zero address");
new ERC1967Proxy(
address(venusAdapterImpl),
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, admin, venusPool, USDC, vUSDC, zero)
abi.encodeWithSelector(venusAdapterImpl.initialize.selector, admin, admin, admin, USDC, vUSDC, zero)
);
}

Expand Down

0 comments on commit fd1cf25

Please sign in to comment.