Uniswap v3 callbacks access control should be hardened
Resolution\\nFixed in GammaStrategies/[email protected]9a7a3dd by implementing the auditor's recommendation for `uniswapV3MintCallback`, and deleting `uniswapV3SwapCallback` and the call to `pool.swap`.\\nUniswap v3 uses a callback pattern to pull funds from the caller. The caller, (in this case Hypervisor) has to implement a callback function which will be called by the Uniswap's `pool`. Both `uniswapV3MintCallback` and `uniswapV3SwapCallback` restrict the access to the callback functions only for the `pool`. However, this alone will not block a random call from the `pool` contract in case the latter was hacked, which will result in stealing all the funds held in `Hypervisor` or of any user that approved the `Hypervisor` contract to transfer tokens on his behalf.\\n```\\nfunction uniswapV3MintCallback(\\n    uint256 amount0,\\n    uint256 amount1,\\n    bytes calldata data\\n) external override {\\n    require(msg.sender == address(pool));\\n    address payer = abi.decode(data, (address));\\n\\n    if (payer == address(this)) {\\n        if (amount0 > 0) token0.safeTransfer(msg.sender, amount0);\\n        if (amount1 > 0) token1.safeTransfer(msg.sender, amount1);\\n    } else {\\n        if (amount0 > 0) token0.safeTransferFrom(payer, msg.sender, amount0);\\n        if (amount1 > 0) token1.safeTransferFrom(payer, msg.sender, amount1);\\n    }\\n}\\n\\nfunction uniswapV3SwapCallback(\\n    int256 amount0Delta,\\n    int256 amount1Delta,\\n    bytes calldata data\\n) external override {\\n    require(msg.sender == address(pool));\\n    address payer = abi.decode(data, (address));\\n\\n    if (amount0Delta > 0) {\\n        if (payer == address(this)) {\\n            token0.safeTransfer(msg.sender, uint256(amount0Delta));\\n        } else {\\n            token0.safeTransferFrom(payer, msg.sender, uint256(amount0Delta));\\n        }\\n    } else if (amount1Delta > 0) {\\n        if (payer == address(this)) {\\n            token1.safeTransfer(msg.sender, uint256(amount1Delta));\\n        } else {\\n            token1.safeTransferFrom(payer, msg.sender, uint256(amount1Delta));\\n        }\\n    }\\n}\\n```\\n
Consider adding (boolean) storage variables that will help to track whether a call to `uniswapV3MintCallback | uniswapV3SwapCallback` was preceded by a call to `_mintLiquidity | rebalance` respectively. An example for the `rebalance` function would be bool `rebalanceCalled`, this variable will be assigned a `true` value in `rebalance` before the external call of `pool.swap`, then `uniswapV3SwapCallback` will require that `rebalanceCalled` == `true`, and then right after `rebalanceCalled` will be assigned a `false` value.
```\\nfunction uniswapV3MintCallback(\\n    uint256 amount0,\\n    uint256 amount1,\\n    bytes calldata data\\n) external override {\\n    require(msg.sender == address(pool));\\n    address payer = abi.decode(data, (address));\\n\\n    if (payer == address(this)) {\\n        if (amount0 > 0) token0.safeTransfer(msg.sender, amount0);\\n        if (amount1 > 0) token1.safeTransfer(msg.sender, amount1);\\n    } else {\\n        if (amount0 > 0) token0.safeTransferFrom(payer, msg.sender, amount0);\\n        if (amount1 > 0) token1.safeTransferFrom(payer, msg.sender, amount1);\\n    }\\n}\\n\\nfunction uniswapV3SwapCallback(\\n    int256 amount0Delta,\\n    int256 amount1Delta,\\n    bytes calldata data\\n) external override {\\n    require(msg.sender == address(pool));\\n    address payer = abi.decode(data, (address));\\n\\n    if (amount0Delta > 0) {\\n        if (payer == address(this)) {\\n            token0.safeTransfer(msg.sender, uint256(amount0Delta));\\n        } else {\\n            token0.safeTransferFrom(payer, msg.sender, uint256(amount0Delta));\\n        }\\n    } else if (amount1Delta > 0) {\\n        if (payer == address(this)) {\\n            token1.safeTransfer(msg.sender, uint256(amount1Delta));\\n        } else {\\n            token1.safeTransferFrom(payer, msg.sender, uint256(amount1Delta));\\n        }\\n    }\\n}\\n```\\n