I'm looking into Uniswap V2 code and found that it uses _safeTransfer
function to transfer ERC20 tokens in the Pair contract.
function _safeTransfer(address token, address to, uint value) private {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');
}
...
function burn(address to) external lock returns (uint amount0, uint amount1) {
...
_safeTransfer(_token0, to, amount0);
...
}
Why doesn't it simply call IERC20(_token).transfer(to, amount0)
?
Best Answer
Because the ERC20 standard kinda sucks, and is unclear about how you should handle non-succeeding token transfers, both reverting and just returning false are technically allowed, so this takes both cases into account
success
is false, the call to the token contract reverted, and we revert the whole transaction,success
is true and there is no return data, the token contract doesnt return anything on transfer and the transfer succeeded (this is technically non compliant with the ERC20 standard, but USDT infamously does that, which is a pain)success
is true but there is return data, we check if it's a bool (if it's not the contract we called isnt compliant with the ERC20 standard and we revert)