Omniscia SaucerSwap Audit
TransferHelper Manual Review Findings
TransferHelper Manual Review Findings
THR-01M: Inexistent Cast of Variable
Type | Severity | Location |
---|---|---|
Standard Conformity | TransferHelper.sol:L27 |
Description:
The value
argument of the IHederaTokenService::transferToken
call needs to be of type int64
, however, no such casting occurs within the TransferHelper::safeTransferFrom
function.
Impact:
As the value
is not cast to its signed counterpart, the IHederaTokenService::transferToken
call may improperly consume the input value
thus causing incorrect transfers to occur.
Example:
25(bool success, bytes memory result) = precompileAddress.call(26 abi.encodeWithSelector(IHederaTokenService.transferToken.selector,27 token, from, to, (value)));
Recommendation:
We advise the value
variable to be safely cast to the int64
data type, ensuring that the invocation style is compliant with the IHederaTokenService
interface.
Alleviation (d8d187efd1fa23b943c82694aaaccb5b9e427096):
The code has been refactored throughout its functions to consistently utilize the IHederaTokenService
when performing token actions and in this refactor, all uint256
to int64
conversions are now performed using safe casting.
As such, we consider this exhibit alleviated.
THR-02M: Inexistent Integration of the Hedera Token Service
Type | Severity | Location |
---|---|---|
Logical Fault | TransferHelper.sol:L46, L61 |
Description:
The referenced functions indicate points where the IHederaTokenService
should be integrated for the contract to function properly, however, they remain as they were in their original implementation.
Impact:
The TransferHelper
contract does not appear to be fully compatible with the Hedera Protocol ecosystem, rendering the AMM system impossible to operate there.
Example:
36/// @notice Transfers tokens from msg.sender to a recipient37/// @dev Errors with ST if transfer fails38/// @param token The contract address of the token which will be transferred39/// @param to The recipient of the transfer40/// @param value The value of the transfer41function safeTransfer(42 address token,43 address to,44 uint256 value45) internal {46 (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));47 require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');48 emit Transfer(address(this), to, value, token);49}50
51/// @notice Approves the stipulated contract to spend the given allowance in the given token52/// @dev Errors with 'SA' if transfer fails53/// @param token The contract address of the token to be approved54/// @param to The target of the approval55/// @param value The amount of the given token the target will be allowed to spend56function safeApprove(57 address token,58 address to,59 uint256 value60) internal {61 (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));62 require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');63 emit Approval(address(this), to, value, token);64}
Recommendation:
We advise them to be updated, properly utilizing the relevant functions of the IHederaTokenService
to ensure that the TransferHelper
contract is properly compatible with the Hedera Protocol ecosystem.
Alleviation (d8d187efd1fa23b943c82694aaaccb5b9e427096):
After discussions with the SaucerSwap team and inspection of the Hedera Improvement Proposals and specifically HIP-218 and HIP-376, we have concluded that a direct invocation of ERC20::transfer
/ ERC20::approve
is equivalent to an invocation of a transfer / approval via the HederaTokenService
.
As such, we consider this exhibit nullified. We would like to note that despite this, the SaucerSwap team has opted to refactor their codebase to consistently utilize the IHederaTokenService
when interacting with tokens thus increasing the standardization of their codebase.