feat: Smother slither and add a reentrancy guard in swap()
--- don't change below this line --- ENG-4041 Took 34 minutes
This commit is contained in:
@@ -50,7 +50,7 @@ contract ExecutionDispatcher {
|
|||||||
* @dev Calls an executor, assumes swap.protocolData contains
|
* @dev Calls an executor, assumes swap.protocolData contains
|
||||||
* protocol-specific data required by the executor.
|
* protocol-specific data required by the executor.
|
||||||
*/
|
*/
|
||||||
// slither-disable-next-line dead-code
|
// slither-disable-next-line delegatecall-loop
|
||||||
function _callExecutor(
|
function _callExecutor(
|
||||||
address executor,
|
address executor,
|
||||||
bytes4 selector,
|
bytes4 selector,
|
||||||
@@ -62,8 +62,7 @@ contract ExecutionDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selector = selector == bytes4(0) ? IExecutor.swap.selector : selector;
|
selector = selector == bytes4(0) ? IExecutor.swap.selector : selector;
|
||||||
|
// slither-disable-next-line controlled-delegatecall,low-level-calls
|
||||||
// slither-disable-next-line low-level-calls
|
|
||||||
(bool success, bytes memory result) = executor.delegatecall(
|
(bool success, bytes memory result) = executor.delegatecall(
|
||||||
abi.encodeWithSelector(selector, amount, data)
|
abi.encodeWithSelector(selector, amount, data)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ import "./CallbackVerificationDispatcher.sol";
|
|||||||
import "@openzeppelin/contracts/access/AccessControl.sol";
|
import "@openzeppelin/contracts/access/AccessControl.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||||
|
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||||
|
import "@openzeppelin/contracts/utils/Pausable.sol";
|
||||||
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
|
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
|
||||||
import "./ExecutionDispatcher.sol";
|
import "./ExecutionDispatcher.sol";
|
||||||
import "./CallbackVerificationDispatcher.sol";
|
import "./CallbackVerificationDispatcher.sol";
|
||||||
import "@openzeppelin/contracts/utils/Pausable.sol";
|
|
||||||
import {LibSwap} from "../lib/LibSwap.sol";
|
import {LibSwap} from "../lib/LibSwap.sol";
|
||||||
|
|
||||||
error TychoRouter__WithdrawalFailed();
|
error TychoRouter__WithdrawalFailed();
|
||||||
@@ -22,7 +23,8 @@ contract TychoRouter is
|
|||||||
AccessControl,
|
AccessControl,
|
||||||
ExecutionDispatcher,
|
ExecutionDispatcher,
|
||||||
CallbackVerificationDispatcher,
|
CallbackVerificationDispatcher,
|
||||||
Pausable
|
Pausable,
|
||||||
|
ReentrancyGuard
|
||||||
{
|
{
|
||||||
IAllowanceTransfer public immutable permit2;
|
IAllowanceTransfer public immutable permit2;
|
||||||
IWETH private immutable _weth;
|
IWETH private immutable _weth;
|
||||||
@@ -125,7 +127,9 @@ contract TychoRouter is
|
|||||||
IAllowanceTransfer.PermitSingle calldata permitSingle,
|
IAllowanceTransfer.PermitSingle calldata permitSingle,
|
||||||
bytes calldata signature,
|
bytes calldata signature,
|
||||||
bytes calldata swaps
|
bytes calldata swaps
|
||||||
) external payable whenNotPaused returns (uint256 amountOut) {
|
) external payable whenNotPaused nonReentrant returns (uint256 amountOut) {
|
||||||
|
require(receiver != address(0), "Invalid receiver address");
|
||||||
|
|
||||||
// For native ETH, assume funds already in our router. Else, transfer and handle approval.
|
// For native ETH, assume funds already in our router. Else, transfer and handle approval.
|
||||||
if (wrapEth) {
|
if (wrapEth) {
|
||||||
_wrapETH(amountIn);
|
_wrapETH(amountIn);
|
||||||
@@ -145,7 +149,7 @@ contract TychoRouter is
|
|||||||
uint256 feeAmount = (amountOut * fee) / 10000;
|
uint256 feeAmount = (amountOut * fee) / 10000;
|
||||||
amountOut -= feeAmount;
|
amountOut -= feeAmount;
|
||||||
IERC20(tokenOut).safeTransfer(feeReceiver, feeAmount);
|
IERC20(tokenOut).safeTransfer(feeReceiver, feeAmount);
|
||||||
if (unwrapEth == false) {
|
if (!unwrapEth) {
|
||||||
IERC20(tokenOut).safeTransfer(receiver, amountOut);
|
IERC20(tokenOut).safeTransfer(receiver, amountOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,6 +160,7 @@ contract TychoRouter is
|
|||||||
|
|
||||||
if (unwrapEth) {
|
if (unwrapEth) {
|
||||||
_unwrapETH(amountOut);
|
_unwrapETH(amountOut);
|
||||||
|
// slither-disable-next-line arbitrary-send-eth
|
||||||
payable(receiver).transfer(amountOut);
|
payable(receiver).transfer(amountOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ error UniswapV2Executor__InvalidDataLength();
|
|||||||
contract UniswapV2Executor is IExecutor {
|
contract UniswapV2Executor is IExecutor {
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
|
// slither-disable-next-line locked-ether
|
||||||
function swap(uint256 givenAmount, bytes calldata data)
|
function swap(uint256 givenAmount, bytes calldata data)
|
||||||
external
|
external
|
||||||
payable
|
payable
|
||||||
|
|||||||
Reference in New Issue
Block a user