Vulnerability: Balancer using safeApprove may lead to revert.
Severity: medium

Description:
When executing `Balancer._routerSwap()`, the `oz` `safeApprove` function is used to set an allowance. Due to the presence of the `convertRate` in the `router`, `Balancer._routerSwap()` rounds down the incoming quantity. This behavior may result in the allowance not being fully use, causing a subsequent execution of `oz.safeApprove()` to revert.\\nThe code snippet for `Balancer._routerSwap()` is as follows:\\n```\\n    function _routerSwap(\\n        uint16 _dstChainId,\\n        uint256 _srcPoolId,\\n        uint256 _dstPoolId,\\n        uint256 _amount,\\n        uint256 _slippage,\\n        address payable _oft,\\n        address _erc20\\n    ) private {\\n        bytes memory _dst = abi.encodePacked(connectedOFTs[_oft][_dstChainId].dstOft);\\n      IERC20(_erc20).safeApprove(address(router), _amount);\\n        router.swap{value: msg.value}(\\n            _dstChainId,\\n            _srcPoolId,\\n            _dstPoolId,\\n            payable(this),\\n            _amount,\\n            _computeMinAmount(_amount, _slippage),\\n            IStargateRouterBase.lzTxObj({dstGasForCall: 0, dstNativeAmount: 0, dstNativeAddr: "0x0"}),\\n            _dst,\\n            "0x"\\n        );\\n    }\\n```\\n\\nIn the above code, `SafeERC20.safeApprove()` from the `oz` library is used, but the allowance is not cleared afterward. Consequently, if the current allowance is not fully use during this transaction, a subsequent execution of `SafeERC20.safeApprove()` will revert.\\n```\\n    function swap(\\n        uint16 _dstChainId,\\n        uint256 _srcPoolId,\\n        uint256 _dstPoolId,\\n        address payable _refundAddress,\\n        uint256 _amountLD,\\n        uint256 _minAmountLD,\\n        lzTxObj memory _lzTxParams,\\n        bytes calldata _to,\\n        bytes calldata _payload\\n    ) external payable override nonReentrant {\\n        require(_amountLD > 0, "Stargate: cannot swap 0");\\n        require(_refundAddress != address(0x0), "Stargate: _refundAddress cannot be 0x0");\\n        Pool.SwapObj memory s;\\n        Pool.CreditObj memory c;\\n        {\\n            Pool pool = _getPool(_srcPoolId);\\n            {\\n              uint256 convertRate = pool.convertRate();\\n              _amountLD = _amountLD.div(convertRate).mul(convertRate);\\n            }\\n\\n            s = pool.swap(_dstChainId, _dstPoolId, msg.sender, _amountLD, _minAmountLD, true);\\n            _safeTransferFrom(pool.token(), msg.sender, address(pool), _amountLD);\\n            c = pool.sendCredits(_dstChainId, _dstPoolId);\\n        }\\n        bridge.swap{value: msg.value}(_dstChainId, _srcPoolId, _dstPoolId, _refundAddress, c, s, _lzTxParams, _to, _payload);\\n    }\\n```\\n

Impact:
Unused allowance may lead to failure in subsequent `_routerSwap()` executions.

Recommended mitigation:
```\\n    function _routerSwap(\\n        uint16 _dstChainId,\\n        uint256 _srcPoolId,\\n        uint256 _dstPoolId,\\n        uint256 _amount,\\n        uint256 _slippage,\\n        address payable _oft,\\n        address _erc20\\n    ) private {\\n        bytes memory _dst = abi.encodePacked(connectedOFTs[_oft][_dstChainId].dstOft);\\n        IERC20(_erc20).safeApprove(address(router), _amount);\\n        router.swap{value: msg.value}(\\n            _dstChainId,\\n            _srcPoolId,\\n            _dstPoolId,\\n            payable(this),\\n            _amount,\\n            _computeMinAmount(_amount, _slippage),\\n            IStargateRouterBase.lzTxObj({dstGasForCall: 0, dstNativeAmount: 0, dstNativeAddr: "0x0"}),\\n            _dst,\\n            "0x"\\n        );\\n// Add the line below\\n       IERC20(_erc20).safeApprove(address(router), 0);\\n```\\n