Re-entrancy points
User control of execution mostly stems from the fact that users exercise full control over asset and pipeToContract in FNFTConfig. Users control ValueLock's oracle and AddressLock's trigger, which can also lead to external, user-controlled calls.
Finally, it is important to keep in mind a callback is called on to whenever an ERC1155 is minted. Although there are so many re-entrancy points, they're not directly exploitable as every external function is marked nonReentrant.
Revest.sol
Revest.sol:{333, 354} - user controls fnftConfig.asset
333: IERC20(fnftConfig.asset).safeTransferFrom(_msgSender(), addressesProvider.getAdmin(), totalERC20Fee);
...
354: IERC20(fnftConfig.asset).safeTransferFrom(_msgSender(), vault, totalQuantity * fnftConfig.depositAmount);Revest.sol:136 - user controls trigger
136: IAddressLock(trigger).createLock(fnftId, lockId, arguments);Revest.sol:{203, 248} - user controls pipeToContract
203: IOutputReceiverV3(config.pipeToContract).handleTimelockExtensions(fnftId, endTime, msg.sender);
...
248: IOutputReceiverV3(fnft.pipeToContract).handleAdditionalDeposit(fnftId, amount, quantity, msg.sender);Revest.sol:358-362 - ERC1155 _mint executes callback on to
358: if(!isSingular) {
359: getFNFTHandler().mintBatchRec(recipients, quantities, fnftId, totalQuantity, '');
360: } else {
361: getFNFTHandler().mint(recipients[0], fnftId, quantities[0], '');
362: }LockManager.sol
LockManager.sol:{60, 158} - user controls lock.valueLock.oracle
60: IOracleDispatch oracle = IOracleDispatch(lock.valueLock.oracle);
...
158: IOracleDispatch oracle = IOracleDispatch(lock.valueLock.oracle);LockManager.sol:{121, 143} - user controls lock.addressLock
121: IAddressLock(addLock).isUnlockable(fnftId, lockId))
...
143: IAddressLock(lock.addressLock).isUnlockable(fnftId, fnftIdToLockId[fnftId])TokenVault.sol
TokenVault.sol:{60, 104, 110, 229} - user controls asset
60: currentAmount = IERC20(asset).balanceOf(address(this));
...
104: IERC20(asset).safeTransfer(user, withdrawAmount);
...
110: IERC20(asset).safeTransfer(fnft.pipeToContract, withdrawAmount);
...
229: currentAmount = IERC20(fnfts[fnftId].asset).balanceOf(address(this));TokenVault.sol:{114, 224} - user controls pipeToContract
114: IOutputReceiver(pipeTo).receiveRevestOutput(fnftId, asset, payable(user), quantity);
...
224: return IOutputReceiver(fnfts[fnftId].pipeToContract).getValue((fnftId));FNFTHandler.sol (fnft-migration branch)
FNFTHandler.sol:{106, 117} - user controls pipeToContract
106: IOutputReceiverV4(config.pipeToContract).onTransferFNFT(ids[0], operator, from, to, amounts[0], data);
...
117: IOutputReceiverV4(config.pipeToContract).onTransferFNFT(ids[i], operator, from, to, amounts[i], data);