diff --git a/nest/src/token/pUSD.sol b/nest/src/token/pUSD.sol index 5d3bb79..b60f7d0 100644 --- a/nest/src/token/pUSD.sol +++ b/nest/src/token/pUSD.sol @@ -6,7 +6,6 @@ import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/I import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import { ERC4626Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol"; -import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol"; import { IERC20Metadata } from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -29,14 +28,7 @@ import { ComponentToken } from "../ComponentToken.sol"; * @author Eugene Y. Q. Shen, Alp Guneysel * @notice Unified Plume USD stablecoin */ -contract pUSD is - Initializable, - ERC20Upgradeable, - AccessControlUpgradeable, - UUPSUpgradeable, - ReentrancyGuardUpgradeable, - ComponentToken -{ +contract pUSD is Initializable, ERC20Upgradeable, AccessControlUpgradeable, UUPSUpgradeable, ComponentToken { using SafeERC20 for IERC20; using FixedPointMathLib for uint256; @@ -132,9 +124,8 @@ contract pUSD is __UUPSUpgradeable_init(); __AccessControl_init(); __ERC20_init("Plume USD", "pUSD"); - __ReentrancyGuard_init(); - super.initialize(owner, "Plume USD", "pUSD", asset_, false, false); + super.initialize(owner, "Plume USD", "pUSD", asset_, false, true); pUSDStorage storage $ = _getpUSDStorage(); $.boringVault.teller = ITeller(teller_); @@ -248,7 +239,7 @@ contract pUSD is address receiver, address controller, uint256 minimumMint - ) public virtual nonReentrant returns (uint256 shares) { + ) public virtual returns (uint256 shares) { if (receiver == address(0)) { revert InvalidReceiver(); } @@ -297,7 +288,7 @@ contract pUSD is address controller, uint256 price, uint64 deadline - ) public virtual nonReentrant returns (uint256) { + ) public virtual returns (uint256) { if (receiver == address(0)) { revert InvalidReceiver(); } @@ -345,7 +336,7 @@ contract pUSD is uint256 shares, address receiver, address controller - ) public virtual override(ComponentToken) nonReentrant returns (uint256 assets) { + ) public virtual override(ComponentToken) returns (uint256 assets) { // Check claimableRedeemRequest, Transfer assets to receiver, Clean up request state. return super.redeem(shares, receiver, controller); } @@ -414,10 +405,7 @@ contract pUSD is * @param amount Amount of tokens to transfer * @return bool indicating whether the transfer was successful */ - function transfer( - address to, - uint256 amount - ) public virtual override(ERC20Upgradeable, IERC20) nonReentrant returns (bool) { + function transfer(address to, uint256 amount) public virtual override(ERC20Upgradeable, IERC20) returns (bool) { address owner = msg.sender; _transfer(owner, to, amount); return true; @@ -434,7 +422,7 @@ contract pUSD is address from, address to, uint256 amount - ) public virtual override(ERC20Upgradeable, IERC20) nonReentrant returns (bool) { + ) public virtual override(ERC20Upgradeable, IERC20) returns (bool) { address spender = msg.sender; _spendAllowance(from, spender, amount); _transfer(from, to, amount); diff --git a/nest/test/pUSD.t.sol b/nest/test/pUSD.t.sol index 3a4a25a..eb97869 100644 --- a/nest/test/pUSD.t.sol +++ b/nest/test/pUSD.t.sol @@ -97,6 +97,17 @@ contract pUSDTest is Test { ); token = pUSD(address(proxy)); + vm.startPrank(owner); + + // Grant ATOMIC_QUEUE_ROLE to mockAtomicQueue + bytes32 ATOMIC_QUEUE_ROLE = keccak256("ATOMIC_QUEUE_ROLE"); + token.grantRole(ATOMIC_QUEUE_ROLE, address(mockAtomicQueue)); + + // Grant ADMIN_ROLE to mockAtomicQueue + token.grantRole(token.ADMIN_ROLE(), address(mockAtomicQueue)); + + vm.stopPrank(); + // Setup balances usdc.mint(user1, 1000e6); @@ -193,25 +204,30 @@ contract pUSDTest is Test { function testPreviewRedeem() public { uint256 depositAmount = 100e6; uint256 redeemAmount = 50e6; + uint256 price = 1e6; uint64 deadline = uint64(block.timestamp + 1 hours); // Setup: First deposit some tokens vm.startPrank(user1); token.deposit(depositAmount, user1, user1, 0); - - // Request redemption - token.requestRedeem(redeemAmount, user1, user1, 1e6, deadline); - - // Mock atomic queue fulfillment vm.stopPrank(); - vm.prank(address(mockAtomicQueue)); - token.notifyRedeem(redeemAmount, redeemAmount, user1); // Preview redeem should return same amount as assets (1:1 ratio) uint256 expectedAssets = token.previewRedeem(redeemAmount); assertEq(expectedAssets, redeemAmount); - // Verify actual redeem matches preview + // Mock the lens to return correct balance + mockLens.setBalance(user1, depositAmount); + + // Request redemption + vm.prank(user1); + token.requestRedeem(redeemAmount, user1, user1, price, deadline); + + // Simulate atomic queue fulfillment + vm.prank(address(mockAtomicQueue)); + token.notifyRedeem(redeemAmount, redeemAmount, user1); + + // Complete redemption vm.prank(user1); uint256 actualAssets = token.redeem(redeemAmount, user1, user1);