Reentrancy in FortaStaking during ERC1155 mints
In the Forta staking system, the staking shares (both “active” and “inactive”) are represented as tokens implemented according to the `ERC1155` standard. The specific implementation that is being used utilizes a smart contract acceptance check `_doSafeTransferAcceptanceCheck()` upon mints to the recipient.\\n```\\ncontract FortaStaking is BaseComponentUpgradeable, ERC1155SupplyUpgradeable, SubjectTypeValidator, ISlashingExecutor, IStakeMigrator {\\n```\\n\\nThe specific implementation for `ERC1155SupplyUpgradeable` contracts can be found here, and the smart contract check can be found here.\\nThis opens up reentrancy into the system's flow. In fact, the reentrancy occurs on all mints that happen in the below functions, and it happens before a call to another Forta contract for allocation is made via either `_allocator.depositAllocation` or _allocator.withdrawAllocation:\\n```\\nfunction deposit(\\n    uint8 subjectType,\\n    uint256 subject,\\n    uint256 stakeValue\\n) external onlyValidSubjectType(subjectType) notAgencyType(subjectType, SubjectStakeAgency.MANAGED) returns (uint256) {\\n    if (address(subjectGateway) == address(0)) revert ZeroAddress("subjectGateway");\\n    if (!subjectGateway.isStakeActivatedFor(subjectType, subject)) revert StakeInactiveOrSubjectNotFound();\\n    address staker = \\_msgSender();\\n    uint256 activeSharesId = FortaStakingUtils.subjectToActive(subjectType, subject);\\n    bool reachedMax;\\n    (stakeValue, reachedMax) = \\_getInboundStake(subjectType, subject, stakeValue);\\n    if (reachedMax) {\\n        emit MaxStakeReached(subjectType, subject);\\n    }\\n    uint256 sharesValue = stakeToActiveShares(activeSharesId, stakeValue);\\n    SafeERC20.safeTransferFrom(stakedToken, staker, address(this), stakeValue);\\n\\n    \\_activeStake.mint(activeSharesId, stakeValue);\\n    \\_mint(staker, activeSharesId, sharesValue, new bytes(0));\\n    emit StakeDeposited(subjectType, subject, staker, stakeValue);\\n    \\_allocator.depositAllocation(activeSharesId, subjectType, subject, staker, stakeValue, sharesValue);\\n    return sharesValue;\\n}\\n```\\n\\n```\\nfunction migrate(\\n    uint8 oldSubjectType,\\n    uint256 oldSubject,\\n    uint8 newSubjectType,\\n    uint256 newSubject,\\n    address staker\\n) external onlyRole(SCANNER\\_2\\_NODE\\_RUNNER\\_MIGRATOR\\_ROLE) {\\n    if (oldSubjectType != SCANNER\\_SUBJECT) revert InvalidSubjectType(oldSubjectType);\\n    if (newSubjectType != NODE\\_RUNNER\\_SUBJECT) revert InvalidSubjectType(newSubjectType); \\n    if (isFrozen(oldSubjectType, oldSubject)) revert FrozenSubject();\\n\\n    uint256 oldSharesId = FortaStakingUtils.subjectToActive(oldSubjectType, oldSubject);\\n    uint256 oldShares = balanceOf(staker, oldSharesId);\\n    uint256 stake = activeSharesToStake(oldSharesId, oldShares);\\n    uint256 newSharesId = FortaStakingUtils.subjectToActive(newSubjectType, newSubject);\\n    uint256 newShares = stakeToActiveShares(newSharesId, stake);\\n\\n    \\_activeStake.burn(oldSharesId, stake);\\n    \\_activeStake.mint(newSharesId, stake);\\n    \\_burn(staker, oldSharesId, oldShares);\\n    \\_mint(staker, newSharesId, newShares, new bytes(0));\\n    emit StakeDeposited(newSubjectType, newSubject, staker, stake);\\n    \\_allocator.depositAllocation(newSharesId, newSubjectType, newSubject, staker, stake, newShares);\\n}\\n```\\n\\n```\\nfunction initiateWithdrawal(\\n    uint8 subjectType,\\n    uint256 subject,\\n    uint256 sharesValue\\n) external onlyValidSubjectType(subjectType) returns (uint64) {\\n    address staker = \\_msgSender();\\n    uint256 activeSharesId = FortaStakingUtils.subjectToActive(subjectType, subject);\\n    if (balanceOf(staker, activeSharesId) == 0) revert NoActiveShares();\\n    uint64 deadline = SafeCast.toUint64(block.timestamp) + \\_withdrawalDelay;\\n\\n    \\_lockingDelay[activeSharesId][staker].setDeadline(deadline);\\n\\n    uint256 activeShares = Math.min(sharesValue, balanceOf(staker, activeSharesId));\\n    uint256 stakeValue = activeSharesToStake(activeSharesId, activeShares);\\n    uint256 inactiveShares = stakeToInactiveShares(FortaStakingUtils.activeToInactive(activeSharesId), stakeValue);\\n    SubjectStakeAgency agency = getSubjectTypeAgency(subjectType);\\n    \\_activeStake.burn(activeSharesId, stakeValue);\\n    \\_inactiveStake.mint(FortaStakingUtils.activeToInactive(activeSharesId), stakeValue);\\n    \\_burn(staker, activeSharesId, activeShares);\\n    \\_mint(staker, FortaStakingUtils.activeToInactive(activeSharesId), inactiveShares, new bytes(0));\\n    if (agency == SubjectStakeAgency.DELEGATED || agency == SubjectStakeAgency.DELEGATOR) {\\n        \\_allocator.withdrawAllocation(activeSharesId, subjectType, subject, staker, stakeValue, activeShares);\\n    }\\n```\\n\\nAlthough this doesn't seem to be an issue in the current Forta system of contracts since the allocator's logic doesn't seem to be manipulable, this could still be dangerous as it opens up an external execution flow.
Consider introducing a reentrancy check or emphasize this behavior in the documentation, so that both other projects using this system later and future upgrades along with maintenance work on the Forta staking system itself are implemented safely.
```\\ncontract FortaStaking is BaseComponentUpgradeable, ERC1155SupplyUpgradeable, SubjectTypeValidator, ISlashingExecutor, IStakeMigrator {\\n```\\n