AuraSpell `openPositionFarm` will revert when the tokens contains `lpToken`
In AuraSpell, the `openPositionFarm` will call `joinPool` in Balancer's vault. But when analyzing the `JoinPoolRequest` struct, we see issue on `maxAmountsIn` and `amountsIn` which can be in different length, thus this will be reverted since in Balancer's vault, this two array should be in the same length.\\n```\\nFile: AuraSpell.sol\\n    function openPositionFarm(\\n        OpenPosParam calldata param,\\n        uint256 minimumBPT\\n    )\\n// rest of code\\n    {\\n// rest of code\\n        /// 3. Add liquidity to the Balancer pool and receive BPT in return.\\n        {\\n// rest of code\\n            if (poolAmountOut != 0) {\\n                vault.joinPool(\\n                    wAuraPools.getBPTPoolId(lpToken),\\n                    address(this),\\n                    address(this),\\n                    IBalancerVault.JoinPoolRequest({\\n                        assets: tokens,\\n                        maxAmountsIn: maxAmountsIn,\\n                        userData: abi.encode(1, amountsIn, _minimumBPT),\\n                        fromInternalBalance: false\\n                    })\\n                );\\n            }\\n        }\\n// rest of code\\n    }\\n// rest of code\\n    function _getJoinPoolParamsAndApprove(\\n        address vault,\\n        address[] memory tokens,\\n        uint256[] memory balances,\\n        address lpToken\\n    ) internal returns (uint256[] memory, uint256[] memory, uint256) {\\n// rest of code\\n        uint256 length = tokens.length;\\n        uint256[] memory maxAmountsIn = new uint256[](length);\\n        uint256[] memory amountsIn = new uint256[](length);\\n        bool isLPIncluded;\\n        for (i; i != length; ) {\\n            if (tokens[i] != lpToken) {\\n                amountsIn[j] = IERC20(tokens[i]).balanceOf(address(this));\\n                if (amountsIn[j] > 0) {\\n                    _ensureApprove(tokens[i], vault, amountsIn[j]);\\n                }\\n                ++j;\\n            } else isLPIncluded = true;\\n            maxAmountsIn[i] = IERC20(tokens[i]).balanceOf(address(this));\\n            unchecked {\\n                ++i;\\n            }\\n        }\\n        if (isLPIncluded) {\\n            assembly {\\n                mstore(amountsIn, sub(mload(amountsIn), 1))\\n            }\\n        }\\n// rest of code\\n        return (maxAmountsIn, amountsIn, poolAmountOut);\\n    }\\n```\\n\\nthese `maxAmountsIn` and `amountsIn` are coming from `_getJoinPoolParamsAndApprove`. And by seeing the function, we can see that there is possible issue when the `tokens[i] == lpToken`.\\nWhen `tokens[i] == lpToken`, the flag `isLPIncluded` will be true. And will enter this block,\\n```\\n        if (isLPIncluded) {\\n            assembly {\\n                mstore(amountsIn, sub(mload(amountsIn), 1))\\n            }\\n        }\\n```\\n\\nthis will decrease the `amountsIn` length. Thus, `amountsIn` and `maxAmountsIn` will be in different length.\\nIn Balancer's `JoinPoolRequest` struct, the `maxAmountsIn`, and `userData` second decoded bytes (amountsIn) should be the same array length, because it will be checked in Balancer.\\n```\\n                    IBalancerVault.JoinPoolRequest({\\n                        assets: tokens,\\n                        maxAmountsIn: maxAmountsIn,\\n                        userData: abi.encode(1, amountsIn, _minimumBPT),\\n                        fromInternalBalance: false\\n                    })\\n```\\n\\nTherefore, in this situation, it will be reverted.
Issue AuraSpell `openPositionFarm` will revert when the tokens contains `lpToken`\\nRemove the assembly code where it will decrease the `amountsIn` length when `isLPIncluded` is true to make sure the array length are same.
User can't open position on AuraSpell when `tokens` contains `lpToken`
```\\nFile: AuraSpell.sol\\n    function openPositionFarm(\\n        OpenPosParam calldata param,\\n        uint256 minimumBPT\\n    )\\n// rest of code\\n    {\\n// rest of code\\n        /// 3. Add liquidity to the Balancer pool and receive BPT in return.\\n        {\\n// rest of code\\n            if (poolAmountOut != 0) {\\n                vault.joinPool(\\n                    wAuraPools.getBPTPoolId(lpToken),\\n                    address(this),\\n                    address(this),\\n                    IBalancerVault.JoinPoolRequest({\\n                        assets: tokens,\\n                        maxAmountsIn: maxAmountsIn,\\n                        userData: abi.encode(1, amountsIn, _minimumBPT),\\n                        fromInternalBalance: false\\n                    })\\n                );\\n            }\\n        }\\n// rest of code\\n    }\\n// rest of code\\n    function _getJoinPoolParamsAndApprove(\\n        address vault,\\n        address[] memory tokens,\\n        uint256[] memory balances,\\n        address lpToken\\n    ) internal returns (uint256[] memory, uint256[] memory, uint256) {\\n// rest of code\\n        uint256 length = tokens.length;\\n        uint256[] memory maxAmountsIn = new uint256[](length);\\n        uint256[] memory amountsIn = new uint256[](length);\\n        bool isLPIncluded;\\n        for (i; i != length; ) {\\n            if (tokens[i] != lpToken) {\\n                amountsIn[j] = IERC20(tokens[i]).balanceOf(address(this));\\n                if (amountsIn[j] > 0) {\\n                    _ensureApprove(tokens[i], vault, amountsIn[j]);\\n                }\\n                ++j;\\n            } else isLPIncluded = true;\\n            maxAmountsIn[i] = IERC20(tokens[i]).balanceOf(address(this));\\n            unchecked {\\n                ++i;\\n            }\\n        }\\n        if (isLPIncluded) {\\n            assembly {\\n                mstore(amountsIn, sub(mload(amountsIn), 1))\\n            }\\n        }\\n// rest of code\\n        return (maxAmountsIn, amountsIn, poolAmountOut);\\n    }\\n```\\n