Last updated: March 11, 2025
SCWE-011: Insecure ABI Encoding and Decoding
Stable Version v0.0.1
This content is in the version-(v0.0.1) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
Send Feedback
Relationships
Description
Insecure ABI encoding and decoding occur when a smart contract improperly handles data serialization and deserialization, leading to vulnerabilities such as data corruption, type confusion, or reentrancy attacks. Solidity provides ABI encoding functions like abi.encode()
, abi.encodePacked()
, and abi.decode()
, but improper usage can cause unexpected behavior.
Common issues with insecure ABI handling:
- Collision Risks in abi.encodePacked()
: Multiple concatenated parameters can lead to ambiguous encoding, making it vulnerable to hash collisions.
- Unchecked Decoding: Improper use of abi.decode()
can result in unintended memory corruption or type confusion.
- Lack of Input Validation: Encoding user inputs without verification can introduce security flaws.
- Mismatched Data Types: Decoding an incorrectly encoded data structure can lead to invalid memory access.
- Use
abi.encode()
Instead of abi.encodePacked()
for Hashing: Prevent collision risks by ensuring unique encoding.
- Validate Data Before Decoding: Ensure the encoded data conforms to the expected structure before decoding.
- Match Encoding and Decoding Types: Always use the correct type structure when decoding to avoid unintended behavior.
- Avoid Direct ABI Decoding of External Calls: Use strict validation mechanisms when handling data from external contracts.
Examples
Example of Insecure ABI Encoding:
pragma solidity ^0.8.0;
contract InsecureABI {
function hashValues(string memory str, uint256 num) public pure returns (bytes32) {
return keccak256(abi.encodePacked(str, num)); // ❌ Collision risk
}
}
- In this example,
abi.encodePacked()
creates a collision risk because different input combinations can produce the same hash.
Refactored to Secure ABI Encoding:
pragma solidity ^0.8.0;
contract SecureABI {
function hashValues(string memory str, uint256 num) public pure returns (bytes32) {
return keccak256(abi.encode(str, num)); // ✅ Unique encoding, no collision
}
}
- In this improved version,
abi.encode()
ensures a unique encoding structure, preventing hash collision attacks.