Skip to content

Commit fd926e8

Browse files
authored
Merge pull request #5 from forefy/feature
Templates Contribution by @scab24
2 parents e91d00b + 8acdff4 commit fd926e8

24 files changed

+280
-1
lines changed

eburger/templates/emit_after_external_call.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Emit After External Call"
34
severity: "Low"
45
precision: "Medium"

eburger/templates/missing_reentrancy_guard.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.6
2+
author: "@forefy"
23
name: "Missing Reentracy Guard"
34
severity: "Low"
45
precision: "Low"

eburger/templates/missing_zero_address_check.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Missing Zero Address Check"
34
severity: "Low"
45
precision: "Medium"

eburger/templates/modifier_without_proper_enforcement.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Modifier Without Proper Enforcement"
34
severity: "High"
45
precision: "Low"

eburger/templates/tx_origin_used_for_access_control.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "tx.origin Used for Access Control"
34
severity: "Low"
45
precision: "Medium"

eburger/templates/unbounded_loop.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Unbounded Loop"
34
severity: "Low"
45
precision: "Low"

eburger/templates/unchecked_call_return.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Unchecked Call Return"
34
severity: "Low"
45
precision: "Low"

eburger/templates/unchecked_chainlink_oracle_price.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Unchecked Chainlink Oracle Price"
34
severity: "Medium"
45
precision: "Medium"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
version: 1.0.6
2+
author: "@Seecoalba"
3+
name: "Unspecific Solidity Pragma Detector"
4+
severity: "Low"
5+
precision: "High"
6+
description: "Detects the usage of unspecific compiler pragmas that allow for a broader range of compiler versions than necessary, which can lead to unintended behavior or compiler warnings/errors with newer versions."
7+
impact: "Unpredictable behavior due to differences in compiler versions."
8+
action-items:
9+
- "Specify a more precise range of compiler versions in the pragma statement to ensure consistent behavior across different environments."
10+
references:
11+
- "https://docs.soliditylang.org/en/latest/layout-of-source-files.html#version-pragma"
12+
reports:
13+
- "https://github.com/Steemhunt/mint.club-v2-contract/issues/36"
14+
- "https://solodit.xyz/issues/n-06-inconsistent-method-of-specifying-a-floating-pragma-code4rena-ens-ens-contest-git"
15+
vulnerable_contracts:
16+
- "../vulnerable_contracts/unspecific_pragma_detector.sol"
17+
python: |
18+
results = []
19+
pragma_directives = get_nodes_by_types(ast_data, "PragmaDirective")
20+
for directive in pragma_directives:
21+
literals = directive.get('literals', [])
22+
pragma_string = ''.join(literals)
23+
if '^' in pragma_string or '>' in pragma_string:
24+
results.append(directive)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
version: 1.0.6
2+
author: "@Seecoalba"
3+
name: "Unverified from Address Usage in transferFrom"
4+
severity: "Low"
5+
precision: "Medium"
6+
description: "Employing an unverified from address in transferFrom or safeTransferFrom operations poses a substantial risk of fund loss. This risk arises from the potential for any party to execute token transfers from the specified from address, contingent upon having received adequate approval."
7+
impact: "Unauthorized token transactions emanating from the specified from address, if it has been authorized, which could lead to significant asset depletion."
8+
action-items:
9+
- "Verify that the from address used in calls to transferFrom or safeTransferFrom is validated properly."
10+
references:
11+
- "https://solidity.readthedocs.io/en/latest/types.html#members-of-addresses"
12+
reports: []
13+
vulnerable_contracts:
14+
- "../vulnerable_contracts/unverified_from_address_in_transfer/"
15+
python: |
16+
results = []
17+
# Retrieve all function call nodes from the AST.
18+
function_calls = get_nodes_by_types(ast_data, ["FunctionCall"])
19+
20+
# Define a function to check the validity of the 'from' argument in a function call.
21+
def check_argument_validity(function_call):
22+
# Extract arguments from the function call.
23+
args = function_call.get("arguments", [])
24+
# Determine the index of the 'from' argument based on the number of arguments.
25+
arg_index = 0 if len(args) == 3 else 1 if len(args) == 4 else -1
26+
27+
# Ensure the arg_index is valid.
28+
if arg_index not in [-1, len(args)]:
29+
# Get the 'from' argument based on its index.
30+
arg = args[arg_index]
31+
# If the 'from' argument is accessed via a member access,
32+
# verify if it securely originates from msg.sender.
33+
if arg.get("nodeType") == "MemberAccess":
34+
base_expr = arg.get("expression", {})
35+
if arg.get("memberName") == "sender" and base_expr.get("name") == "msg":
36+
return False
37+
# If the 'from' argument is a result of a function call,
38+
# verify if it safely refers to 'this'.
39+
elif arg.get("nodeType") == "FunctionCall":
40+
expr = arg.get("expression", {})
41+
if expr.get("typeName", {}).get("name") == "address" and \
42+
arg.get("arguments", [])[0].get("name") == "this":
43+
return False
44+
# Consider the call valid if none of the above conditions are met.
45+
return True
46+
47+
# Iterate through each function call found in the AST.
48+
for function_call in function_calls:
49+
# Extract the name of the function being called.
50+
function_name = function_call.get("expression", {}).get("memberName", "")
51+
# If the function is 'transferFrom' or 'safeTransferFrom', and the 'from' argument is considered valid,
52+
# add the function call to the results.
53+
if function_name in ["transferFrom", "safeTransferFrom"] and check_argument_validity(function_call):
54+
results.append(function_call)

eburger/templates/use_of_approve_with_max_allowance.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Use of approve with Max Allowance"
34
severity: "Low"
45
precision: "High"
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
version: 1.0.6
2+
author: "@Seecoalba"
3+
name: "Use of encodedPacked with Dynamic Data Types"
4+
severity: "Low"
5+
precision: "Medium"
6+
description: "It's recommended to avoid `abi.encodePacked()` for dynamic data types before hashing operations, like with `keccak256()`."
7+
impact: "Potential triggering of hash collisions."
8+
action-items:
9+
- "Unless encodePacked is necessary, switch from `abi.encodePacked()` to `abi.encode()` in scenarios involving dynamic types ahead of hash function usage."
10+
- "Consider `bytes.concat()` for concatenating strings or bytes, as a preferable method over `abi.encodePacked()`."
11+
references:
12+
- "https://docs.soliditylang.org/en/v0.8.13/abi-spec.html#non-standard-packed-mode"
13+
- "https://ethereum.stackexchange.com/questions/30912/how-to-compare-strings-in-solidity#answer-82739"
14+
reports:
15+
- "https://github.com/code-423n4/2023-11-shellprotocol/blob/8c6c6a33c817b588567a5b6a65bdda72d905941f/4naly3er-report.md?plain=1#L330"
16+
- "https://solodit.xyz/issues/l-07-code4rena-backd-backd-contest-git"
17+
vulnerable_contracts:
18+
"../vulnerable_contracts/use_of_encodepacked.sol"
19+
python: |
20+
results = []
21+
nodes = get_nodes_by_types(ast_data, ["MemberAccess"])
22+
for node in nodes:
23+
if node.get("memberName") == "encodePacked":
24+
uses_dynamic_data_types = False
25+
problematic_type_string_patterns = ["bytes memory", "[] memory", "string memory"]
26+
argument_types = node.get("argumentTypes", [])
27+
for argument_type in argument_types:
28+
type_string = argument_type.get("typeString", None)
29+
30+
pattern_match = False
31+
for pattern in problematic_type_string_patterns:
32+
if pattern in type_string:
33+
pattern_match = True
34+
break
35+
36+
if pattern_match:
37+
uses_dynamic_data_types = True
38+
break
39+
40+
if uses_dynamic_data_types:
41+
results.append(node)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
version: 1.0.6
2+
author: "@Seecoalba"
3+
name: "Use of SafeTransferLib"
4+
severity: "Low"
5+
precision: "High"
6+
description: "A notable distinction exists between Solmate's SafeTransferLib and OpenZeppelin's SafeERC20 library: the latter ensures the target is indeed a contract, a step omitted by Solmate's library. It is crucial to note from the documentation that the functions within this library do not verify the existence of code at the token's address, leaving it up to the user to ensure validity."
7+
impact: "Omitting checks for the token contract's presence could lead to tokens being sent to addresses that cannot interact with them properly, potentially resulting in the loss of assets or unsuccessful transactions."
8+
action-items:
9+
- "Consider leveraging OpenZeppelin's SafeERC20 for ERC20 token interactions to incorporate contract presence verification."
10+
references:
11+
- "https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol#L9"
12+
reports:
13+
- "https://github.com/code-423n4/2023-01-astaria-findings/blob/8059d5e7c4b3b7155259c7990226c91dc2f375fb/data/btk-Q.md?plain=1#L11"
14+
- "https://solodit.xyz/issues/l-04-solmates-code4rena-caviar-caviar-contest-git"
15+
- "https://solodit.xyz/issues/l-03-solmates-safetransferlib-doesnt-check-whether-the-erc20-contract-exists-code4rena-redacted-cartel-redacted-cartel-contest-git"
16+
vulnerable_contracts:
17+
- "../vulnerable_contracts/use_of_safetransferlib/"
18+
python: |
19+
results = []
20+
import_directives = get_nodes_by_types(ast_data, "ImportDirective")
21+
for directive in import_directives:
22+
absolute_path = directive.get("absolutePath", "")
23+
if "solmate" in absolute_path and "SafeTransferLib" in absolute_path:
24+
results.append(directive)

eburger/templates/use_of_transfer_or_send_on_payable.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Use of transfer or send on a payable address"
34
severity: "Medium"
45
precision: "Medium"

eburger/templates/use_of_unsafe_mint.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 1.0.5
2+
author: "@forefy"
23
name: "Usage of unsafe _mint"
34
severity: "Medium"
45
precision: "High"

vulnerable_contracts/missing_reentrancy_guard/src/missing_reentrancy_guard.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity 0.8.20;
2+
pragma solidity ^0.8.20;
33

44
contract ProblematicContract {
55
mapping(address => uint) public balances;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
contract OutOfControlContract {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Unverified from Address Usage in transferFrom
2+
An intentionally vulnerable Foundry project.
3+
4+
```bash
5+
tree
6+
.
7+
├── foundry.toml # Contract's root
8+
├── src/
9+
│   └── unverified_from_address_in_transfer.sol # Vulnerable contract
10+
```
11+
## Usage
12+
13+
### Install dependencies
14+
```bash
15+
forge install OpenZeppelin/openzeppelin-contracts --no-git
16+
```
17+
18+
### Build
19+
20+
```bash
21+
forge build
22+
```
23+
24+
### Test
25+
26+
```bash
27+
forge test
28+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[profile.default]
2+
src = "src"
3+
out = "out"
4+
libs = ["lib"]
5+
6+
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.20;
3+
4+
import "../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
5+
import "../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
6+
7+
contract InsecureTokenTransfer {
8+
using SafeERC20 for IERC20;
9+
10+
IERC20 private _token;
11+
12+
constructor(IERC20 tokenAddress) {
13+
_token = tokenAddress;
14+
}
15+
16+
function insecureTransfer(address sender, address recipient, uint256 value) public {
17+
_token.transferFrom(sender, recipient, value);
18+
}
19+
20+
// Methods below are intended to show secure use cases
21+
function secureTransferTo(address recipient, uint256 value) public {
22+
// transferring from the function caller can give more control over the from address
23+
_token.transferFrom(msg.sender, recipient, value);
24+
}
25+
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.20;
3+
4+
contract BadCode {
5+
function hashCollision1(string memory input1, string memory input2) public pure returns (bytes32) {
6+
return keccak256(abi.encodePacked(input1, input2));
7+
}
8+
9+
function hashCollision2(bytes memory input1, uint256[] memory input2) public pure returns (bytes32) {
10+
return keccak256(abi.encodePacked(input1, input2));
11+
}
12+
13+
function noHashCollision(string memory input1, string memory input2) public pure returns (bytes32) {
14+
return keccak256(abi.encode(input1, input2));
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Use of SafeTransferLib
2+
An intentionally vulnerable Foundry project.
3+
4+
```bash
5+
tree
6+
.
7+
├── foundry.toml # Contract's root
8+
├── src/
9+
│   └── use_of_safetransferlib.sol # Vulnerable contract
10+
```
11+
## Usage
12+
13+
### Install dependencies
14+
```bash
15+
forge install transmissions11/solmate --no-git
16+
```
17+
18+
### Build
19+
20+
```bash
21+
forge build
22+
```
23+
24+
### Test
25+
26+
```bash
27+
forge test
28+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[profile.default]
2+
src = "src"
3+
out = "out"
4+
libs = ["lib"]
5+
6+
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.20;
3+
import {ERC20, SafeTransferLib} from "../lib/solmate/src/utils/SafeTransferLib.sol";
4+
5+
contract NotSoSafe {
6+
using SafeTransferLib for ERC20;
7+
8+
function sendSomeTokens(ERC20 token, address to, uint256 amount) external {
9+
token.safeTransfer(to, amount);
10+
}
11+
}

0 commit comments

Comments
 (0)