crytic / crytic/slither

how to read caller function parameters

Open
#2,533 1 comment 0 reactions 0 assignees View on GitHub
question
Dominant language
Python
Stars
6.4k
Forks
1.1k
PR merge metrics
No merged PRs in 30d

Description

### Describe the issue:

There is a smart contract
```
// SPDX-License-Identifier: BSL-1.1

pragma solidity ^0.8.26;

library TransferHelper {
/// @notice Transfers tokens from the targeted address to the given destination
/// @notice Errors with 'STF' 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(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
}

/// @notice Transfers tokens from msg.sender to a recipient
/// @dev Errors with ST 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(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
}
}

contract TokenFee{
address public ETH=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

function transferFee(
uint256 amount,
address token,
address from,
address to
) public returns (uint256) {
uint256 fee = 10000;
if (fee > 0) {
if (token != ETH) {
// ERC20 token
if (from == address(this)) {
TransferHelper.safeTransfer(token, to, fee);
} else {
// safeTransferFrom requires approval
TransferHelper.safeTransferFrom(token, from, to, fee);
}
} else {
require(
from == address(this),
"can only transfer eth from the router address"
);

// Native ether
(bool success, ) = to.call{value: fee}("");
require(success, "transfer failed in transferFee");
}
return fee;
} else {
return 0;
}
}
}

```

I use slither in python, to detect the safeTransferFrom whether limit the from parameter.
This is my code

```
from slither.slither import Slither
file='TokenFee'
ctsl=Slither(file,solc_args="--optimize --optimize-runs 200")
ct=ctsl.contracts
for contract in ct:
funcs=contract.functions
for func in funcs:
fps=[]
for fp in func.parameters:
fps.append(fp.name)
for scs in func.all_high_level_calls():
if str(scs[1])=='safeTransferFrom':

frm=str(scs[1].parameters[1])
t=str(scs[1].parameters[2])
if (frm in fps) and (t in fps):
print('vuln')
```

But I found scs[1].parameters are parameters 'token' 'from','to','value' which are in TransferHelper smart contract's safeTransferFrom, not 'token','from','to','fee' in TokenFee contract's safeTransferFrom. How to get the right parameter 'token','from','to','fee'?

### Code example to reproduce the issue:

```
from slither.slither import Slither
file='TokenFee'
ctsl=Slither(file,solc_args="--optimize --optimize-runs 200")
ct=ctsl.contracts
for contract in ct:
funcs=contract.functions
for func in funcs:
fps=[]
for fp in func.parameters:
fps.append(fp.name)
for scs in func.all_high_level_calls():
if str(scs[1])=='safeTransferFrom':

frm=str(scs[1].parameters[1])
t=str(scs[1].parameters[2])
if (frm in fps) and (t in fps):
print('vuln')
```

### Version:

0.10.3

### Relevant log output:

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.