// SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.17; /// @title SecuredTokenTransfer - Secure token transfer abstract contract SecuredTokenTransfer { /// @dev Transfers a token and returns if it was a success /// @param token Token that should be transferred /// @param receiver Receiver to whom the token should be transferred /// @param amount The amount of tokens that should be transferred function transferToken( address token, address receiver, uint256 amount ) internal returns (bool transferred) { require(token != address(0), "token can not be zero address"); require(token.code.length > 0, "token contract doesn't exist"); // 0xa9059cbb - keccack("transfer(address,uint256)") bytes memory data = abi.encodeWithSelector( 0xa9059cbb, receiver, amount ); // solhint-disable-next-line no-inline-assembly assembly { // We write the return value to scratch space. // See https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_memory.html#layout-in-memory let success := call( sub(gas(), 10000), token, 0, add(data, 0x20), mload(data), 0, 0x20 ) switch returndatasize() case 0 { transferred := success } case 0x20 { transferred := iszero(or(iszero(success), iszero(mload(0)))) } default { transferred := 0 } } } }