Skip to content

Commit

Permalink
Update TransferHelper
Browse files Browse the repository at this point in the history
  • Loading branch information
alcueca committed Jul 26, 2023
1 parent df3badd commit 37f5a11
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 85 deletions.
19 changes: 1 addition & 18 deletions src/dydx/DYDXWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,13 @@ pragma solidity ^0.8.0;
import { SoloMarginLike } from "./interfaces/SoloMarginLike.sol";
import { DYDXFlashBorrowerLike } from "./interfaces/DYDXFlashBorrowerLike.sol";
import { DYDXDataTypes } from "./libraries/DYDXDataTypes.sol";
import { RevertMsgExtractor } from "../utils/RevertMsgExtractor.sol";
import { TransferHelper } from "../utils/TransferHelper.sol";
import { FunctionCodec } from "../utils/FunctionCodec.sol";

import { IERC20 } from "lib/erc3156pp/src/interfaces/IERC20.sol";
import { IERC3156PPFlashLender } from "lib/erc3156pp/src/interfaces/IERC3156PPFlashLender.sol";


library TransferHelper {
/// @notice Transfers tokens from msg.sender to a recipient
/// @dev Errors with the underlying revert message if transfer fails
/// @param token The contract address of the token which will be transferred
/// @param to The recipient of the transfer
/// @param value The value of the transfer
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
if (!(success && (data.length == 0 || abi.decode(data, (bool))))) revert(RevertMsgExtractor.getRevertMsg(data));
}
}


contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike {
using TransferHelper for IERC20;
using FunctionCodec for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory);
Expand Down
19 changes: 1 addition & 18 deletions src/erc3156/ERC3156Wrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,19 @@ pragma solidity ^0.8.0;

import { IERC3156FlashLender } from "lib/erc3156/contracts/interfaces/IERC3156FlashLender.sol";
import { IERC3156FlashBorrower } from "lib/erc3156/contracts/interfaces/IERC3156FlashBorrower.sol";
import { RevertMsgExtractor } from "../utils/RevertMsgExtractor.sol";
import { TransferHelper } from "../utils/TransferHelper.sol";
import { FunctionCodec } from "../utils/FunctionCodec.sol";

import { IERC3156PPFlashLender } from "lib/erc3156pp/src/interfaces/IERC3156PPFlashLender.sol";
import { IERC20 } from "lib/erc3156pp/src/interfaces/IERC20.sol";


library TransferHelper {
/// @notice Transfers assets from msg.sender to a recipient
/// @dev Errors with the underlying revert message if transfer fails
/// @param asset The contract address of the asset which will be transferred
/// @param to The recipient of the transfer
/// @param value The value of the transfer
function safeTransfer(
IERC20 asset,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = address(asset).call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
if (!(success && (data.length == 0 || abi.decode(data, (bool))))) revert(RevertMsgExtractor.getRevertMsg(data));
}
}

/**
* @author Alberto Cuesta Cañada
* @dev ERC3156++ Flash Lender that uses ERC3156 Flash Lenders as source of liquidity.
*/
contract ERC3156Wrapper is IERC3156PPFlashLender, IERC3156FlashBorrower {
using TransferHelper for IERC20;
using RevertMsgExtractor for bytes;
using FunctionCodec for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory);
using FunctionCodec for bytes24;

Expand Down
55 changes: 6 additions & 49 deletions src/utils/TransferHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,24 @@
// Taken from https://github.com/Uniswap/uniswap-lib/blob/master/src/libraries/TransferHelper.sol
pragma solidity ^0.8.0;

import "lib/solmate/src/tokens/ERC20.sol";
import { IERC20 } from "lib/erc3156pp/src/interfaces/IERC20.sol";
import "./RevertMsgExtractor.sol";

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
// USDT is a well known token that returns nothing for its transfer, transferFrom, and approve functions
// and part of the reason this library exists
library TransferHelper {
/// @notice Transfers tokens from msg.sender to a recipient
/// @notice Transfers assets from msg.sender to a recipient
/// @dev Errors with the underlying revert message if transfer fails
/// @param token The contract address of the token which will be transferred
/// @param asset The contract address of the asset which will be transferred
/// @param to The recipient of the transfer
/// @param value The value of the transfer
function safeTransfer(
ERC20 token,
IERC20 asset,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(ERC20.transfer.selector, to, value));
if (!(success && _returnTrueOrNothing(data))) revert(RevertMsgExtractor.getRevertMsg(data));
}

/// @notice Approves a spender to transfer tokens from msg.sender
/// @dev Errors with the underlying revert message if transfer fails
/// @param token The contract address of the token which will be approved
/// @param spender The approved spender
/// @param value The value of the allowance
function safeApprove(
ERC20 token,
address spender,
uint256 value
) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(ERC20.approve.selector, spender, value));
if (!(success && _returnTrueOrNothing(data))) revert(RevertMsgExtractor.getRevertMsg(data));
}

/// @notice Transfers tokens from the targeted address to the given destination
/// @dev Errors with the underlying revert message if transfer fails
/// @param token The contract address of the token to be transferred
/// @param from The originating address from which the tokens will be transferred
/// @param to The destination address of the transfer
/// @param value The amount to be transferred
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(ERC20.transferFrom.selector, from, to, value));
if (!(success && _returnTrueOrNothing(data))) revert(RevertMsgExtractor.getRevertMsg(data));
}

/// @notice Transfers ETH to the recipient address
/// @dev Errors with the underlying revert message if transfer fails
/// @param to The destination of the transfer
/// @param value The value to be transferred
function safeTransferETH(address payable to, uint256 value) internal {
(bool success, bytes memory data) = to.call{value: value}(new bytes(0));
if (!success) revert(RevertMsgExtractor.getRevertMsg(data));
}

function _returnTrueOrNothing(bytes memory data) internal pure returns(bool) {
return (data.length == 0 || abi.decode(data, (bool)));
(bool success, bytes memory data) = address(asset).call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
if (!(success && (data.length == 0 || abi.decode(data, (bool))))) revert(RevertMsgExtractor.getRevertMsg(data));
}
}

0 comments on commit 37f5a11

Please sign in to comment.